diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index 83d903a0..0004c3bf 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.132 — Compile 1C managed form from JSON or object metadata +# form-compile v1.133 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, @@ -1627,6 +1627,8 @@ $script:comparisonTypes = @{ "inHierarchy" = "InHierarchy"; "inListByHierarchy" = "InListByHierarchy" "contains" = "Contains"; "notContains" = "NotContains" "beginsWith" = "BeginsWith"; "notBeginsWith" = "NotBeginsWith" + "like" = "Like"; "notLike" = "NotLike" + "подобно" = "Like"; "неподобно" = "NotLike" # рус. синоним (хэш регистронезависим: ПОДОБНО=подобно) "filled" = "Filled"; "notFilled" = "NotFilled" } @@ -1642,6 +1644,7 @@ function Parse-FilterShorthand { $opPatterns = @('<>', '>=', '<=', '=', '>', '<', 'notIn\b', 'in\b', 'inHierarchy\b', 'inListByHierarchy\b', 'notContains\b', 'contains\b', 'notBeginsWith\b', 'beginsWith\b', + 'notLike\b', 'like\b', 'неподобно\b', 'подобно\b', 'notFilled\b', 'filled\b') $opJoined = $opPatterns -join '|' if ($s -match "^(.+?)\s+($opJoined)\s*(.*)?$") { diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index e2e759df..b6e7c27e 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.132 — Compile 1C managed form from JSON or object metadata +# form-compile v1.133 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -1333,8 +1333,12 @@ COMPARISON_TYPES = { 'inHierarchy': 'InHierarchy', 'inListByHierarchy': 'InListByHierarchy', 'contains': 'Contains', 'notContains': 'NotContains', 'beginsWith': 'BeginsWith', 'notBeginsWith': 'NotBeginsWith', + 'like': 'Like', 'notLike': 'NotLike', + 'подобно': 'Like', 'неподобно': 'NotLike', # рус. синоним 'filled': 'Filled', 'notFilled': 'NotFilled', } +# Регистронезависимый лукап (зеркало PS-хэша): Like/LIKE/ПОДОБНО → канон +_COMPARISON_TYPES_CI = {k.lower(): v for k, v in COMPARISON_TYPES.items()} _REF_TYPE_RE = re.compile( r'^(Перечисление|Справочник|ПланСчетов|Документ|ПланВидовХарактеристик|ПланВидовРасчета|' @@ -1365,9 +1369,10 @@ def parse_filter_shorthand(s): op_patterns = ['<>', '>=', '<=', '=', '>', '<', r'notIn\b', r'in\b', r'inHierarchy\b', r'inListByHierarchy\b', r'notContains\b', r'contains\b', r'notBeginsWith\b', r'beginsWith\b', + r'notLike\b', r'like\b', r'неподобно\b', r'подобно\b', r'notFilled\b', r'filled\b'] op_joined = '|'.join(op_patterns) - m = re.match(r'^(.+?)\s+(' + op_joined + r')\s*(.*)?$', s) + m = re.match(r'^(.+?)\s+(' + op_joined + r')\s*(.*)?$', s, re.IGNORECASE) if m: result['field'] = m.group(1).strip() result['op'] = m.group(2).strip() @@ -1449,7 +1454,8 @@ def emit_filter_item(lines, item, indent): if item.get('use') is False: lines.append(f'{indent}\tfalse') lines.append(f'{indent}\t{esc_xml(str(item.get("field", "")))}') - comp_type = COMPARISON_TYPES.get(str(item.get('op'))) + # Регистронезависимый лукап (зеркало PS): Like/LIKE/ПОДОБНО → канон; иначе — как есть + comp_type = _COMPARISON_TYPES_CI.get(str(item.get('op')).lower()) if not comp_type: comp_type = str(item.get('op')) lines.append(f'{indent}\t{esc_xml(comp_type)}') diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1 index 087fef4f..be13bf9d 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.106 — Decompile 1C managed Form.xml to JSON DSL (draft) +# form-decompile v0.107 — Decompile 1C managed Form.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью. param( @@ -458,6 +458,7 @@ $script:filterOpMap = @{ 'InHierarchy'='inHierarchy'; 'InListByHierarchy'='inListByHierarchy'; 'Contains'='contains'; 'NotContains'='notContains'; 'BeginsWith'='beginsWith'; 'NotBeginsWith'='notBeginsWith'; + 'Like'='like'; 'NotLike'='notLike'; 'Filled'='filled'; 'NotFilled'='notFilled' } diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md index 01fe2839..ee561597 100644 --- a/docs/form-dsl-spec.md +++ b/docs/form-dsl-spec.md @@ -990,6 +990,7 @@ Forgiving-синонимы типа: XML-имя (`SpreadSheetDocumentField`) и - **order** — строка `"Поле"` (asc) / `"Поле desc"` (синонимы `убыв`/`desc`, `возр`/`asc`) / `"Auto"`, либо объект `{ field, direction?, use?, viewMode? }`. - **filter** — shorthand `"Поле оператор значение @флаги"` (`@off`, `@user`, `@quickAccess`, `@normal`, `@inaccessible`; `_` = пусто) или объект `{ field, op, value?, use?, userSettingID? }` или группа `{ group: "And"|"Or"|"Not", items: [...] }`. + - **Операторы:** `=` `<>` `>` `>=` `<` `<=`, `in`/`notIn`, `inHierarchy`/`inListByHierarchy`, `contains`/`notContains`, `beginsWith`/`notBeginsWith`, `like`/`notLike` (подобно; `%`-шаблон в значении, напр. `"КодВалют like %/ %"`), `filled`/`notFilled`. Регистр оператора не важен; у `like`/`notLike` есть рус. синоним `подобно`/`неподобно`. - **Дата в фильтре = `StandardBeginningDate`** (так платформа хранит дату-значение почти всегда — корпус 268 vs 2 `xs:dateTime`). Формы значения (от компактной к полной): - **голая ISO-дата** `"2020-01-01T00:00:00"` (без `valueType`) → `Custom` + эта дата. Работает и в shorthand: `"ДатаЗаказа > 2020-01-01T00:00:00"`. Это дефолт даты в фильтре. - **строка-вариант** `"BeginningOfThisDay"` + `valueType: "v8:StandardBeginningDate"` — именованный вариант без даты (`BeginningOfThisWeek`/`BeginningOfThisYear`/…; имя ≠ дата, нужен `valueType`). diff --git a/tests/skills/cases/form-compile/dynamic-list-form.json b/tests/skills/cases/form-compile/dynamic-list-form.json index 8210e303..8d03f38b 100644 --- a/tests/skills/cases/form-compile/dynamic-list-form.json +++ b/tests/skills/cases/form-compile/dynamic-list-form.json @@ -20,7 +20,7 @@ { "name": "Список", "type": "DynamicList", "useAlways": ["~Артикул", "Список.Code", "Description"], "settings": { "mainTable": "Catalog.Товары", "dynamicDataRead": true, "autoSaveUserSettings": false, "order": [ "Description", "Code desc" ], - "filter": [ "Артикул = _ @off @user" ], + "filter": [ "Артикул = _ @off @user", "Артикул like %тест%", "Description подобно %abc%" ], "conditionalAppearance": [ { "filter": ["Артикул = _"], "appearance": { "ЦветТекста": "web:Red" } } ] } } ], diff --git a/tests/skills/cases/form-compile/snapshots/dynamic-list-form/Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml b/tests/skills/cases/form-compile/snapshots/dynamic-list-form/Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml index fdb205d7..c52430b9 100644 --- a/tests/skills/cases/form-compile/snapshots/dynamic-list-form/Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml +++ b/tests/skills/cases/form-compile/snapshots/dynamic-list-form/Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml @@ -110,6 +110,16 @@ Equal UUID-002 + + Артикул + Like + %тест% + + + Description + Like + %abc% + Normal UUID-003