From c0acb52cf6e3d75c004bdb9755f4a71648d16936 Mon Sep 17 00:00:00 2001 From: Repinoid Date: Wed, 21 Oct 2026 15:51:34 +0300 Subject: [PATCH] Clarify lst glob semantics and tests --- PLAN-LST-FILTER.md | 58 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/PLAN-LST-FILTER.md b/PLAN-LST-FILTER.md index 24e77c9..3995f60 100644 --- a/PLAN-LST-FILTER.md +++ b/PLAN-LST-FILTER.md @@ -19,7 +19,7 @@ - пути относительны к выбранной папке; - абсолютные пути и сегменты `..` запрещены; - разделители `\` нормализуются в `/`; -- расширения сравниваются без учёта регистра; +- весь путь сравнивается без учёта регистра; - несколько совпавших правил не создают дубли. Пример: @@ -44,10 +44,16 @@ reports/name*.docx Семантика: -- `*.pdf` — PDF в выбранной папке и подпапках; +- `*.pdf` — PDF только в корне выбранной папки; - `reports/*.pdf` — PDF внутри `reports`; - `**/*.pdf` — PDF на любой глубине; -- `name*.pdf` — файлы с префиксом `name`. +- `name*.pdf` — файлы с префиксом `name` в корне; +- `reports/name*.pdf` — файлы с префиксом `name` непосредственно в `reports`; +- `reports/` — то же, что `reports/**`; +- `a**b` — две звёздочки внутри сегмента работают как обычная `*`. + +Правило без `/` не применяется рекурсивно. Для поиска на любой глубине нужно +явно использовать `**/`, например `**/*.pdf`. Положительные правила формируют набор кандидатов. Отрицательные правила удаляют совпавшие файлы из результата. @@ -56,7 +62,9 @@ reports/name*.docx 1. Получить все файлы выбранной папки и подпапок через `webkitdirectory`. 2. Нормализовать `webkitRelativePath`, убрав имя корневой выбранной папки. -3. Найти `.lst` только в корне выбранной папки, без учёта регистра. +3. Найти `.lst` только в корне выбранной папки, без учёта регистра. Если найдено + несколько `.lst`, использовать первый в стабильном алфавитном порядке и + показать предупреждение. 4. Если `.lst` нет, передать в текущую логику все поддерживаемые файлы. 5. Если `.lst` найден: - прочитать UTF-8 и убрать BOM; @@ -80,6 +88,21 @@ reports/name*.docx Содержимое ZIP отдельно не фильтровать: ZIP выбирается как один файл и далее обрабатывается существующим механизмом раскрытия архивов. +## Нормализация и предупреждения + +Перед сопоставлением: + +- заменить `\` на `/`; +- убрать ведущие `./`; +- свернуть повторные `/`; +- убрать имя корневой выбранной папки из `webkitRelativePath`; +- отклонить абсолютные пути, сегменты `..` и пустые правила; +- отклонить незакрытые классы `[` с указанием номера строки. + +Ошибки и предупреждения передавать через существующий `cfg.onError` или +`statusEl`. Ошибка одного правила не должна останавливать остальные правила. +Ошибка чтения или декодирования `.lst` даёт предупреждение и пустой результат. + ## Где менять код Алгоритм фильтра вынести в чистый модуль рядом с текущим picker, например: @@ -100,17 +123,22 @@ upload/frontend/table/lst_filter.js 1. Папка без `.lst` сохраняет старое поведение. 2. `.lst` не попадает в результат. 3. `*.pdf`, `name*.pdf`, `?`, `**` и классы символов. -4. Положительные и отрицательные правила вместе. -5. Комментарии, пустые строки, BOM, CRLF и пробелы. -6. Регистр расширения (`A.PDF` совпадает с `*.pdf`). -7. Кириллицу, пробелы и вложенные каталоги. -8. Дубли и перекрывающиеся маски. -9. Запрет `/etc/x`, `C:/x`, `../x`, `a/../b`. -10. Битую маску без падения всего picker. -11. Правило без совпадений с предупреждением. -12. Только отрицательные или полностью битые правила дают пустой результат. -13. `.lst` во вложенной папке не включает manifest-режим. -14. ZIP выбирается целиком, без фильтрации его внутреннего содержимого. +4. `*.pdf` совпадает только с файлом в корне, а `**/*.pdf` — также с `x.pdf` + в корне и файлами в подпапках. +5. `docs/name*.pdf`, `docs/`, `a**b` и точные пути. +6. Положительные и отрицательные правила вместе. +7. Комментарии, пустые строки, BOM, CRLF и пробелы. +8. Регистр всего пути (`DOCS/A.PDF` совпадает с `docs/*.pdf`). +9. Кириллицу, пробелы, вложенные каталоги и обратные слеши (`docs\a.pdf`). +10. Дубли и перекрывающиеся маски. +11. Запрет `/etc/x`, `C:/x`, `../x`, `a/../b`. +12. Битую маску без падения всего picker. +13. Ошибка чтения `.lst` даёт пустой результат и предупреждение. +14. Правило без совпадений даёт предупреждение. +15. Только отрицательные или полностью битые правила дают пустой результат. +16. Несколько `.lst` дают предупреждение и используют первый по имени. +17. `.lst` во вложенной папке не включает manifest-режим. +18. ZIP выбирается целиком, без фильтрации его внутреннего содержимого. ## Ограничения реализации