Plan lst file filtering

This commit is contained in:
Repinoid
2026-10-21 15:49:29 +03:00
parent 02fe39e52c
commit ce44143a09
+121
View File
@@ -0,0 +1,121 @@
# План: фильтрация файлов через `.lst`
## Цель
Добавить в file picker режим manifest-фильтра:
- пользователь выбирает папку целиком;
- если в корне выбранной папки есть `.lst`, он ограничивает набор файлов;
- если `.lst` нет, сохраняется текущее поведение: выбираются все поддерживаемые файлы;
- сам `.lst` никогда не отправляется на обработку.
## Правила `.lst`
Одна строка — одно правило.
- пустые строки игнорируются;
- строки, начинающиеся с `#`, являются комментариями;
- `!` в начале строки означает отрицательное правило;
- пути относительны к выбранной папке;
- абсолютные пути и сегменты `..` запрещены;
- разделители `\` нормализуются в `/`;
- расширения сравниваются без учёта регистра;
- несколько совпавших правил не создают дубли.
Пример:
```text
*.pdf
reports/name*.docx
!archive/**
!**/*draft*.*
```
## Glob-маски
Поддержать общепринятые шаблоны:
- `*` — любое количество символов, кроме `/`;
- `?` — один символ, кроме `/`;
- `**` — любое количество каталогов;
- `[abc]` и `[a-z]` — классы и диапазоны символов;
- `[!a]` и `[^a]` — отрицательные классы;
- обычный путь без glob-символов — точное совпадение.
Семантика:
- `*.pdf` — PDF в выбранной папке и подпапках;
- `reports/*.pdf` — PDF внутри `reports`;
- `**/*.pdf` — PDF на любой глубине;
- `name*.pdf` — файлы с префиксом `name`.
Положительные правила формируют набор кандидатов. Отрицательные правила
удаляют совпавшие файлы из результата.
## Алгоритм
1. Получить все файлы выбранной папки и подпапок через `webkitdirectory`.
2. Нормализовать `webkitRelativePath`, убрав имя корневой выбранной папки.
3. Найти `.lst` только в корне выбранной папки, без учёта регистра.
4. Если `.lst` нет, передать в текущую логику все поддерживаемые файлы.
5. Если `.lst` найден:
- прочитать UTF-8 и убрать BOM;
- разобрать строки и скомпилировать glob в RegExp;
- отбросить некорректные правила с предупреждением и номером строки;
- выбрать поддерживаемые файлы, совпавшие хотя бы с одним положительным правилом;
- удалить совпадения с отрицательными правилами;
- удалить `.lst` из результата;
- сохранить исходный порядок файлов и убрать дубли по нормализованному пути.
6. Передать итоговый список в существующий цикл построения таблицы без изменений.
Если все положительные правила отсутствуют или некорректны, результат пустой.
Автоматический fallback на все файлы запрещён.
Если положительное правило не совпало ни с одним файлом, показать предупреждение,
но продолжить обработку остальных правил. Неподдерживаемые файлы не добавлять.
`.lst` во вложенной папке не является manifest-фильтром и обрабатывается как
обычный неподдерживаемый файл.
Содержимое ZIP отдельно не фильтровать: ZIP выбирается как один файл и далее
обрабатывается существующим механизмом раскрытия архивов.
## Где менять код
Алгоритм фильтра вынести в чистый модуль рядом с текущим picker, например:
```text
upload/frontend/table/lst_filter.js
```
Точка подключения — `on_folder_change.js`, до существующего цикла построения
дерева. DOM и upload-транспорт в модуль фильтра не добавлять.
Сборочные `site/static/dist/*.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 выбирается целиком, без фильтрации его внутреннего содержимого.
## Ограничения реализации
- Не менять backend-контракт.
- Не добавлять базу данных, отдельный сервис или новый формат конфигурации.
- Не переписывать существующий picker.
- Изменить минимальное число файлов.
- Сначала реализовать алгоритм и тесты, затем обновить dist штатной сборкой.