Compare commits

...
3 Commits
Author SHA1 Message Date
Nick ShirokovandClaude Opus 4.6 3c48451704 docs(meta-compile): add new Catalog props and multiline flag to specs
Update meta-dsl-spec.md and types-basic.md reference with:
limitLevelCount, levelCount, foldersOnTop, codeSeries,
subordinationUse, quickChoice, choiceMode, multiline flag.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 15:00:04 +03:00
Nick ShirokovandClaude Opus 4.6 801ceea2c0 feat(meta-compile): configurable Catalog props, owners, multiLine, fix reservedAttrNames
- Catalog: limitLevelCount, levelCount, foldersOnTop, subordinationUse,
  codeSeries, quickChoice, choiceMode now read from JSON (were hardcoded)
- Catalog owners: new `owners` array property with shorthand normalization
- Attribute MultiLine: configurable via `multiLine: true` or `| multiline` flag
- reservedAttrNames warning: now skipped for tabular/processor-tabular context
- 3 new enum validations: SubordinationUse, CodeSeries, ChoiceMode

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:54:50 +03:00
Nick ShirokovandClaude Opus 4.6 63de8bd27c fix(meta-compile,meta-edit,meta-validate): strict enum validation + fix RequireCalculationTypes
Normalize-EnumValue now uses 4-step logic: alias→case-insensitive→
error (if propName known)→pass-through (if unknown). Previously step 3
silently passed invalid values through to XML, causing cryptic 1C
LoadConfigFromFiles errors.

Also fixed RequireCalculationTypes→OnActionPeriod (the former never
existed in 1C; verified against ERP/ACC dumps). Added NotUsed→DontUse
alias, synced meta-edit.ps1 aliases with meta-compile.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:29:46 +03:00
9 changed files with 154 additions and 66 deletions
@@ -6,13 +6,20 @@
|-----------|----------|-------------|
| `hierarchical` | `false` | Hierarchical |
| `hierarchyType` | `HierarchyFoldersAndItems` | HierarchyType |
| `limitLevelCount` | `false` | LimitLevelCount |
| `levelCount` | `2` | LevelCount |
| `foldersOnTop` | `true` | FoldersOnTop |
| `codeLength` | `9` | CodeLength |
| `codeType` | `String` | CodeType |
| `codeAllowedLength` | `Variable` | CodeAllowedLength |
| `codeSeries` | `WholeCatalog` | CodeSeries |
| `descriptionLength` | `25` | DescriptionLength |
| `autonumbering` | `true` | Autonumbering |
| `checkUnique` | `false` | CheckUnique |
| `defaultPresentation` | `AsDescription` | DefaultPresentation |
| `subordinationUse` | `ToItems` | SubordinationUse |
| `quickChoice` | `true` | QuickChoice |
| `choiceMode` | `BothWays` | ChoiceMode |
| `owners` | `[]` | Owners |
| `attributes` | `[]` | → Attribute в ChildObjects |
| `tabularSections` | `{}` | → TabularSection в ChildObjects |
@@ -156,15 +156,15 @@
| `descriptionLength` | `25` | DescriptionLength |
| `autonumbering` | `true` | Autonumbering |
| `checkUnique` | `false` | CheckUnique |
| `dependenceOnCalculationTypes` | `NotUsed` | DependenceOnCalculationTypes |
| `dependenceOnCalculationTypes` | `DontUse` | DependenceOnCalculationTypes |
| `actionPeriodUse` | `false` | ActionPeriodUse |
| `attributes` | `[]` | → Attribute |
| `tabularSections` | `{}` | → TabularSection |
`dependenceOnCalculationTypes`: `NotUsed`, `ExclusionAndDependence`, `ExclusionOnly`.
`dependenceOnCalculationTypes`: `DontUse`, `OnActionPeriod`.
```json
{ "type": "ChartOfCalculationTypes", "name": "Начисления", "dependenceOnCalculationTypes": "ExclusionAndDependence" }
{ "type": "ChartOfCalculationTypes", "name": "Начисления", "dependenceOnCalculationTypes": "OnActionPeriod" }
```
## Зависимости
@@ -1,4 +1,4 @@
# meta-compile v1.8 — Compile 1C metadata object from JSON
# meta-compile v1.10 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -87,8 +87,8 @@ $script:enumValueAliases = @{
"RecordSubordinate" = "RecorderSubordinate"; "Subordinate" = "RecorderSubordinate"
"ПодчинениеРегистратору" = "RecorderSubordinate"; "Независимый" = "Independent"
# DependenceOnCalculationTypes (ChartOfCalculationTypes)
"NotDependOnCalculationTypes" = "DontUse"; "NoDependence" = "DontUse"
"Depend" = "RequireCalculationTypes"; "RequireCalculation" = "RequireCalculationTypes"
"NotDependOnCalculationTypes" = "DontUse"; "NoDependence" = "DontUse"; "NotUsed" = "DontUse"
"Depend" = "OnActionPeriod"; "ПоПериодуДействия" = "OnActionPeriod"
# InformationRegisterPeriodicity
"None" = "Nonperiodical"; "Daily" = "Day"; "Monthly" = "Month"
"Quarterly" = "Quarter"; "Yearly" = "Year"
@@ -117,7 +117,7 @@ $script:validEnumValues = @{
"RegisterType" = @("Balance","Turnovers")
"WriteMode" = @("Independent","RecorderSubordinate")
"InformationRegisterPeriodicity" = @("Nonperiodical","Second","Day","Month","Quarter","Year","RecorderPosition")
"DependenceOnCalculationTypes" = @("DontUse","RequireCalculationTypes")
"DependenceOnCalculationTypes" = @("DontUse","OnActionPeriod")
"DataLockControlMode" = @("Automatic","Managed")
"FullTextSearch" = @("Use","DontUse")
"DataHistory" = @("Use","DontUse")
@@ -136,22 +136,28 @@ $script:validEnumValues = @{
"ReuseSessions" = @("DontUse","AutoUse")
"FillChecking" = @("DontCheck","ShowError","ShowWarning")
"Indexing" = @("DontIndex","Index","IndexWithAdditionalOrder")
"SubordinationUse" = @("ToItems","ToFolders","ToFoldersAndItems")
"CodeSeries" = @("WholeCatalog","WithinSubordination")
"ChoiceMode" = @("BothWays","QuickChoice","FromForm")
}
function Normalize-EnumValue {
param([string]$propName, [string]$value)
# 1. Check alias dictionary
# 1. Check alias dictionary — silent auto-correct
if ($script:enumValueAliases.ContainsKey($value)) {
return $script:enumValueAliases[$value]
}
# 2. Case-insensitive match against valid values
# 2. Case-insensitive match against valid values — silent
$valid = $script:validEnumValues[$propName]
if ($valid) {
foreach ($v in $valid) {
if ($v -ieq $value) { return $v }
}
# 3. Known property, unknown value — error with hint
Write-Error "Invalid value '$value' for property '$propName'. Valid values: $($valid -join ', ')"
exit 1
}
# 3. Return as-is (validator will catch if wrong)
# 4. Unknown property — pass-through (no validation data)
return $value
}
@@ -495,6 +501,7 @@ function Parse-AttributeShorthand {
flags = @(if ($val.flags) { $val.flags } else { @() })
fillChecking = if ($val.fillChecking) { "$($val.fillChecking)" } else { "" }
indexing = if ($val.indexing) { "$($val.indexing)" } else { "" }
multiLine = if ($val.multiLine -eq $true) { $true } else { $false }
}
}
@@ -757,7 +764,8 @@ function Emit-Attribute {
param([string]$indent, $parsed, [string]$context)
# $context: "catalog", "document", "object", "processor", "tabular", "processor-tabular", "register"
$attrName = $parsed.name
if ($script:reservedAttrNames.ContainsKey($attrName) -or $script:reservedAttrNames.ContainsValue($attrName)) {
if ($context -notin @("tabular", "processor-tabular") -and
($script:reservedAttrNames.ContainsKey($attrName) -or $script:reservedAttrNames.ContainsValue($attrName))) {
Write-Warning "Attribute '$attrName' conflicts with a standard attribute name. This may cause errors when loading into 1C."
}
$uuid = New-Guid-String
@@ -784,7 +792,8 @@ function Emit-Attribute {
X "$indent`t`t<ToolTip/>"
X "$indent`t`t<MarkNegatives>false</MarkNegatives>"
X "$indent`t`t<Mask/>"
X "$indent`t`t<MultiLine>false</MultiLine>"
$multiLine = if ($parsed.multiLine -eq $true -or $parsed.flags -contains "multiline") { "true" } else { "false" }
X "$indent`t`t<MultiLine>$multiLine</MultiLine>"
X "$indent`t`t<ExtendedEdit>false</ExtendedEdit>"
X "$indent`t`t<MinValue xsi:nil=`"true`"/>"
X "$indent`t`t<MaxValue xsi:nil=`"true`"/>"
@@ -928,7 +937,8 @@ function Emit-Dimension {
X "$indent`t`t<ToolTip/>"
X "$indent`t`t<MarkNegatives>false</MarkNegatives>"
X "$indent`t`t<Mask/>"
X "$indent`t`t<MultiLine>false</MultiLine>"
$multiLine = if ($parsed.multiLine -eq $true -or $parsed.flags -contains "multiline") { "true" } else { "false" }
X "$indent`t`t<MultiLine>$multiLine</MultiLine>"
X "$indent`t`t<ExtendedEdit>false</ExtendedEdit>"
X "$indent`t`t<MinValue xsi:nil=`"true`"/>"
X "$indent`t`t<MaxValue xsi:nil=`"true`"/>"
@@ -1021,7 +1031,8 @@ function Emit-Resource {
X "$indent`t`t<ToolTip/>"
X "$indent`t`t<MarkNegatives>false</MarkNegatives>"
X "$indent`t`t<Mask/>"
X "$indent`t`t<MultiLine>false</MultiLine>"
$multiLine = if ($parsed.multiLine -eq $true -or $parsed.flags -contains "multiline") { "true" } else { "false" }
X "$indent`t`t<MultiLine>$multiLine</MultiLine>"
X "$indent`t`t<ExtendedEdit>false</ExtendedEdit>"
X "$indent`t`t<MinValue xsi:nil=`"true`"/>"
X "$indent`t`t<MaxValue xsi:nil=`"true`"/>"
@@ -1075,12 +1086,25 @@ function Emit-CatalogProperties {
$hierarchyType = Get-EnumProp "HierarchyType" "hierarchyType" "HierarchyFoldersAndItems"
X "$i<Hierarchical>$hierarchical</Hierarchical>"
X "$i<HierarchyType>$hierarchyType</HierarchyType>"
X "$i<LimitLevelCount>false</LimitLevelCount>"
X "$i<LevelCount>2</LevelCount>"
X "$i<FoldersOnTop>true</FoldersOnTop>"
$limitLevelCount = if ($def.limitLevelCount -eq $true) { "true" } else { "false" }
$levelCount = if ($null -ne $def.levelCount) { "$($def.levelCount)" } else { "2" }
$foldersOnTop = if ($def.foldersOnTop -eq $false) { "false" } else { "true" }
X "$i<LimitLevelCount>$limitLevelCount</LimitLevelCount>"
X "$i<LevelCount>$levelCount</LevelCount>"
X "$i<FoldersOnTop>$foldersOnTop</FoldersOnTop>"
X "$i<UseStandardCommands>true</UseStandardCommands>"
X "$i<Owners/>"
X "$i<SubordinationUse>ToItems</SubordinationUse>"
if ($def.owners -and $def.owners.Count -gt 0) {
X "$i<Owners>"
foreach ($ownerRef in $def.owners) {
$fullRef = if ("$ownerRef" -match '\.') { "$ownerRef" } else { "Catalog.$ownerRef" }
X "$i`t<xr:Item xsi:type=`"xr:MDObjectRef`">$fullRef</xr:Item>"
}
X "$i</Owners>"
} else {
X "$i<Owners/>"
}
$subordinationUse = Get-EnumProp "SubordinationUse" "subordinationUse" "ToItems"
X "$i<SubordinationUse>$subordinationUse</SubordinationUse>"
$codeLength = if ($null -ne $def.codeLength) { "$($def.codeLength)" } else { "9" }
$descriptionLength = if ($null -ne $def.descriptionLength) { "$($def.descriptionLength)" } else { "25" }
@@ -1093,7 +1117,8 @@ function Emit-CatalogProperties {
X "$i<DescriptionLength>$descriptionLength</DescriptionLength>"
X "$i<CodeType>$codeType</CodeType>"
X "$i<CodeAllowedLength>$codeAllowedLength</CodeAllowedLength>"
X "$i<CodeSeries>WholeCatalog</CodeSeries>"
$codeSeries = Get-EnumProp "CodeSeries" "codeSeries" "WholeCatalog"
X "$i<CodeSeries>$codeSeries</CodeSeries>"
X "$i<CheckUnique>$checkUnique</CheckUnique>"
X "$i<Autonumbering>$autonumbering</Autonumbering>"
@@ -1104,8 +1129,10 @@ function Emit-CatalogProperties {
X "$i<Characteristics/>"
X "$i<PredefinedDataUpdate>Auto</PredefinedDataUpdate>"
X "$i<EditType>InDialog</EditType>"
X "$i<QuickChoice>true</QuickChoice>"
X "$i<ChoiceMode>BothWays</ChoiceMode>"
$quickChoice = if ($def.quickChoice -eq $false) { "false" } else { "true" }
$choiceMode = Get-EnumProp "ChoiceMode" "choiceMode" "BothWays"
X "$i<QuickChoice>$quickChoice</QuickChoice>"
X "$i<ChoiceMode>$choiceMode</ChoiceMode>"
X "$i<InputByString>"
X "$i`t<xr:Field>Catalog.$objName.StandardAttribute.Description</xr:Field>"
X "$i`t<xr:Field>Catalog.$objName.StandardAttribute.Code</xr:Field>"
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# meta-compile v1.8 — Compile 1C metadata object from JSON
# meta-compile v1.10 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -147,8 +147,8 @@ enum_value_aliases = {
'RecordSubordinate': 'RecorderSubordinate', 'Subordinate': 'RecorderSubordinate',
'ПодчинениеРегистратору': 'RecorderSubordinate', 'Независимый': 'Independent',
# DependenceOnCalculationTypes (ChartOfCalculationTypes)
'NotDependOnCalculationTypes': 'DontUse', 'NoDependence': 'DontUse',
'Depend': 'RequireCalculationTypes', 'RequireCalculation': 'RequireCalculationTypes',
'NotDependOnCalculationTypes': 'DontUse', 'NoDependence': 'DontUse', 'NotUsed': 'DontUse',
'Depend': 'OnActionPeriod', 'ПоПериодуДействия': 'OnActionPeriod',
# InformationRegisterPeriodicity
'None': 'Nonperiodical', 'Daily': 'Day', 'Monthly': 'Month',
'Quarterly': 'Quarter', 'Yearly': 'Year',
@@ -177,7 +177,7 @@ valid_enum_values = {
'RegisterType': ['Balance', 'Turnovers'],
'WriteMode': ['Independent', 'RecorderSubordinate'],
'InformationRegisterPeriodicity': ['Nonperiodical', 'Second', 'Day', 'Month', 'Quarter', 'Year', 'RecorderPosition'],
'DependenceOnCalculationTypes': ['DontUse', 'RequireCalculationTypes'],
'DependenceOnCalculationTypes': ['DontUse', 'OnActionPeriod'],
'DataLockControlMode': ['Automatic', 'Managed'],
'FullTextSearch': ['Use', 'DontUse'],
'DataHistory': ['Use', 'DontUse'],
@@ -196,19 +196,25 @@ valid_enum_values = {
'ReuseSessions': ['DontUse', 'AutoUse'],
'FillChecking': ['DontCheck', 'ShowError', 'ShowWarning'],
'Indexing': ['DontIndex', 'Index', 'IndexWithAdditionalOrder'],
'SubordinationUse': ['ToItems', 'ToFolders', 'ToFoldersAndItems'],
'CodeSeries': ['WholeCatalog', 'WithinSubordination'],
'ChoiceMode': ['BothWays', 'QuickChoice', 'FromForm'],
}
def normalize_enum_value(prop_name, value):
# 1. Check alias dictionary
# 1. Check alias dictionary — silent auto-correct
if value in enum_value_aliases:
return enum_value_aliases[value]
# 2. Case-insensitive match against valid values
# 2. Case-insensitive match against valid values — silent
valid = valid_enum_values.get(prop_name)
if valid:
for v in valid:
if v.lower() == value.lower():
return v
# 3. Return as-is (validator will catch if wrong)
# 3. Known property, unknown value — error with hint
print(f"Invalid value '{value}' for property '{prop_name}'. Valid values: {', '.join(valid)}", file=sys.stderr)
sys.exit(1)
# 4. Unknown property — pass-through (no validation data)
return value
def get_enum_prop(prop_name, field_name, default):
@@ -458,6 +464,7 @@ def parse_attribute_shorthand(val):
'flags': list(val.get('flags', [])),
'fillChecking': str(val['fillChecking']) if val.get('fillChecking') else '',
'indexing': str(val['indexing']) if val.get('indexing') else '',
'multiLine': True if val.get('multiLine') is True else False,
}
def parse_enum_value_shorthand(val):
@@ -722,7 +729,7 @@ RESERVED_ATTR_NAMES_RU = {
def emit_attribute(indent, parsed, context):
attr_name = parsed['name']
if attr_name in RESERVED_ATTR_NAMES or attr_name in RESERVED_ATTR_NAMES_RU:
if context not in ('tabular', 'processor-tabular') and (attr_name in RESERVED_ATTR_NAMES or attr_name in RESERVED_ATTR_NAMES_RU):
print(f"WARNING: Attribute '{attr_name}' conflicts with a standard attribute name. This may cause errors when loading into 1C.", file=sys.stderr)
uid = new_uuid()
X(f'{indent}<Attribute uuid="{uid}">')
@@ -743,7 +750,8 @@ def emit_attribute(indent, parsed, context):
X(f'{indent}\t\t<ToolTip/>')
X(f'{indent}\t\t<MarkNegatives>false</MarkNegatives>')
X(f'{indent}\t\t<Mask/>')
X(f'{indent}\t\t<MultiLine>false</MultiLine>')
multi_line = 'true' if (parsed.get('multiLine') is True or 'multiline' in parsed.get('flags', [])) else 'false'
X(f'{indent}\t\t<MultiLine>{multi_line}</MultiLine>')
X(f'{indent}\t\t<ExtendedEdit>false</ExtendedEdit>')
X(f'{indent}\t\t<MinValue xsi:nil="true"/>')
X(f'{indent}\t\t<MaxValue xsi:nil="true"/>')
@@ -861,7 +869,8 @@ def emit_dimension(indent, parsed, register_type):
X(f'{indent}\t\t<ToolTip/>')
X(f'{indent}\t\t<MarkNegatives>false</MarkNegatives>')
X(f'{indent}\t\t<Mask/>')
X(f'{indent}\t\t<MultiLine>false</MultiLine>')
multi_line = 'true' if (parsed.get('multiLine') is True or 'multiline' in parsed.get('flags', [])) else 'false'
X(f'{indent}\t\t<MultiLine>{multi_line}</MultiLine>')
X(f'{indent}\t\t<ExtendedEdit>false</ExtendedEdit>')
X(f'{indent}\t\t<MinValue xsi:nil="true"/>')
X(f'{indent}\t\t<MaxValue xsi:nil="true"/>')
@@ -934,7 +943,8 @@ def emit_resource(indent, parsed, register_type):
X(f'{indent}\t\t<ToolTip/>')
X(f'{indent}\t\t<MarkNegatives>false</MarkNegatives>')
X(f'{indent}\t\t<Mask/>')
X(f'{indent}\t\t<MultiLine>false</MultiLine>')
multi_line = 'true' if (parsed.get('multiLine') is True or 'multiline' in parsed.get('flags', [])) else 'false'
X(f'{indent}\t\t<MultiLine>{multi_line}</MultiLine>')
X(f'{indent}\t\t<ExtendedEdit>false</ExtendedEdit>')
X(f'{indent}\t\t<MinValue xsi:nil="true"/>')
X(f'{indent}\t\t<MaxValue xsi:nil="true"/>')
@@ -976,12 +986,24 @@ def emit_catalog_properties(indent):
hierarchy_type = get_enum_prop('HierarchyType', 'hierarchyType', 'HierarchyFoldersAndItems')
X(f'{i}<Hierarchical>{hierarchical}</Hierarchical>')
X(f'{i}<HierarchyType>{hierarchy_type}</HierarchyType>')
X(f'{i}<LimitLevelCount>false</LimitLevelCount>')
X(f'{i}<LevelCount>2</LevelCount>')
X(f'{i}<FoldersOnTop>true</FoldersOnTop>')
limit_level_count = 'true' if defn.get('limitLevelCount') is True else 'false'
level_count = str(defn['levelCount']) if defn.get('levelCount') is not None else '2'
folders_on_top = 'false' if defn.get('foldersOnTop') is False else 'true'
X(f'{i}<LimitLevelCount>{limit_level_count}</LimitLevelCount>')
X(f'{i}<LevelCount>{level_count}</LevelCount>')
X(f'{i}<FoldersOnTop>{folders_on_top}</FoldersOnTop>')
X(f'{i}<UseStandardCommands>true</UseStandardCommands>')
X(f'{i}<Owners/>')
X(f'{i}<SubordinationUse>ToItems</SubordinationUse>')
owners = defn.get('owners', [])
if owners:
X(f'{i}<Owners>')
for owner_ref in owners:
full_ref = owner_ref if '.' in str(owner_ref) else f'Catalog.{owner_ref}'
X(f'{i}\t<xr:Item xsi:type="xr:MDObjectRef">{full_ref}</xr:Item>')
X(f'{i}</Owners>')
else:
X(f'{i}<Owners/>')
subordination_use = get_enum_prop('SubordinationUse', 'subordinationUse', 'ToItems')
X(f'{i}<SubordinationUse>{subordination_use}</SubordinationUse>')
code_length = str(defn['codeLength']) if defn.get('codeLength') is not None else '9'
description_length = str(defn['descriptionLength']) if defn.get('descriptionLength') is not None else '25'
code_type = get_enum_prop('CodeType', 'codeType', 'String')
@@ -992,7 +1014,8 @@ def emit_catalog_properties(indent):
X(f'{i}<DescriptionLength>{description_length}</DescriptionLength>')
X(f'{i}<CodeType>{code_type}</CodeType>')
X(f'{i}<CodeAllowedLength>{code_allowed_length}</CodeAllowedLength>')
X(f'{i}<CodeSeries>WholeCatalog</CodeSeries>')
code_series = get_enum_prop('CodeSeries', 'codeSeries', 'WholeCatalog')
X(f'{i}<CodeSeries>{code_series}</CodeSeries>')
X(f'{i}<CheckUnique>{check_unique}</CheckUnique>')
X(f'{i}<Autonumbering>{autonumbering}</Autonumbering>')
default_presentation = get_enum_prop('DefaultPresentation', 'defaultPresentation', 'AsDescription')
@@ -1001,8 +1024,10 @@ def emit_catalog_properties(indent):
X(f'{i}<Characteristics/>')
X(f'{i}<PredefinedDataUpdate>Auto</PredefinedDataUpdate>')
X(f'{i}<EditType>InDialog</EditType>')
X(f'{i}<QuickChoice>true</QuickChoice>')
X(f'{i}<ChoiceMode>BothWays</ChoiceMode>')
quick_choice = 'false' if defn.get('quickChoice') is False else 'true'
choice_mode = get_enum_prop('ChoiceMode', 'choiceMode', 'BothWays')
X(f'{i}<QuickChoice>{quick_choice}</QuickChoice>')
X(f'{i}<ChoiceMode>{choice_mode}</ChoiceMode>')
X(f'{i}<InputByString>')
X(f'{i}\t<xr:Field>Catalog.{obj_name}.StandardAttribute.Description</xr:Field>')
X(f'{i}\t<xr:Field>Catalog.{obj_name}.StandardAttribute.Code</xr:Field>')
+34 -16
View File
@@ -1,4 +1,4 @@
# meta-edit v1.5 — Edit existing 1C metadata object XML (inline mode + complex properties + TS attribute ops + modify-ts)
# meta-edit v1.6 — Edit existing 1C metadata object XML (inline mode + complex properties + TS attribute ops + modify-ts)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[string]$DefinitionFile,
@@ -48,47 +48,65 @@ $script:enumValueAliases = @{
"Balances" = "Balance"; "Остатки" = "Balance"; "Обороты" = "Turnovers"
"RecordSubordinate" = "RecorderSubordinate"; "Subordinate" = "RecorderSubordinate"
"ПодчинениеРегистратору" = "RecorderSubordinate"; "Независимый" = "Independent"
"NotDependOnCalculationTypes" = "DontUse"; "NoDependence" = "DontUse"
"NotDependOnCalculationTypes" = "DontUse"; "NoDependence" = "DontUse"; "NotUsed" = "DontUse"
"Depend" = "OnActionPeriod"; "ПоПериодуДействия" = "OnActionPeriod"
"None" = "Nonperiodical"; "Daily" = "Day"; "Monthly" = "Month"
"Quarterly" = "Quarter"; "Yearly" = "Year"
"Непериодический" = "Nonperiodical"; "День" = "Day"; "Месяц" = "Month"
"Непериодический" = "Nonperiodical"; "Секунда" = "Second"; "День" = "Day"; "Месяц" = "Month"
"Квартал" = "Quarter"; "Год" = "Year"
"ПозицияРегистратора" = "RecorderPosition"
"Автоматический" = "Automatic"; "Управляемый" = "Managed"
"Использовать" = "Use"; "НеИспользовать" = "DontUse"
"Разрешить" = "Allow"; "Запретить" = "Deny"
"ВДиалоге" = "InDialog"; "ВСписке" = "InList"; "ОбаСпособа" = "BothWays"
"ВВидеНаименования" = "AsDescription"; "ВВидеКода" = "AsCode"
"НеПроверять" = "DontCheck"; "Ошибка" = "ShowError"; "Предупреждение" = "ShowWarning"
"НеИндексировать" = "DontIndex"; "Индексировать" = "Index"
"ИндексироватьСДопУпорядочиванием" = "IndexWithAdditionalOrder"
}
$script:validEnumValues = @{
"RegisterType" = @("Balance","Turnovers")
"WriteMode" = @("Independent","RecorderSubordinate")
"RegisterType" = @("Balance","Turnovers")
"WriteMode" = @("Independent","RecorderSubordinate")
"InformationRegisterPeriodicity" = @("Nonperiodical","Second","Day","Month","Quarter","Year","RecorderPosition")
"DependenceOnCalculationTypes" = @("DontUse","RequireCalculationTypes")
"DataLockControlMode" = @("Automatic","Managed")
"FullTextSearch" = @("Use","DontUse")
"DataHistory" = @("Use","DontUse")
"DefaultPresentation" = @("AsDescription","AsCode")
"Posting" = @("Allow","Deny")
"RealTimePosting" = @("Allow","Deny")
"EditType" = @("InDialog","InList","BothWays")
"HierarchyType" = @("HierarchyFoldersAndItems","HierarchyItemsOnly")
"FillChecking" = @("DontCheck","ShowError","ShowWarning")
"Indexing" = @("DontIndex","Index","IndexWithAdditionalOrder")
"DependenceOnCalculationTypes" = @("DontUse","OnActionPeriod")
"DataLockControlMode" = @("Automatic","Managed")
"FullTextSearch" = @("Use","DontUse")
"DataHistory" = @("Use","DontUse")
"DefaultPresentation" = @("AsDescription","AsCode")
"Posting" = @("Allow","Deny")
"RealTimePosting" = @("Allow","Deny")
"EditType" = @("InDialog","InList","BothWays")
"HierarchyType" = @("HierarchyFoldersAndItems","HierarchyItemsOnly")
"CodeType" = @("String","Number")
"CodeAllowedLength" = @("Variable","Fixed")
"NumberType" = @("String","Number")
"NumberAllowedLength" = @("Variable","Fixed")
"RegisterRecordsDeletion" = @("AutoDelete","AutoDeleteOnUnpost","AutoDeleteOff")
"RegisterRecordsWritingOnPost" = @("WriteModified","WriteSelected","WriteAll")
"ReturnValuesReuse" = @("DontUse","DuringRequest","DuringSession")
"ReuseSessions" = @("DontUse","AutoUse")
"FillChecking" = @("DontCheck","ShowError","ShowWarning")
"Indexing" = @("DontIndex","Index","IndexWithAdditionalOrder")
}
function Normalize-EnumValue {
param([string]$propName, [string]$value)
# 1. Check alias dictionary — silent auto-correct
if ($script:enumValueAliases.ContainsKey($value)) {
return $script:enumValueAliases[$value]
}
# 2. Case-insensitive match against valid values — silent
$valid = $script:validEnumValues[$propName]
if ($valid) {
foreach ($v in $valid) {
if ($v -ieq $value) { return $v }
}
# 3. Known property, unknown value — error with hint
Write-Error "Invalid value '$value' for property '$propName'. Valid values: $($valid -join ', ')"
exit 1
}
# 4. Unknown property — pass-through (no validation data)
return $value
}
+10 -7
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# meta-edit v1.5 — Edit existing 1C metadata object XML (inline mode + complex properties + TS attribute ops + modify-ts)
# meta-edit v1.6 — Edit existing 1C metadata object XML (inline mode + complex properties + TS attribute ops + modify-ts)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -88,8 +88,8 @@ enum_value_aliases = {
'RecordSubordinate': 'RecorderSubordinate', 'Subordinate': 'RecorderSubordinate',
'ПодчинениеРегистратору': 'RecorderSubordinate', 'Независимый': 'Independent',
# DependenceOnCalculationTypes (ChartOfCalculationTypes)
'NotDependOnCalculationTypes': 'DontUse', 'NoDependence': 'DontUse',
'Depend': 'RequireCalculationTypes', 'RequireCalculation': 'RequireCalculationTypes',
'NotDependOnCalculationTypes': 'DontUse', 'NoDependence': 'DontUse', 'NotUsed': 'DontUse',
'Depend': 'OnActionPeriod', 'ПоПериодуДействия': 'OnActionPeriod',
# InformationRegisterPeriodicity
'None': 'Nonperiodical', 'Daily': 'Day', 'Monthly': 'Month',
'Quarterly': 'Quarter', 'Yearly': 'Year',
@@ -117,7 +117,7 @@ valid_enum_values = {
'RegisterType': ['Balance', 'Turnovers'],
'WriteMode': ['Independent', 'RecorderSubordinate'],
'InformationRegisterPeriodicity': ['Nonperiodical', 'Second', 'Day', 'Month', 'Quarter', 'Year', 'RecorderPosition'],
'DependenceOnCalculationTypes': ['DontUse', 'RequireCalculationTypes'],
'DependenceOnCalculationTypes': ['DontUse', 'OnActionPeriod'],
'DataLockControlMode': ['Automatic', 'Managed'],
'FullTextSearch': ['Use', 'DontUse'],
'DataHistory': ['Use', 'DontUse'],
@@ -140,16 +140,19 @@ valid_enum_values = {
def normalize_enum_value(prop_name, value):
# 1. Check alias dictionary
# 1. Check alias dictionary — silent auto-correct
if value in enum_value_aliases:
return enum_value_aliases[value]
# 2. Case-insensitive match against valid values
# 2. Case-insensitive match against valid values — silent
valid = valid_enum_values.get(prop_name)
if valid:
for v in valid:
if v.lower() == value.lower():
return v
# 3. Return as-is (validator will catch if wrong)
# 3. Known property, unknown value — error with hint
print(f"Invalid value '{value}' for property '{prop_name}'. Valid values: {', '.join(valid)}", file=sys.stderr)
sys.exit(1)
# 4. Unknown property — pass-through (no validation data)
return value
@@ -262,7 +262,7 @@ $validPropertyValues = @{
"FillChecking" = @("DontCheck","ShowError","ShowWarning")
"Indexing" = @("DontIndex","Index","IndexWithAdditionalOrder")
"DataHistory" = @("Use","DontUse")
"DependenceOnCalculationTypes" = @("DontUse","RequireCalculationTypes")
"DependenceOnCalculationTypes" = @("DontUse","OnActionPeriod")
}
# Properties forbidden per type (would cause LoadConfigFromFiles error)
@@ -263,7 +263,7 @@ valid_property_values = {
"FillChecking": ["DontCheck", "ShowError", "ShowWarning"],
"Indexing": ["DontIndex", "Index", "IndexWithAdditionalOrder"],
"DataHistory": ["Use", "DontUse"],
"DependenceOnCalculationTypes": ["DontUse", "RequireCalculationTypes"],
"DependenceOnCalculationTypes": ["DontUse", "OnActionPeriod"],
}
# Properties forbidden per type (would cause LoadConfigFromFiles error)
+8
View File
@@ -148,6 +148,7 @@ JSON DSL для описания объектов метаданных конф
| `req` | FillChecking = ShowError | attributes, dimensions, resources |
| `index` | Indexing = Index | attributes, dimensions |
| `indexAdditional` | Indexing = IndexWithAdditionalOrder | attributes |
| `multiline` | MultiLine = true | attributes |
| `nonneg` | MinValue = 0 (+ nonneg для Number) | attributes, resources |
| `master` | Master = true | dimensions (РС) |
| `mainFilter` | MainFilter = true | dimensions (РС) |
@@ -206,13 +207,20 @@ JSON DSL для описания объектов метаданных конф
|-----------|----------|-------------|
| `hierarchical` | `false` | Hierarchical |
| `hierarchyType` | `HierarchyFoldersAndItems` | HierarchyType |
| `limitLevelCount` | `false` | LimitLevelCount |
| `levelCount` | `2` | LevelCount |
| `foldersOnTop` | `true` | FoldersOnTop |
| `codeLength` | `9` | CodeLength |
| `codeType` | `String` | CodeType |
| `codeAllowedLength` | `Variable` | CodeAllowedLength |
| `codeSeries` | `WholeCatalog` | CodeSeries |
| `descriptionLength` | `25` | DescriptionLength |
| `autonumbering` | `true` | Autonumbering |
| `checkUnique` | `false` | CheckUnique |
| `defaultPresentation` | `AsDescription` | DefaultPresentation |
| `subordinationUse` | `ToItems` | SubordinationUse |
| `quickChoice` | `true` | QuickChoice |
| `choiceMode` | `BothWays` | ChoiceMode |
| `dataLockControlMode` | `Automatic` | DataLockControlMode |
| `fullTextSearch` | `Use` | FullTextSearch |
| `owners` | `[]` | Owners |