mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-06-14 18:04:58 +03:00
feat(form-decompile,form-compile): контент расширенной подсказки extendedTooltip + единая ML-text форма с formatted (кластер companion-content tier 1)
Companion <ExtendedTooltip> несёт <Title> (текст расширенной подсказки) — декомпилятор
пропускал companion целиком, текст терялся. Теперь companion = свойство родителя:
ключ extendedTooltip на элементе (синоним extTooltip).
Единая форма ML-текста (для title/tooltip/extendedTooltip):
- строка → ru; {ru,en} → многоязычно; {text, formatted: true} → форматированный.
- formatted: текст несётся RAW (1С inline-разметка <b>/<color>/<link>/</> — часть строки,
round-trip через XML-экранирование, спаны не моделируем).
- Гибрид: флаг formatted авто-детектится по известной разметке/</> (детектор идентичен в
ps1+py+декомпиляторе); явный {text,formatted} — только когда авто-детект неверен (~2%
корпуса: formatted без разметки / литеральные <…>-плейсхолдеры). Авто-детект подтверждён
данными (98% верно, мисматч 1003 из 53612).
Декомпилятор (v0.26): извлекает Title из companion <ExtendedTooltip> на родителя (гибрид).
Компилятор (ps1+py v1.44): Emit-Companion с опциональным контентом; 14 call-site'ов
ExtendedTooltip передают el.extendedTooltip; синоним extTooltip→extendedTooltip; whitelist.
Валидация: content-bearing round-trip CLEAN (Банки/ФормаЭлемента byte-identical, formatted=true
round-trip); регресс 33/33 ps+py; py==ps1 идентичны; harness 8368→8202.
Хвосты (в BACKLOG): пустое присутствие companion (Table/CommandBar/Popup не генерят
ExtendedTooltip — ~437, вскрыто фиксом метрики) и ExtendedTooltip с own-layout (<Width>).
Spec: extendedTooltip + раздел ML-text/formatted/markup-словарь.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# form-compile v1.43 — Compile 1C managed form from JSON or object metadata
|
||||
# form-compile v1.44 — Compile 1C managed form from JSON or object metadata
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[string]$JsonPath,
|
||||
@@ -1563,6 +1563,34 @@ function Emit-MLText {
|
||||
X "$indent</$tag>"
|
||||
}
|
||||
|
||||
# Детектор «настоящей» inline-разметки форматированного текста (1С: <link>/<b>/<color>/…
|
||||
# и закрывающий </>). Плейсхолдеры вида <не заполнен> НЕ срабатывают (нет известного тега/</>).
|
||||
# ВАЖНО: regex должен быть идентичен в form-decompile (иначе гибрид-раундтрип поедет).
|
||||
$script:fmtMarkupRe = '</>|<\s*(?:link|b|i|u|s|color|colorStyle|bgColor|bgColorStyle|font|fontSize|fontStyle|img)(?:\s|>)'
|
||||
function Test-HasRealMarkup {
|
||||
param($text)
|
||||
if ($null -eq $text) { return $false }
|
||||
$vals = if ($text -is [System.Collections.IDictionary]) { @($text.Values) }
|
||||
elseif ($text -is [System.Management.Automation.PSCustomObject]) { @($text.PSObject.Properties.Value) }
|
||||
else { @("$text") }
|
||||
foreach ($v in $vals) { if ("$v" -match $script:fmtMarkupRe) { return $true } }
|
||||
return $false
|
||||
}
|
||||
# DSL-значение ML-поля → @{ text; formatted }. Форма {text, formatted} = явный override;
|
||||
# строка/мапа → авто-детект formatted по разметке.
|
||||
function Resolve-MLFormatted {
|
||||
param($val)
|
||||
$hasText = $false
|
||||
if ($val -is [System.Management.Automation.PSCustomObject]) { $hasText = [bool]$val.PSObject.Properties['text'] }
|
||||
elseif ($val -is [System.Collections.IDictionary]) { $hasText = $val.Contains('text') }
|
||||
if ($hasText) {
|
||||
$t = if ($val -is [System.Collections.IDictionary]) { $val['text'] } else { $val.text }
|
||||
$f = if ($val -is [System.Collections.IDictionary]) { $val['formatted'] } else { $val.formatted }
|
||||
return @{ text = $t; formatted = [bool]$f }
|
||||
}
|
||||
return @{ text = $val; formatted = (Test-HasRealMarkup $val) }
|
||||
}
|
||||
|
||||
# Каноничные GUID пустых контейнеров ListSettings (умолчание платформы, ~90% форм).
|
||||
# Декомпилятор опускает пустые настройки → компилятор регенерит этот скелет → раундтрип
|
||||
# (harness нормализует GUID для хвоста с иными идентификаторами).
|
||||
@@ -2219,9 +2247,21 @@ function Emit-Events {
|
||||
}
|
||||
|
||||
function Emit-Companion {
|
||||
param([string]$tag, [string]$name, [string]$indent)
|
||||
param([string]$tag, [string]$name, [string]$indent, $content = $null)
|
||||
$id = New-Id
|
||||
X "$indent<$tag name=`"$name`" id=`"$id`"/>"
|
||||
$hasContent = $null -ne $content -and -not ($content -is [string] -and "$content" -eq '')
|
||||
if (-not $hasContent) {
|
||||
X "$indent<$tag name=`"$name`" id=`"$id`"/>"
|
||||
return
|
||||
}
|
||||
# Companion с контентом: <Title formatted="…"> (расширенная подсказка)
|
||||
X "$indent<$tag name=`"$name`" id=`"$id`">"
|
||||
$r = Resolve-MLFormatted $content
|
||||
$fmt = if ($r.formatted) { 'true' } else { 'false' }
|
||||
X "$indent`t<Title formatted=`"$fmt`">"
|
||||
Emit-MLItems -val $r.text -indent "$indent`t`t"
|
||||
X "$indent`t</Title>"
|
||||
X "$indent</$tag>"
|
||||
}
|
||||
|
||||
# Табличный addition (СтрокаПоиска/СостояниеПросмотра/УправлениеПоиском) с AdditionSource.
|
||||
@@ -2316,7 +2356,7 @@ function Emit-Element {
|
||||
# radio-specific
|
||||
"radioButtonType"=1;"choiceList"=1;"columnsCount"=1;"checkBoxType"=1;"editMode"=1
|
||||
# naming & binding
|
||||
"name"=1;"path"=1;"title"=1;"tooltip"=1;"tooltipRepresentation"=1
|
||||
"name"=1;"path"=1;"title"=1;"tooltip"=1;"tooltipRepresentation"=1;"extendedTooltip"=1
|
||||
# visibility & state
|
||||
"visible"=1;"hidden"=1;"enabled"=1;"disabled"=1;"readOnly"=1;"userVisible"=1
|
||||
# events ("events" — основной формат; on/handlers — legacy, принимаются ради совместимости)
|
||||
@@ -2548,7 +2588,7 @@ function Emit-Group {
|
||||
Emit-Layout -el $el -indent $inner
|
||||
|
||||
# Companion: ExtendedTooltip
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner -content $el.extendedTooltip
|
||||
|
||||
# Children
|
||||
if ($el.children -and $el.children.Count -gt 0) {
|
||||
@@ -2590,7 +2630,7 @@ function Emit-ColumnGroup {
|
||||
Emit-Layout -el $el -indent $inner
|
||||
|
||||
# Companion: ExtendedTooltip
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner -content $el.extendedTooltip
|
||||
|
||||
# Children
|
||||
if ($el.children -and $el.children.Count -gt 0) {
|
||||
@@ -2645,7 +2685,7 @@ function Emit-Input {
|
||||
|
||||
# Companions
|
||||
Emit-Companion -tag "ContextMenu" -name "${name}КонтекстноеМеню" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner -content $el.extendedTooltip
|
||||
|
||||
Emit-Events -el $el -elementName $name -indent $inner -typeKey "input"
|
||||
|
||||
@@ -2678,7 +2718,7 @@ function Emit-Check {
|
||||
|
||||
# Companions
|
||||
Emit-Companion -tag "ContextMenu" -name "${name}КонтекстноеМеню" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner -content $el.extendedTooltip
|
||||
|
||||
Emit-Events -el $el -elementName $name -indent $inner -typeKey "check"
|
||||
|
||||
@@ -2903,7 +2943,7 @@ function Emit-Radio {
|
||||
|
||||
# Companions
|
||||
Emit-Companion -tag "ContextMenu" -name "${name}КонтекстноеМеню" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner -content $el.extendedTooltip
|
||||
|
||||
Emit-Events -el $el -elementName $name -indent $inner -typeKey "radio"
|
||||
|
||||
@@ -2935,7 +2975,7 @@ function Emit-Label {
|
||||
|
||||
# Companions
|
||||
Emit-Companion -tag "ContextMenu" -name "${name}КонтекстноеМеню" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner -content $el.extendedTooltip
|
||||
|
||||
Emit-Events -el $el -elementName $name -indent $inner -typeKey "label"
|
||||
|
||||
@@ -2961,7 +3001,7 @@ function Emit-LabelField {
|
||||
|
||||
# Companions
|
||||
Emit-Companion -tag "ContextMenu" -name "${name}КонтекстноеМеню" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner -content $el.extendedTooltip
|
||||
|
||||
Emit-Events -el $el -elementName $name -indent $inner -typeKey "labelField"
|
||||
|
||||
@@ -3108,7 +3148,7 @@ function Emit-Pages {
|
||||
Emit-Layout -el $el -indent $inner
|
||||
|
||||
# Companion
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner -content $el.extendedTooltip
|
||||
|
||||
Emit-Events -el $el -elementName $name -indent $inner -typeKey "pages"
|
||||
|
||||
@@ -3146,7 +3186,7 @@ function Emit-Page {
|
||||
Emit-Layout -el $el -indent $inner
|
||||
|
||||
# Companion
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner -content $el.extendedTooltip
|
||||
|
||||
# Children
|
||||
if ($el.children -and $el.children.Count -gt 0) {
|
||||
@@ -3244,7 +3284,7 @@ function Emit-Button {
|
||||
Emit-Layout -el $el -indent $inner
|
||||
|
||||
# Companion
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner -content $el.extendedTooltip
|
||||
|
||||
Emit-Events -el $el -elementName $name -indent $inner -typeKey "button"
|
||||
|
||||
@@ -3274,7 +3314,7 @@ function Emit-PictureDecoration {
|
||||
|
||||
# Companions
|
||||
Emit-Companion -tag "ContextMenu" -name "${name}КонтекстноеМеню" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner -content $el.extendedTooltip
|
||||
|
||||
Emit-Events -el $el -elementName $name -indent $inner -typeKey "picture"
|
||||
|
||||
@@ -3308,7 +3348,7 @@ function Emit-PictureField {
|
||||
|
||||
# Companions
|
||||
Emit-Companion -tag "ContextMenu" -name "${name}КонтекстноеМеню" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner -content $el.extendedTooltip
|
||||
|
||||
Emit-Events -el $el -elementName $name -indent $inner -typeKey "picField"
|
||||
|
||||
@@ -3350,7 +3390,7 @@ function Emit-Calendar {
|
||||
|
||||
# Companions
|
||||
Emit-Companion -tag "ContextMenu" -name "${name}КонтекстноеМеню" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner -content $el.extendedTooltip
|
||||
|
||||
Emit-Events -el $el -elementName $name -indent $inner -typeKey "calendar"
|
||||
|
||||
@@ -3398,7 +3438,7 @@ function Emit-ButtonGroup {
|
||||
Emit-Layout -el $el -indent $inner
|
||||
|
||||
# Companion: ExtendedTooltip
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner -content $el.extendedTooltip
|
||||
|
||||
# Children (кнопки в контексте командной панели)
|
||||
if ($el.children -and $el.children.Count -gt 0) {
|
||||
@@ -3676,7 +3716,7 @@ function Emit-Properties {
|
||||
function Normalize-ElementSynonyms {
|
||||
param($el)
|
||||
if ($null -eq $el) { return }
|
||||
$synonyms = @{ "commandBar" = "cmdBar"; "autoCommandBar" = "autoCmdBar" }
|
||||
$synonyms = @{ "commandBar" = "cmdBar"; "autoCommandBar" = "autoCmdBar"; "extTooltip" = "extendedTooltip" }
|
||||
foreach ($pair in $synonyms.GetEnumerator()) {
|
||||
if ($null -ne $el.PSObject.Properties[$pair.Key] -and $null -eq $el.PSObject.Properties[$pair.Value]) {
|
||||
$val = $el.($pair.Key)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# form-compile v1.43 — Compile 1C managed form from JSON or object metadata
|
||||
# form-compile v1.44 — Compile 1C managed form from JSON or object metadata
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import copy
|
||||
@@ -1761,7 +1761,7 @@ KNOWN_KEYS = {
|
||||
"button", "picture", "picField", "calendar", "cmdBar", "popup",
|
||||
"showInHeader",
|
||||
"radioButtonType", "choiceList", "columnsCount", "checkBoxType", "editMode",
|
||||
"name", "path", "title", "tooltip", "tooltipRepresentation",
|
||||
"name", "path", "title", "tooltip", "tooltipRepresentation", "extendedTooltip",
|
||||
"visible", "hidden", "enabled", "disabled", "readOnly", "userVisible",
|
||||
"events", "on", "handlers",
|
||||
"selectionMode", "showCurrentDate", "widthInMonths", "heightInMonths", "showMonthsPanel",
|
||||
@@ -2012,9 +2012,37 @@ def emit_events(lines, el, element_name, indent, type_key):
|
||||
lines.append(f"{indent}</Events>")
|
||||
|
||||
|
||||
def emit_companion(lines, tag, name, indent):
|
||||
# Детектор «настоящей» inline-разметки (1С: <link>/<b>/<color>/… и </>). Должен быть
|
||||
# идентичен form-decompile/form-compile.ps1, иначе гибрид-раундтрип поедет.
|
||||
_FMT_MARKUP_RE = re.compile(r'</>|<\s*(?:link|b|i|u|s|color|colorStyle|bgColor|bgColorStyle|font|fontSize|fontStyle|img)(?:\s|>)', re.I)
|
||||
|
||||
|
||||
def _has_real_markup(text):
|
||||
if text is None:
|
||||
return False
|
||||
vals = list(text.values()) if isinstance(text, dict) else [text]
|
||||
return any(_FMT_MARKUP_RE.search(str(v)) for v in vals)
|
||||
|
||||
|
||||
def resolve_ml_formatted(val):
|
||||
# {text, formatted} = явный override; строка/мапа → авто-детект formatted
|
||||
if isinstance(val, dict) and 'text' in val:
|
||||
return val['text'], bool(val.get('formatted'))
|
||||
return val, _has_real_markup(val)
|
||||
|
||||
|
||||
def emit_companion(lines, tag, name, indent, content=None):
|
||||
cid = new_id()
|
||||
lines.append(f'{indent}<{tag} name="{name}" id="{cid}"/>')
|
||||
has_content = content is not None and not (isinstance(content, str) and content == '')
|
||||
if not has_content:
|
||||
lines.append(f'{indent}<{tag} name="{name}" id="{cid}"/>')
|
||||
return
|
||||
lines.append(f'{indent}<{tag} name="{name}" id="{cid}">')
|
||||
text, fmt = resolve_ml_formatted(content)
|
||||
lines.append(f'{indent}\t<Title formatted="{"true" if fmt else "false"}">')
|
||||
emit_ml_items(lines, f'{indent}\t\t', text)
|
||||
lines.append(f'{indent}\t</Title>')
|
||||
lines.append(f'{indent}</{tag}>')
|
||||
|
||||
|
||||
def emit_table_addition(lines, tag, table_name, name_suffix, src_type, indent):
|
||||
@@ -2422,7 +2450,7 @@ def emit_group(lines, el, name, eid, indent):
|
||||
emit_layout(lines, el, inner)
|
||||
|
||||
# Companion: ExtendedTooltip
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner, el.get('extendedTooltip'))
|
||||
|
||||
# Children
|
||||
if el.get('children') and len(el['children']) > 0:
|
||||
@@ -2459,7 +2487,7 @@ def emit_column_group(lines, el, name, eid, indent):
|
||||
emit_common_flags(lines, el, inner)
|
||||
emit_layout(lines, el, inner)
|
||||
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}РасширеннаяПодсказка', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}РасширеннаяПодсказка', inner, el.get('extendedTooltip'))
|
||||
|
||||
if el.get('children') and len(el['children']) > 0:
|
||||
lines.append(f'{inner}<ChildItems>')
|
||||
@@ -2512,7 +2540,7 @@ def emit_input(lines, el, name, eid, indent):
|
||||
|
||||
# Companions
|
||||
emit_companion(lines, 'ContextMenu', f'{name}\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0435\u041c\u0435\u043d\u044e', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner, el.get('extendedTooltip'))
|
||||
|
||||
emit_events(lines, el, name, inner, 'input')
|
||||
|
||||
@@ -2545,7 +2573,7 @@ def emit_check(lines, el, name, eid, indent):
|
||||
|
||||
# Companions
|
||||
emit_companion(lines, 'ContextMenu', f'{name}\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0435\u041c\u0435\u043d\u044e', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner, el.get('extendedTooltip'))
|
||||
|
||||
emit_events(lines, el, name, inner, 'check')
|
||||
|
||||
@@ -2604,7 +2632,7 @@ def emit_radio_button_field(lines, el, name, eid, indent):
|
||||
emit_layout(lines, el, inner)
|
||||
|
||||
emit_companion(lines, 'ContextMenu', f'{name}КонтекстноеМеню', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}РасширеннаяПодсказка', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}РасширеннаяПодсказка', inner, el.get('extendedTooltip'))
|
||||
|
||||
emit_events(lines, el, name, inner, 'radio')
|
||||
|
||||
@@ -2635,7 +2663,7 @@ def emit_label(lines, el, name, eid, indent):
|
||||
|
||||
# Companions
|
||||
emit_companion(lines, 'ContextMenu', f'{name}\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0435\u041c\u0435\u043d\u044e', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner, el.get('extendedTooltip'))
|
||||
|
||||
emit_events(lines, el, name, inner, 'label')
|
||||
|
||||
@@ -2663,7 +2691,7 @@ def emit_label_field(lines, el, name, eid, indent):
|
||||
|
||||
# Companions
|
||||
emit_companion(lines, 'ContextMenu', f'{name}\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0435\u041c\u0435\u043d\u044e', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner, el.get('extendedTooltip'))
|
||||
|
||||
emit_events(lines, el, name, inner, 'labelField')
|
||||
|
||||
@@ -2815,7 +2843,7 @@ def emit_pages(lines, el, name, eid, indent):
|
||||
emit_layout(lines, el, inner)
|
||||
|
||||
# Companion
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner, el.get('extendedTooltip'))
|
||||
|
||||
emit_events(lines, el, name, inner, 'pages')
|
||||
|
||||
@@ -2849,7 +2877,7 @@ def emit_page(lines, el, name, eid, indent):
|
||||
emit_layout(lines, el, inner)
|
||||
|
||||
# Companion
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner, el.get('extendedTooltip'))
|
||||
|
||||
# Children
|
||||
if el.get('children') and len(el['children']) > 0:
|
||||
@@ -2932,7 +2960,7 @@ def emit_button(lines, el, name, eid, indent, in_cmd_bar=False):
|
||||
emit_layout(lines, el, inner)
|
||||
|
||||
# Companion
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner, el.get('extendedTooltip'))
|
||||
|
||||
emit_events(lines, el, name, inner, 'button')
|
||||
|
||||
@@ -2960,7 +2988,7 @@ def emit_picture_decoration(lines, el, name, eid, indent):
|
||||
|
||||
# Companions
|
||||
emit_companion(lines, 'ContextMenu', f'{name}\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0435\u041c\u0435\u043d\u044e', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner, el.get('extendedTooltip'))
|
||||
|
||||
emit_events(lines, el, name, inner, 'picture')
|
||||
|
||||
@@ -2994,7 +3022,7 @@ def emit_picture_field(lines, el, name, eid, indent):
|
||||
|
||||
# Companions
|
||||
emit_companion(lines, 'ContextMenu', f'{name}\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0435\u041c\u0435\u043d\u044e', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner, el.get('extendedTooltip'))
|
||||
|
||||
emit_events(lines, el, name, inner, 'picField')
|
||||
|
||||
@@ -3032,7 +3060,7 @@ def emit_calendar(lines, el, name, eid, indent):
|
||||
|
||||
# Companions
|
||||
emit_companion(lines, 'ContextMenu', f'{name}\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0435\u041c\u0435\u043d\u044e', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner, el.get('extendedTooltip'))
|
||||
|
||||
emit_events(lines, el, name, inner, 'calendar')
|
||||
|
||||
@@ -3101,7 +3129,7 @@ def emit_button_group(lines, el, name, eid, indent):
|
||||
emit_layout(lines, el, inner)
|
||||
|
||||
# Companion: ExtendedTooltip
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}РасширеннаяПодсказка', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}РасширеннаяПодсказка', inner, el.get('extendedTooltip'))
|
||||
|
||||
# Children (кнопки в контексте командной панели)
|
||||
if el.get('children') and len(el['children']) > 0:
|
||||
@@ -3575,7 +3603,7 @@ def main():
|
||||
def _normalize_synonyms(el):
|
||||
if not isinstance(el, dict):
|
||||
return
|
||||
synonyms = {'commandBar': 'cmdBar', 'autoCommandBar': 'autoCmdBar'}
|
||||
synonyms = {'commandBar': 'cmdBar', 'autoCommandBar': 'autoCmdBar', 'extTooltip': 'extendedTooltip'}
|
||||
for src, dst in synonyms.items():
|
||||
if src in el and dst not in el:
|
||||
el[dst] = el.pop(src)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# form-decompile v0.25 — Decompile 1C managed Form.xml to JSON DSL (draft)
|
||||
# form-decompile v0.26 — Decompile 1C managed Form.xml to JSON DSL (draft)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
|
||||
param(
|
||||
@@ -230,6 +230,27 @@ function Get-LangText {
|
||||
return $map
|
||||
}
|
||||
|
||||
# Детектор «настоящей» inline-разметки форматированного текста (идентичен form-compile!).
|
||||
$script:fmtMarkupRe = '</>|<\s*(?:link|b|i|u|s|color|colorStyle|bgColor|bgColorStyle|font|fontSize|fontStyle|img)(?:\s|>)'
|
||||
function Test-HasRealMarkup {
|
||||
param($text)
|
||||
if ($null -eq $text) { return $false }
|
||||
$vals = if ($text -is [System.Collections.IDictionary]) { @($text.Values) } else { @("$text") }
|
||||
foreach ($v in $vals) { if ("$v" -match $script:fmtMarkupRe) { return $true } }
|
||||
return $false
|
||||
}
|
||||
# Title-узел → DSL-значение ML-поля (гибрид): строка/мапа когда авто-детект formatted
|
||||
# совпал с атрибутом; иначе явный {text, formatted}.
|
||||
function Get-MLFormattedValue {
|
||||
param($titleNode)
|
||||
if (-not $titleNode) { return $null }
|
||||
$text = Get-LangText $titleNode
|
||||
if ($null -eq $text) { return $null }
|
||||
$fmtAttr = ($titleNode.GetAttribute('formatted') -eq 'true')
|
||||
if ($fmtAttr -eq (Test-HasRealMarkup $text)) { return $text }
|
||||
$o = [ordered]@{}; $o['text'] = $text; $o['formatted'] = $fmtAttr; return $o
|
||||
}
|
||||
|
||||
# Прочитать дочерний скаляр (по local-name, без namespace)
|
||||
function Get-Child {
|
||||
param($node, [string]$name)
|
||||
@@ -1086,6 +1107,9 @@ function Decompile-Element {
|
||||
if ($autoTitle) { $obj['title'] = '' }
|
||||
}
|
||||
Add-Layout $obj $node
|
||||
# extendedTooltip: контент companion <ExtendedTooltip><Title> (любой элемент)
|
||||
$etTitle = $node.SelectSingleNode("lf:ExtendedTooltip/lf:Title", $ns)
|
||||
if ($etTitle) { $et = Get-MLFormattedValue $etTitle; if ($null -ne $et) { $obj['extendedTooltip'] = $et } }
|
||||
return $obj
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +118,18 @@
|
||||
| `titleLocation` | string | Расположение заголовка: `none`/`left`/`right`/`top`/`bottom`/`auto`. Эмитится при наличии (input, labelField, picField, table, calendar). У `check`/`radio` — особая семантика с умным дефолтом (см. их разделы) |
|
||||
| `tooltip` | string/object | Всплывающая подсказка элемента (`<ToolTip>`). Строка → ru, объект `{ "ru": …, "en": … }` → мультиязычный (как `title`). Эмитится сразу после `title` |
|
||||
| `tooltipRepresentation` | string | Режим показа подсказки (`<ToolTipRepresentation>`): `None`, `Button`, `ShowBottom`, `ShowTop`, `ShowLeft`, `ShowRight`, `ShowAuto`, `Balloon`. Эмитится при наличии |
|
||||
| `extendedTooltip` | string/object | Расширенная подсказка (контент companion `<ExtendedTooltip>`). См. форму ML-текста ниже. Синоним: `extTooltip` |
|
||||
|
||||
#### Форма ML-текста и `formatted`
|
||||
|
||||
`title`/`tooltip`/`extendedTooltip` принимают:
|
||||
- `"строка"` — ru-текст;
|
||||
- `{ "ru": "…", "en": "…" }` — многоязычный;
|
||||
- `{ "text": <строка|мапа>, "formatted": true }` — **форматированный** текст (атрибут `<Title formatted="true">`).
|
||||
|
||||
**`formatted`** включает интерпретацию inline-разметки в тексте (1С-формат, похож на BBCode): `<b>…</>`, `<i>`, `<u>`, `<color web:Red>…</>`, `<bgColor …>`, `<font …>`, `<fontSize …>`, `<link URL>…</>`, `<img …>`; закрывающий тег — `</>`. Текст несётся **raw** (разметка — часть строки), парсинг не требуется.
|
||||
|
||||
Флаг авто-детектится по наличию известной разметки/`</>`: для plain-строки объект не нужен. Явная форма `{text, formatted}` — только когда авто-детект неверен (formatted-текст без разметки, либо буквальные `<…>`-плейсхолдеры в неформатированном).
|
||||
|
||||
### 4.1a. Общие layout-свойства
|
||||
|
||||
|
||||
Reference in New Issue
Block a user