diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index 202c759c..62f3d8da 100644 --- a/.claude/skills/form-compile/scripts/form-compile.ps1 +++ b/.claude/skills/form-compile/scripts/form-compile.ps1 @@ -1,4 +1,4 @@ -# form-compile v1.94 — Compile 1C managed form from JSON or object metadata +# form-compile v1.95 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, @@ -2153,6 +2153,28 @@ function Emit-SingleType { return } + # Спец-типы платформы с собственным namespace (объявляется ЛОКАЛЬНО на ). + # Префикс d5p1 неоднозначен (5 разных URI), поэтому маппинг по полному значению типа. + # К таким типам привязаны спец-поля: mxl→SpreadSheetDocumentField, fd→FormattedDocumentField, + # d5p1:TextDocument→TextDocumentField, pdfdoc→PDF, pl→Planner, chart/geo/graphscheme/data-analysis. + $specialTypeNs = @{ + "mxl:SpreadsheetDocument" = "http://v8.1c.ru/8.2/data/spreadsheet" + "fd:FormattedDocument" = "http://v8.1c.ru/8.2/data/formatted-document" + "d5p1:TextDocument" = "http://v8.1c.ru/8.1/data/txtedt" + "d5p1:Chart" = "http://v8.1c.ru/8.2/data/chart" + "d5p1:GanttChart" = "http://v8.1c.ru/8.2/data/chart" + "d5p1:FlowchartContextType" = "http://v8.1c.ru/8.2/data/graphscheme" + "d5p1:DataAnalysisTimeIntervalUnitType" = "http://v8.1c.ru/8.2/data/data-analysis" + "d5p1:GeographicalSchema" = "http://v8.1c.ru/8.2/data/geo" + "pdfdoc:PDFDocument" = "http://v8.1c.ru/8.3/data/pdf" + "pl:Planner" = "http://v8.1c.ru/8.3/data/planner" + } + if ($specialTypeNs.ContainsKey($typeStr)) { + $pref = $typeStr.Substring(0, $typeStr.IndexOf(':')) + X "$indent$typeStr" + return + } + # Fallback with validation if ($script:knownInvalidTypes.ContainsKey($typeStr)) { throw "Invalid form attribute type '$typeStr': $($script:knownInvalidTypes[$typeStr])" @@ -2524,6 +2546,19 @@ function Emit-Element { "SearchControl" = "searchControl" "управлениеПоиском" = "searchControl" "Управление поиском" = "searchControl" + # Спец-поля (документ/датчик) — XML-имя/рус. → канон + "SpreadSheetDocumentField" = "spreadsheet" + "ПолеТабличногоДокумента" = "spreadsheet" + "HTMLDocumentField" = "html" + "ПолеHTMLДокумента" = "html" + "TextDocumentField" = "textDoc" + "ПолеТекстовогоДокумента" = "textDoc" + "FormattedDocumentField" = "formattedDoc" + "ПолеФорматированногоДокумента" = "formattedDoc" + "ProgressBarField" = "progressBar" + "ПолеИндикатора" = "progressBar" + "TrackBarField" = "trackBar" + "ПолеПолосыРегулирования" = "trackBar" } foreach ($pair in $synonyms.GetEnumerator()) { if ($null -ne $el.PSObject.Properties[$pair.Key] -and $null -eq $el.PSObject.Properties[$pair.Value]) { @@ -2556,7 +2591,7 @@ function Emit-Element { # у popup/button/cmdBar. Тип-ключ владельца (popup/button/…) должен выиграть. # pages/page ПЕРЕД group: у Page/Pages ключ 'group' — это направление раскладки детей # (Horizontal), а не тип UsualGroup. Реальная UsualGroup ключа page/pages не несёт. - foreach ($key in @("columnGroup","buttonGroup","pages","page","group","input","check","radio","label","labelField","table","button","calendar","cmdBar","popup","searchString","viewStatus","searchControl","picField","picture")) { + foreach ($key in @("columnGroup","buttonGroup","pages","page","group","input","check","radio","label","labelField","table","button","calendar","cmdBar","popup","searchString","viewStatus","searchControl","picField","picture","spreadsheet","html","textDoc","formattedDoc","progressBar","trackBar")) { if ($el.$key -ne $null) { $typeKey = $key break @@ -2573,6 +2608,12 @@ function Emit-Element { # type keys "group"=1;"columnGroup"=1;"buttonGroup"=1;"input"=1;"check"=1;"radio"=1;"label"=1;"labelField"=1;"table"=1;"pages"=1;"page"=1 "button"=1;"picture"=1;"picField"=1;"calendar"=1;"cmdBar"=1;"popup"=1 + # спец-поля (документ/датчик) — тип-ключи + типоспец. скаляры + "spreadsheet"=1;"html"=1;"textDoc"=1;"formattedDoc"=1;"progressBar"=1;"trackBar"=1 + "showPercent"=1;"largeStep"=1;"markingStep"=1;"step"=1 + "horizontalScrollBar"=1;"viewScalingMode"=1;"output"=1;"selectionShowMode"=1;"protection"=1 + "edit"=1;"showGrid"=1;"showGroups"=1;"showHeaders"=1;"showRowAndColumnNames"=1;"showCellNames"=1 + "pointerType"=1;"drawingSelectionShowMode"=1;"warningOnEditRepresentation"=1;"markingAppearance"=1 # columnGroup-specific "showInHeader"=1 # radio-specific @@ -2680,6 +2721,12 @@ function Emit-Element { "calendar" { Emit-Calendar -el $el -name $name -id $id -indent $indent } "cmdBar" { Emit-CommandBar -el $el -name $name -id $id -indent $indent } "popup" { Emit-Popup -el $el -name $name -id $id -indent $indent } + "spreadsheet" { Emit-SimpleField -el $el -name $name -id $id -indent $indent -xmlTag "SpreadSheetDocumentField" -typeKey "spreadsheet" } + "html" { Emit-SimpleField -el $el -name $name -id $id -indent $indent -xmlTag "HTMLDocumentField" -typeKey "html" } + "textDoc" { Emit-SimpleField -el $el -name $name -id $id -indent $indent -xmlTag "TextDocumentField" -typeKey "textDoc" } + "formattedDoc" { Emit-SimpleField -el $el -name $name -id $id -indent $indent -xmlTag "FormattedDocumentField" -typeKey "formattedDoc" } + "progressBar" { Emit-SimpleField -el $el -name $name -id $id -indent $indent -xmlTag "ProgressBarField" -typeKey "progressBar" } + "trackBar" { Emit-SimpleField -el $el -name $name -id $id -indent $indent -xmlTag "TrackBarField" -typeKey "trackBar" } } } @@ -2732,7 +2779,8 @@ function Emit-CommonElementProps { $siv = if ($el.skipOnInput -eq $true) { 'true' } else { 'false' } X "$indent$siv" } - if ($el.enableStartDrag -eq $true) { X "$indenttrue" } + # EnableStartDrag — фактическое значение (платформа эмитит и явный false, напр. SpreadSheet) + if ($null -ne $el.enableStartDrag) { X "$indent$(if ($el.enableStartDrag){'true'}else{'false'})" } if ($el.fileDragMode) { X "$indent$($el.fileDragMode)" } # Cell-свойства поля в таблице (общие для Input/Label/Picture/CheckBox): захват «как есть» foreach ($p in @(@('showInHeader','ShowInHeader'), @('showInFooter','ShowInFooter'), @('autoCellHeight','AutoCellHeight'))) { @@ -2849,6 +2897,23 @@ $script:genericScalars = @( @{ Tag='CreateButton'; Key='createButton'; Kind='bool' } @{ Tag='FixingInTable'; Key='fixingInTable'; Kind='value' } @{ Tag='VerticalSpacing'; Key='verticalSpacing'; Kind='value' } + # Спец-поля (документ/датчик) — типоспец. enum/bool скаляры pass-through + @{ Tag='HorizontalScrollBar'; Key='horizontalScrollBar'; Kind='value' } + @{ Tag='ViewScalingMode'; Key='viewScalingMode'; Kind='value' } + @{ Tag='Output'; Key='output'; Kind='value' } + @{ Tag='SelectionShowMode'; Key='selectionShowMode'; Kind='value' } + @{ Tag='PointerType'; Key='pointerType'; Kind='value' } + @{ Tag='DrawingSelectionShowMode'; Key='drawingSelectionShowMode'; Kind='value' } + @{ Tag='WarningOnEditRepresentation'; Key='warningOnEditRepresentation'; Kind='value' } + @{ Tag='MarkingAppearance'; Key='markingAppearance'; Kind='value' } + @{ Tag='Protection'; Key='protection'; Kind='bool' } + @{ Tag='Edit'; Key='edit'; Kind='bool' } + @{ Tag='ShowGrid'; Key='showGrid'; Kind='bool' } + @{ Tag='ShowGroups'; Key='showGroups'; Kind='bool' } + @{ Tag='ShowHeaders'; Key='showHeaders'; Kind='bool' } + @{ Tag='ShowRowAndColumnNames'; Key='showRowAndColumnNames'; Kind='bool' } + @{ Tag='ShowCellNames'; Key='showCellNames'; Kind='bool' } + @{ Tag='ShowPercent'; Key='showPercent'; Kind='bool' } ) function Emit-GenericScalars { @@ -3809,7 +3874,7 @@ function Emit-Table { if ($el.verticalLines -eq $false) { X "$innerfalse" } if ($el.horizontalLines -eq $false) { X "$innerfalse" } if ($el.initialTreeView) { X "$inner$($el.initialTreeView)" } - if ($el.enableDrag -eq $true) { X "$innertrue" } + if ($null -ne $el.enableDrag) { X "$inner$(if ($el.enableDrag){'true'}else{'false'})" } if ($el.rowPictureDataPath) { X "$inner$($el.rowPictureDataPath)" } if ($el.rowsPicture) { # Строка = Ref (LoadTransparent дефолт false); объект {src, loadTransparent} → факт. значение @@ -4153,6 +4218,45 @@ function Emit-Calendar { X "$indent" } +# Спец-поля «документ/датчик» (SpreadSheet/HTML/Text/Formatted/ProgressBar/TrackBar): +# единый скелет поля (path/title/flags/titleLocation/editMode/layout/companions/events). +# Типоспец. enum/bool скаляры — через generic (Emit-Layout→Emit-GenericScalars); +# числовые скаляры датчиков (min/max/шаги) — без xsi:type (≠ типизированных InputField). +# enableDrag/enableStartDrag — общие (Emit-CommonElementProps), фактическое значение. +function Emit-SimpleField { + param($el, [string]$name, [int]$id, [string]$indent, [string]$xmlTag, [string]$typeKey) + + X "$indent<$xmlTag name=`"$name`" id=`"$id`"$(DI-Attr $el)>" + $inner = "$indent`t" + + if ($el.path) { X "$inner$($el.path)" } + Emit-Title -el $el -name $name -indent $inner -auto:(-not $el.path) + Emit-CommonFlags -el $el -indent $inner + if ($el.titleLocation) { X "$inner$(Map-TitleLoc "$($el.titleLocation)")" } + if ($el.editMode) { X "$inner$($el.editMode)" } + + Emit-Layout -el $el -indent $inner + + # EnableDrag — фактическое значение (SpreadSheet; платформа эмитит явный false). enableStartDrag — через Emit-Layout. + if ($null -ne $el.enableDrag) { X "$inner$(if ($el.enableDrag){'true'}else{'false'})" } + + # Датчики (ProgressBar/TrackBar) — числовые скаляры (без xsi:type) + foreach ($p in @(@('minValue','MinValue'), @('maxValue','MaxValue'), @('largeStep','LargeStep'), @('markingStep','MarkingStep'), @('step','Step'))) { + if ($null -ne $el.($p[0])) { X "$inner<$($p[1])>$($el.($p[0]))" } + } + + # Оформление (цвета/шрифты/граница) — перед компаньонами + Emit-Appearance -el $el -indent $inner -profile 'field' + + # Companions + Emit-CompanionPanel -tag "ContextMenu" -name "${name}КонтекстноеМеню" -indent $inner -panel $el.contextMenu + Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner -content $el.extendedTooltip + + Emit-Events -el $el -elementName $name -indent $inner -typeKey $typeKey + + X "$indent" +} + function Emit-CommandBar { param($el, [string]$name, [int]$id, [string]$indent) diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index 2d31454b..34840d66 100644 --- a/.claude/skills/form-compile/scripts/form-compile.py +++ b/.claude/skills/form-compile/scripts/form-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-compile v1.94 — Compile 1C managed form from JSON or object metadata +# form-compile v1.95 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -1829,6 +1829,12 @@ KNOWN_KEYS = { "choiceForm", "choiceHistoryOnInput", "footerDataPath", "minValue", "maxValue", # Button — пометка toggle-кнопки "checked", + # спец-поля (документ/датчик) — тип-ключи + типоспец. скаляры + "spreadsheet", "html", "textDoc", "formattedDoc", "progressBar", "trackBar", + "showPercent", "largeStep", "markingStep", "step", + "horizontalScrollBar", "viewScalingMode", "output", "selectionShowMode", "protection", + "edit", "showGrid", "showGroups", "showHeaders", "showRowAndColumnNames", "showCellNames", + "pointerType", "drawingSelectionShowMode", "warningOnEditRepresentation", "markingAppearance", } # picture/picField — НИЗКИЙ приоритет: 'picture' это и тип (PictureDecoration), и свойство-иконка @@ -1836,7 +1842,8 @@ KNOWN_KEYS = { # pages/page ПЕРЕД group: у Page/Pages ключ 'group' — это направление раскладки детей # (Horizontal), а не тип UsualGroup. Реальная UsualGroup ключа page/pages не несёт. TYPE_KEYS = ["columnGroup", "buttonGroup", "pages", "page", "group", "input", "check", "radio", "label", "labelField", "table", - "button", "calendar", "cmdBar", "popup", "searchString", "viewStatus", "searchControl", "picField", "picture"] + "button", "calendar", "cmdBar", "popup", "searchString", "viewStatus", "searchControl", "picField", "picture", + "spreadsheet", "html", "textDoc", "formattedDoc", "progressBar", "trackBar"] # Synonyms: model often writes XML name or Russian (ПолеПереключателя/RadioButtonField → radio) ELEMENT_TYPE_SYNONYMS = { @@ -1889,6 +1896,19 @@ ELEMENT_TYPE_SYNONYMS = { "SearchControl": "searchControl", "управлениеПоиском": "searchControl", "Управление поиском": "searchControl", + # Спец-поля (документ/датчик) — XML-имя/рус. → канон + "SpreadSheetDocumentField": "spreadsheet", + "ПолеТабличногоДокумента": "spreadsheet", + "HTMLDocumentField": "html", + "ПолеHTMLДокумента": "html", + "TextDocumentField": "textDoc", + "ПолеТекстовогоДокумента": "textDoc", + "FormattedDocumentField": "formattedDoc", + "ПолеФорматированногоДокумента": "formattedDoc", + "ProgressBarField": "progressBar", + "ПолеИндикатора": "progressBar", + "TrackBarField": "trackBar", + "ПолеПолосыРегулирования": "trackBar", } # Тип-синонимы, применяемые ТОЛЬКО к строковому значению (имя элемента); объект/массив @@ -2511,8 +2531,9 @@ def emit_common_element_props(lines, el, indent): if 'skipOnInput' in el and el['skipOnInput'] is not None: siv = 'true' if el['skipOnInput'] is True else 'false' lines.append(f"{indent}{siv}") - if el.get('enableStartDrag') is True: - lines.append(f"{indent}true") + # EnableStartDrag — фактическое значение (платформа эмитит и явный false, напр. SpreadSheet) + if el.get('enableStartDrag') is not None: + lines.append(f'{indent}{"true" if el["enableStartDrag"] else "false"}') if el.get('fileDragMode'): lines.append(f"{indent}{el['fileDragMode']}") # Cell-свойства поля в таблице (общие для Input/Label/Picture/CheckBox): захват «как есть» @@ -2697,6 +2718,23 @@ GENERIC_SCALARS = [ ('CreateButton', 'createButton', 'bool'), ('FixingInTable', 'fixingInTable', 'value'), ('VerticalSpacing', 'verticalSpacing', 'value'), + # Spec-fields (document/gauge) - type-specific enum/bool scalars pass-through + ('HorizontalScrollBar', 'horizontalScrollBar', 'value'), + ('ViewScalingMode', 'viewScalingMode', 'value'), + ('Output', 'output', 'value'), + ('SelectionShowMode', 'selectionShowMode', 'value'), + ('PointerType', 'pointerType', 'value'), + ('DrawingSelectionShowMode', 'drawingSelectionShowMode', 'value'), + ('WarningOnEditRepresentation', 'warningOnEditRepresentation', 'value'), + ('MarkingAppearance', 'markingAppearance', 'value'), + ('Protection', 'protection', 'bool'), + ('Edit', 'edit', 'bool'), + ('ShowGrid', 'showGrid', 'bool'), + ('ShowGroups', 'showGroups', 'bool'), + ('ShowHeaders', 'showHeaders', 'bool'), + ('ShowRowAndColumnNames', 'showRowAndColumnNames', 'bool'), + ('ShowCellNames', 'showCellNames', 'bool'), + ('ShowPercent', 'showPercent', 'bool'), ] @@ -2971,6 +3009,27 @@ def emit_single_type(lines, type_str, indent): lines.append(f'{indent}cfg:{type_str}') return + # Спец-типы платформы с собственным namespace (объявляется ЛОКАЛЬНО на ). + # Префикс d5p1 неоднозначен (5 разных URI), поэтому маппинг по полному значению типа. + # К таким типам привязаны спец-поля: mxl→SpreadSheetDocumentField, fd→FormattedDocumentField, + # d5p1:TextDocument→TextDocumentField, pdfdoc→PDF, pl→Planner, chart/geo/graphscheme/data-analysis. + special_type_ns = { + "mxl:SpreadsheetDocument": "http://v8.1c.ru/8.2/data/spreadsheet", + "fd:FormattedDocument": "http://v8.1c.ru/8.2/data/formatted-document", + "d5p1:TextDocument": "http://v8.1c.ru/8.1/data/txtedt", + "d5p1:Chart": "http://v8.1c.ru/8.2/data/chart", + "d5p1:GanttChart": "http://v8.1c.ru/8.2/data/chart", + "d5p1:FlowchartContextType": "http://v8.1c.ru/8.2/data/graphscheme", + "d5p1:DataAnalysisTimeIntervalUnitType": "http://v8.1c.ru/8.2/data/data-analysis", + "d5p1:GeographicalSchema": "http://v8.1c.ru/8.2/data/geo", + "pdfdoc:PDFDocument": "http://v8.1c.ru/8.3/data/pdf", + "pl:Planner": "http://v8.1c.ru/8.3/data/planner", + } + if type_str in special_type_ns: + pref = type_str.split(':', 1)[0] + lines.append(f'{indent}{type_str}') + return + # Fallback with validation if type_str in KNOWN_INVALID_TYPES: raise ValueError(f"Invalid form attribute type '{type_str}': {KNOWN_INVALID_TYPES[type_str]}") @@ -3068,6 +3127,12 @@ def emit_element(lines, el, indent, in_cmd_bar=False): 'searchString': lambda lines, el, name, eid, indent: emit_addition(lines, el, name, eid, 'searchString', indent), 'viewStatus': lambda lines, el, name, eid, indent: emit_addition(lines, el, name, eid, 'viewStatus', indent), 'searchControl': lambda lines, el, name, eid, indent: emit_addition(lines, el, name, eid, 'searchControl', indent), + 'spreadsheet': lambda lines, el, name, eid, indent: emit_simple_field(lines, el, name, eid, indent, 'SpreadSheetDocumentField', 'spreadsheet'), + 'html': lambda lines, el, name, eid, indent: emit_simple_field(lines, el, name, eid, indent, 'HTMLDocumentField', 'html'), + 'textDoc': lambda lines, el, name, eid, indent: emit_simple_field(lines, el, name, eid, indent, 'TextDocumentField', 'textDoc'), + 'formattedDoc': lambda lines, el, name, eid, indent: emit_simple_field(lines, el, name, eid, indent, 'FormattedDocumentField', 'formattedDoc'), + 'progressBar': lambda lines, el, name, eid, indent: emit_simple_field(lines, el, name, eid, indent, 'ProgressBarField', 'progressBar'), + 'trackBar': lambda lines, el, name, eid, indent: emit_simple_field(lines, el, name, eid, indent, 'TrackBarField', 'trackBar'), } emitter = emitters.get(type_key) @@ -3519,8 +3584,8 @@ def emit_table(lines, el, name, eid, indent): lines.append(f'{inner}false') if el.get('initialTreeView'): lines.append(f'{inner}{el["initialTreeView"]}') - if el.get('enableDrag') is True: - lines.append(f'{inner}true') + if el.get('enableDrag') is not None: + lines.append(f'{inner}{"true" if el["enableDrag"] else "false"}') if el.get('rowPictureDataPath'): lines.append(f'{inner}{el["rowPictureDataPath"]}') if el.get('rowsPicture'): @@ -3805,6 +3870,45 @@ def emit_picture_field(lines, el, name, eid, indent): lines.append(f'{indent}') +def emit_simple_field(lines, el, name, eid, indent, xml_tag, type_key): + # Спец-поля "документ/датчик" (SpreadSheet/HTML/Text/Formatted/ProgressBar/TrackBar): + # единый скелет поля. Типоспец. enum/bool скаляры — через generic (emit_layout); + # числовые скаляры датчиков (min/max/шаги) — без xsi:type; enableDrag — фактическое значение. + lines.append(f'{indent}<{xml_tag} name="{name}" id="{eid}"{di_attr(el)}>') + inner = f'{indent}\t' + + if el.get('path'): + lines.append(f'{inner}{el["path"]}') + emit_title(lines, el, name, inner, auto=not el.get('path')) + emit_common_flags(lines, el, inner) + if el.get('titleLocation'): + lines.append(f'{inner}{map_title_loc(el["titleLocation"])}') + if el.get('editMode'): + lines.append(f'{inner}{el["editMode"]}') + + emit_layout(lines, el, inner) + + # EnableDrag — фактическое значение (SpreadSheet; платформа эмитит явный false). enableStartDrag — через emit_layout. + if el.get('enableDrag') is not None: + lines.append(f'{inner}{"true" if el["enableDrag"] else "false"}') + + # Датчики (ProgressBar/TrackBar) — числовые скаляры (без xsi:type) + for key, tag in (('minValue', 'MinValue'), ('maxValue', 'MaxValue'), ('largeStep', 'LargeStep'), ('markingStep', 'MarkingStep'), ('step', 'Step')): + if el.get(key) is not None: + lines.append(f'{inner}<{tag}>{el[key]}') + + # Оформление (цвета/шрифты/граница) — перед компаньонами + emit_appearance(lines, el, inner, 'field') + + # Companions + emit_companion_panel(lines, 'ContextMenu', f'{name}КонтекстноеМеню', inner, el.get('contextMenu')) + emit_companion(lines, 'ExtendedTooltip', f'{name}РасширеннаяПодсказка', inner, el.get('extendedTooltip')) + + emit_events(lines, el, name, inner, type_key) + + lines.append(f'{indent}') + + def emit_calendar(lines, el, name, eid, indent): lines.append(f'{indent}') inner = f'{indent}\t' diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1 index 6a9250ce..207f9f6e 100644 --- a/.claude/skills/form-decompile/scripts/form-decompile.ps1 +++ b/.claude/skills/form-decompile/scripts/form-decompile.ps1 @@ -1,4 +1,4 @@ -# form-decompile v0.70 — Decompile 1C managed Form.xml to JSON DSL (draft) +# form-decompile v0.71 — Decompile 1C managed Form.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью. param( @@ -788,7 +788,9 @@ function Add-Layout { # Общие свойства элемента (любой тип): default/drag/skip if ((Get-Child $node 'DefaultItem') -eq 'true') { $obj['defaultItem'] = $true } $soi = Get-Child $node 'SkipOnInput'; if ($null -ne $soi) { $obj['skipOnInput'] = ($soi -eq 'true') } - if ((Get-Child $node 'EnableStartDrag') -eq 'true') { $obj['enableStartDrag'] = $true } + # EnableStartDrag/EnableDrag — фактическое значение (платформа эмитит и явный false, напр. SpreadSheet) + $esd = Get-Child $node 'EnableStartDrag'; if ($null -ne $esd) { $obj['enableStartDrag'] = ($esd -eq 'true') } + $edr = Get-Child $node 'EnableDrag'; if ($null -ne $edr) { $obj['enableDrag'] = ($edr -eq 'true') } $fdm = Get-Child $node 'FileDragMode'; if ($fdm) { $obj['fileDragMode'] = $fdm } # AutoMaxWidth: компилятор додумывает false для multiLine-input без явного ключа (multiLineDefault). # Захват факт. значения; multiLine-input без тега → autoMaxWidth:true (суппресс эвристики). @@ -1147,7 +1149,9 @@ $ELEMENT_KEY = @{ 'RadioButtonField'='radio'; 'LabelDecoration'='label'; 'LabelField'='labelField'; 'PictureDecoration'='picture'; 'PictureField'='picField'; 'CalendarField'='calendar'; 'Table'='table'; 'Pages'='pages'; 'Page'='page'; 'Button'='button'; 'CommandBar'='cmdBar'; 'Popup'='popup'; - 'SearchStringAddition'='searchString'; 'ViewStatusAddition'='viewStatus'; 'SearchControlAddition'='searchControl' + 'SearchStringAddition'='searchString'; 'ViewStatusAddition'='viewStatus'; 'SearchControlAddition'='searchControl'; + 'SpreadSheetDocumentField'='spreadsheet'; 'HTMLDocumentField'='html'; 'TextDocumentField'='textDoc'; + 'FormattedDocumentField'='formattedDoc'; 'ProgressBarField'='progressBar'; 'TrackBarField'='trackBar' } # Простые скаляры элемента (pass-through, зеркало $script:genericScalars компилятора). kind bool/value. @@ -1167,6 +1171,23 @@ $GENERIC_SCALARS = @( @{ Tag='CreateButton'; Key='createButton'; Kind='bool' } @{ Tag='FixingInTable'; Key='fixingInTable'; Kind='value' } @{ Tag='VerticalSpacing'; Key='verticalSpacing'; Kind='value' } + # Спец-поля (документ/датчик) — типоспец. enum/bool скаляры pass-through (зеркало компилятора) + @{ Tag='HorizontalScrollBar'; Key='horizontalScrollBar'; Kind='value' } + @{ Tag='ViewScalingMode'; Key='viewScalingMode'; Kind='value' } + @{ Tag='Output'; Key='output'; Kind='value' } + @{ Tag='SelectionShowMode'; Key='selectionShowMode'; Kind='value' } + @{ Tag='PointerType'; Key='pointerType'; Kind='value' } + @{ Tag='DrawingSelectionShowMode'; Key='drawingSelectionShowMode'; Kind='value' } + @{ Tag='WarningOnEditRepresentation'; Key='warningOnEditRepresentation'; Kind='value' } + @{ Tag='MarkingAppearance'; Key='markingAppearance'; Kind='value' } + @{ Tag='Protection'; Key='protection'; Kind='bool' } + @{ Tag='Edit'; Key='edit'; Kind='bool' } + @{ Tag='ShowGrid'; Key='showGrid'; Kind='bool' } + @{ Tag='ShowGroups'; Key='showGroups'; Kind='bool' } + @{ Tag='ShowHeaders'; Key='showHeaders'; Kind='bool' } + @{ Tag='ShowRowAndColumnNames'; Key='showRowAndColumnNames'; Kind='bool' } + @{ Tag='ShowCellNames'; Key='showCellNames'; Kind='bool' } + @{ Tag='ShowPercent'; Key='showPercent'; Kind='bool' } ) # Захват generic-скаляров. Специфичная обработка (если ключ уже задан) — побеждает. @@ -1350,6 +1371,28 @@ function Decompile-TableAdditions { return $null } +# Спец-поля «документ/датчик» — общий скелет поля (имя/path/CommonProps/TitleLocation/editMode). +# Типоспец. enum/bool скаляры ловит пост-switch Add-GenericScalars; layout/companions — общий хвост. +function Decompile-SimpleField { + param($obj, $node, [string]$name, [string]$key) + $obj[$key] = $name + $dp = Get-Child $node 'DataPath'; if ($dp) { $obj['path'] = $dp } + Add-CommonProps $obj $node $name + $tl = Get-Child $node 'TitleLocation'; if ($tl) { $obj['titleLocation'] = $tl.ToLower() } + $em = Get-Child $node 'EditMode'; if ($em) { $obj['editMode'] = $em } +} + +# Числовые скаляры датчиков (ProgressBar/TrackBar) — без xsi:type (≠ типизированных InputField). +function Add-GaugeScalars { + param($obj, $node, $tags) + foreach ($p in $tags) { + $v = Get-Child $node $p + if ($null -eq $v) { continue } + $key = $p.Substring(0,1).ToLower() + $p.Substring(1) + if ($v -match '^-?\d+$') { $obj[$key] = [int]$v } else { $obj[$key] = $v } + } +} + function Decompile-Element { param($node) $tag = $node.LocalName @@ -1521,7 +1564,7 @@ function Decompile-Element { $crs = Get-Child $node 'ChangeRowSet'; if ($null -ne $crs) { $obj['changeRowSet'] = ($crs -eq 'true') } $cro = Get-Child $node 'ChangeRowOrder'; if ($null -ne $cro) { $obj['changeRowOrder'] = ($cro -eq 'true') } if ((Get-Child $node 'AutoInsertNewRow') -eq 'true') { $obj['autoInsertNewRow'] = $true } - if ((Get-Child $node 'EnableDrag') -eq 'true') { $obj['enableDrag'] = $true } + # enableDrag — теперь общий (Add-Layout, фактическое значение) if ($node.SelectSingleNode("lf:RowFilter", $ns)) { $obj['rowFilter'] = $null } if ((Get-Child $node 'Header') -eq 'false') { $obj['header'] = $false } if ((Get-Child $node 'Footer') -eq 'true') { $obj['footer'] = $true } @@ -1653,6 +1696,12 @@ function Decompile-Element { 'SearchStringAddition' { $obj[$key] = $name; Add-AdditionCore $obj $node $name } 'ViewStatusAddition' { $obj[$key] = $name; Add-AdditionCore $obj $node $name } 'SearchControlAddition' { $obj[$key] = $name; Add-AdditionCore $obj $node $name } + 'SpreadSheetDocumentField' { Decompile-SimpleField $obj $node $name $key } + 'HTMLDocumentField' { Decompile-SimpleField $obj $node $name $key } + 'TextDocumentField' { Decompile-SimpleField $obj $node $name $key } + 'FormattedDocumentField' { Decompile-SimpleField $obj $node $name $key } + 'ProgressBarField' { Decompile-SimpleField $obj $node $name $key; Add-GaugeScalars $obj $node @('MinValue','MaxValue') } + 'TrackBarField' { Decompile-SimpleField $obj $node $name $key; Add-GaugeScalars $obj $node @('MinValue','MaxValue','LargeStep','MarkingStep','Step') } } # DisplayImportance — атрибут открывающего тега (адаптивная важность отображения), захват «как есть». $di = $node.GetAttribute("DisplayImportance"); if ($di) { $obj['displayImportance'] = $di } @@ -1709,7 +1758,7 @@ $titleNode = $root.SelectSingleNode("lf:Title", $ns) if ($titleNode) { $t = Get-LangText $titleNode; if ($null -ne $t) { $dsl['title'] = $t } } # properties (прямые скаляры под
, PascalCase → camelCase) -$KNOWN_FORM_PROPS = @('AutoTitle','WindowOpeningMode','CommandBarLocation','SaveDataInSettings','AutoSaveDataInSettings','AutoTime','UsePostingMode','RepostOnWrite','AutoURL','AutoFillCheck','Customizable','EnterKeyBehavior','VerticalScroll','Width','Height','Group','UseForFoldersAndItems','SaveWindowSettings') +$KNOWN_FORM_PROPS = @('AutoTitle','WindowOpeningMode','CommandBarLocation','SaveDataInSettings','AutoSaveDataInSettings','AutoTime','UsePostingMode','RepostOnWrite','AutoURL','AutoFillCheck','Customizable','EnterKeyBehavior','VerticalScroll','Width','Height','Group','UseForFoldersAndItems','SaveWindowSettings','ScalingMode','VerticalSpacing') $props = [ordered]@{} foreach ($pn in $KNOWN_FORM_PROPS) { $v = Get-Child $root $pn diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md index f19fb120..f77f0c8e 100644 --- a/docs/form-dsl-spec.md +++ b/docs/form-dsl-spec.md @@ -735,6 +735,29 @@ Pages поддерживает `pagesRepresentation`: `None`, `TabsOnTop`, `Tabs | `representation` | string | `Auto`, `Picture`, `Text`, `PictureAndText` | | `children` | array | Кнопки (`button`) внутри группы | +#### Спец-поля «документ/датчик» + +Поля для отображения специальных данных. Структурно — обычные поля (скелет `path`/`title`/`titleLocation`/ +flags/layout/оформление/companions/события общий), плюс собственные скаляры. Привязываются к реквизиту +соответствующего платформенного типа (см. §8 «Платформенные типы»). + +| Ключ типа | XML-элемент | Тип реквизита | Спец. скаляры | +|-----------|-------------|---------------|----------------| +| `spreadsheet` | SpreadSheetDocumentField | `mxl:SpreadsheetDocument` | `output` (Disable/Enable), `protection`, `verticalScrollBar`/`horizontalScrollBar`, `viewScalingMode`, `selectionShowMode`, `pointerType`, `showGrid`/`showGroups`/`showHeaders`/`showRowAndColumnNames`/`showCellNames`, `edit`, `enableDrag`/`enableStartDrag` (фактическое значение) | +| `html` | HTMLDocumentField | `string` | `output`, `warningOnEditRepresentation` | +| `textDoc` | TextDocumentField | `d5p1:TextDocument` | `editMode` | +| `formattedDoc` | FormattedDocumentField | `fd:FormattedDocument` | `editMode` | +| `progressBar` | ProgressBarField | число | `showPercent`, `minValue`/`maxValue` (без `xsi:type`, ≠ типизированных у `input`) | +| `trackBar` | TrackBarField | число | `minValue`/`maxValue`/`largeStep`/`markingStep`/`step` (числовые), `markingAppearance` | + +```json +{ "spreadsheet": "ТаблицаОтчета", "path": "ТаблицаОтчета", "titleLocation": "none", "readOnly": true, "output": "Disable", "protection": true } +{ "trackBar": "Масштаб", "path": "Масштаб", "minValue": 20, "maxValue": 400, "markingStep": 20 } +``` + +Forgiving-синонимы типа: XML-имя (`SpreadSheetDocumentField`) и рус. (`ПолеТабличногоДокумента`, `ПолеИндикатора`, …). +Скаляры `output`/`protection`/… — generic pass-through; bool как `true`/`false`, enum verbatim. + #### autoCmdBar — командная панель формы Командная панель самой формы (``). Задаётся как элемент в `elements`; компилятор автоматически вынимает его из дерева. Нужен только если в панель помещаются **явные** кнопки/группы или меняется выравнивание/автозаполнение — иначе панель формируется автоматически. @@ -950,6 +973,21 @@ Pages поддерживает `pagesRepresentation`: `None`, `TabsOnTop`, `Tabs > Платформенные `v8:`-типы можно писать без префикса или по-русски — компилятор приводит к каноничному `v8:X`. Уже-префиксованную форму (`v8:StandardPeriod`) принимает как есть. +**Спец-типы с собственным namespace** (для спец-полей). Хранятся verbatim с префиксом; компилятор объявляет +namespace **локально** на ``. Префикс `d5p1` неоднозначен (несколько URI) — резолв по полному значению типа. + +| DSL | XML (с локальным xmlns) | +|-----|-----| +| `"mxl:SpreadsheetDocument"` | `mxl:SpreadsheetDocument` | +| `"fd:FormattedDocument"` | `xmlns:fd="…/formatted-document"` | +| `"d5p1:TextDocument"` | `xmlns:d5p1="…/txtedt"` | +| `"d5p1:Chart"` / `"d5p1:GanttChart"` | `xmlns:d5p1="…/chart"` | +| `"d5p1:FlowchartContextType"` | `xmlns:d5p1="…/graphscheme"` | +| `"d5p1:GeographicalSchema"` | `xmlns:d5p1="…/geo"` | +| `"d5p1:DataAnalysisTimeIntervalUnitType"` | `xmlns:d5p1="…/data-analysis"` | +| `"pdfdoc:PDFDocument"` | `xmlns:pdfdoc="…/pdf"` | +| `"pl:Planner"` | `xmlns:pl="…/planner"` | + ### Наборы типов (TypeSet → ``) «Набор типов» вместо конкретного типа. Развязка с обычным типом — по наличию `.Имя`: diff --git a/tests/skills/cases/form-compile/snapshots/special-fields/Configuration.xml b/tests/skills/cases/form-compile/snapshots/special-fields/Configuration.xml new file mode 100644 index 00000000..3baa925d --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/special-fields/Configuration.xml @@ -0,0 +1,252 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + UUID-006 + UUID-007 + + + UUID-008 + UUID-009 + + + UUID-010 + UUID-011 + + + UUID-012 + UUID-013 + + + UUID-014 + UUID-015 + + + + TestConfig + + + ru + TestConfig + + + + + Version8_3_24 + ManagedApplication + + PlatformApplication + + Russian + + + + + false + false + false + + + + + + + + + + + + + + + + + + + + + + Biometrics + true + + + Location + false + + + BackgroundLocation + false + + + BluetoothPrinters + false + + + WiFiPrinters + false + + + Contacts + false + + + Calendars + false + + + PushNotifications + false + + + LocalNotifications + false + + + InAppPurchases + false + + + PersonalComputerFileExchange + false + + + Ads + false + + + NumberDialing + false + + + CallProcessing + false + + + CallLog + false + + + AutoSendSMS + false + + + ReceiveSMS + false + + + SMSLog + false + + + Camera + false + + + Microphone + false + + + MusicLibrary + false + + + PictureAndVideoLibraries + false + + + AudioPlaybackAndVibration + false + + + BackgroundAudioPlaybackAndVibration + false + + + InstallPackages + false + + + OSBackup + true + + + ApplicationUsageStatistics + false + + + BarcodeScanning + false + + + BackgroundAudioRecording + false + + + AllFilesAccess + false + + + Videoconferences + false + + + NFC + false + + + DocumentScanning + false + + + SpeechToText + false + + + Geofences + false + + + IncomingShareRequests + false + + + AllIncomingShareRequestsTypesProcessing + false + + + + + + Normal + + + Language.Русский + + + + + + Managed + NotAutoFree + DontUse + DontUse + TaxiEnableVersion8_2 + DontUse + Version8_3_24 + + + + Русский + СпецПоля + + + \ No newline at end of file diff --git a/tests/skills/cases/form-compile/snapshots/special-fields/DataProcessors/СпецПоля.xml b/tests/skills/cases/form-compile/snapshots/special-fields/DataProcessors/СпецПоля.xml new file mode 100644 index 00000000..bca1f73a --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/special-fields/DataProcessors/СпецПоля.xml @@ -0,0 +1,34 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + + СпецПоля + + + ru + Спец поля + + + + false + DataProcessor.СпецПоля.Form.Форма + + false + + + + + Форма + + + diff --git a/tests/skills/cases/form-compile/snapshots/special-fields/DataProcessors/СпецПоля/Ext/ManagerModule.bsl b/tests/skills/cases/form-compile/snapshots/special-fields/DataProcessors/СпецПоля/Ext/ManagerModule.bsl new file mode 100644 index 00000000..e69de29b diff --git a/tests/skills/cases/form-compile/snapshots/special-fields/DataProcessors/СпецПоля/Ext/ObjectModule.bsl b/tests/skills/cases/form-compile/snapshots/special-fields/DataProcessors/СпецПоля/Ext/ObjectModule.bsl new file mode 100644 index 00000000..e69de29b diff --git a/tests/skills/cases/form-compile/snapshots/special-fields/DataProcessors/СпецПоля/Forms/Форма.xml b/tests/skills/cases/form-compile/snapshots/special-fields/DataProcessors/СпецПоля/Forms/Форма.xml new file mode 100644 index 00000000..dffeea01 --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/special-fields/DataProcessors/СпецПоля/Forms/Форма.xml @@ -0,0 +1,22 @@ + + +
+ + Форма + + + ru + Форма + + + + Managed + false + + PlatformApplication + MobilePlatformApplication + + + +
+
\ No newline at end of file diff --git a/tests/skills/cases/form-compile/snapshots/special-fields/DataProcessors/СпецПоля/Forms/Форма/Ext/Form.xml b/tests/skills/cases/form-compile/snapshots/special-fields/DataProcessors/СпецПоля/Forms/Форма/Ext/Form.xml new file mode 100644 index 00000000..6f871db7 --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/special-fields/DataProcessors/СпецПоля/Forms/Форма/Ext/Form.xml @@ -0,0 +1,164 @@ + +
+ + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Спец-поля</v8:content> + </v8:item> + + false + + + + ТаблицаОтчета + true + None + false + true + true + Normal + Disable + true + false + false + false + + + + + Описание + true + None + EnterOnInput + + + + + Содержимое + None + 37 + false + Enable + DontShow + + + + + ТекстXML + true + None + 56 + + + + + ПроцентВыполнения + None + 30 + true + 10000 + + + + + Масштаб + None + 50 + TopLeft + 20 + 400 + 5 + 20 + + + + + + + + cfg:DataProcessorObject.СпецПоля + + true + + + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Таблица отчета</v8:content> + </v8:item> + + + mxl:SpreadsheetDocument + + + + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Описание</v8:content> + </v8:item> + + + fd:FormattedDocument + + + + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Содержимое</v8:content> + </v8:item> + + + xs:string + + 0 + Variable + + + + + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Текст XML</v8:content> + </v8:item> + + + d5p1:TextDocument + + + + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Процент выполнения</v8:content> + </v8:item> + + + xs:decimal + + 5 + 2 + Nonnegative + + + + + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Масштаб</v8:content> + </v8:item> + + + xs:decimal + + 10 + 0 + Any + + + + + diff --git a/tests/skills/cases/form-compile/snapshots/special-fields/DataProcessors/СпецПоля/Forms/Форма/Ext/Form/Module.bsl b/tests/skills/cases/form-compile/snapshots/special-fields/DataProcessors/СпецПоля/Forms/Форма/Ext/Form/Module.bsl new file mode 100644 index 00000000..8ead4cec --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/special-fields/DataProcessors/СпецПоля/Forms/Форма/Ext/Form/Module.bsl @@ -0,0 +1,19 @@ +#Область ОбработчикиСобытийФормы + +#КонецОбласти + +#Область ОбработчикиСобытийЭлементовФормы + +#КонецОбласти + +#Область ОбработчикиКомандФормы + +#КонецОбласти + +#Область ОбработчикиОповещений + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +#КонецОбласти \ No newline at end of file diff --git a/tests/skills/cases/form-compile/snapshots/special-fields/Ext/ClientApplicationInterface.xml b/tests/skills/cases/form-compile/snapshots/special-fields/Ext/ClientApplicationInterface.xml new file mode 100644 index 00000000..3c1161b2 --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/special-fields/Ext/ClientApplicationInterface.xml @@ -0,0 +1,18 @@ + + + + + UUID-002 + + + + + UUID-004 + + + + + + + + \ No newline at end of file diff --git a/tests/skills/cases/form-compile/snapshots/special-fields/Languages/Русский.xml b/tests/skills/cases/form-compile/snapshots/special-fields/Languages/Русский.xml new file mode 100644 index 00000000..37c60d78 --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/special-fields/Languages/Русский.xml @@ -0,0 +1,16 @@ + + + + + Русский + + + ru + Русский + + + + ru + + + \ No newline at end of file diff --git a/tests/skills/cases/form-compile/special-fields.json b/tests/skills/cases/form-compile/special-fields.json new file mode 100644 index 00000000..b510b2b1 --- /dev/null +++ b/tests/skills/cases/form-compile/special-fields.json @@ -0,0 +1,36 @@ +{ + "name": "Форма со спец-полями (документ/датчик)", + "preRun": [ + { + "script": "meta-compile/scripts/meta-compile", + "input": { "type": "DataProcessor", "name": "СпецПоля" }, + "args": { "-JsonPath": "{inputFile}", "-OutputDir": "{workDir}" } + }, + { + "script": "form-add/scripts/form-add", + "args": { "-ObjectPath": "{workDir}/DataProcessors/СпецПоля.xml", "-FormName": "Форма" } + } + ], + "params": { "outputPath": "DataProcessors/СпецПоля/Forms/Форма/Ext/Form.xml" }, + "validatePath": "DataProcessors/СпецПоля/Forms/Форма/Ext/Form.xml", + "input": { + "title": "Спец-поля", + "elements": [ + { "spreadsheet": "ТаблицаОтчета", "path": "ТаблицаОтчета", "titleLocation": "none", "readOnly": true, "verticalScrollBar": "true", "horizontalScrollBar": "true", "viewScalingMode": "Normal", "output": "Disable", "protection": true, "showGrid": false, "showHeaders": false, "enableDrag": false, "enableStartDrag": false }, + { "formattedDoc": "Описание", "path": "Описание", "titleLocation": "none", "readOnly": true, "editMode": "EnterOnInput" }, + { "html": "Содержимое", "path": "Содержимое", "titleLocation": "none", "width": 37, "horizontalStretch": false, "output": "Enable", "warningOnEditRepresentation": "DontShow" }, + { "textDoc": "ТекстXML", "path": "ТекстXML", "titleLocation": "none", "readOnly": true, "width": 56 }, + { "progressBar": "Прогресс", "path": "ПроцентВыполнения", "titleLocation": "none", "showPercent": true, "maxValue": 10000, "width": 30 }, + { "trackBar": "Масштаб", "path": "Масштаб", "titleLocation": "none", "minValue": 20, "maxValue": 400, "largeStep": 5, "markingStep": 20, "markingAppearance": "TopLeft", "width": 50 } + ], + "attributes": [ + { "name": "Объект", "type": "DataProcessorObject.СпецПоля", "main": true }, + { "name": "ТаблицаОтчета", "type": "mxl:SpreadsheetDocument" }, + { "name": "Описание", "type": "fd:FormattedDocument" }, + { "name": "Содержимое", "type": "string" }, + { "name": "ТекстXML", "type": "d5p1:TextDocument" }, + { "name": "ПроцентВыполнения", "type": "decimal(5,2,nonneg)" }, + { "name": "Масштаб", "type": "decimal(10,0)" } + ] + } +}