Усі записи

Поле, яке гасить вісь, а не перелічує знайдене

Заморожений контракт пошуку розконсервовано: фільтри скасовано, додано український стемер, а сам пошук повернувся шаром над віссю — за 2426 байтів JavaScript.

Пошук стояв під шапкою відтоді, як репозиторію було чотири дні: модуль, якого ніхто не імпортував, збережений і покритий тестами навмисно, під правилом проєкту, що забороняло і видаляти його, і видавати пошук за доступний. Цей прохід зняв шапку у два кроки — спершу контракт, потім те, чим читач може користуватися.

Фільтри не побудовано, а скасовано

Заморожений модуль мав дві половини. Одна — пошук по тексту; друга — набір фільтрів: обрати організації, обрати людей, АБО всередині групи та І між групами, з обходом зв’язків owned_by і developed_by, щоб вибір компанії захоплював і зроблені нею моделі.

Фільтри пішли. Не відкладено вкотре — скасовано. Читач, який шукає OpenAI, друкує «OpenAI»; він не відкриває форму, щоб знайти організацію в списку з кількох сотень і поставити позначку. Ті самі імена в пошуковому тексті роблять ту саму роботу взагалі без інтерфейсу, а обхід графа існував лише заради фасетів. Третя гілка шукала по tags, а колекція не має жодного: 483 записи, нуль тегів. Ця гілка ніколи нічого не знаходила.

Лишилася одна група токенів, поєднаних через І, по назвах, коротких описах та іменах, які згадує запис.

Індексу немає, бо перебір і так швидший за кадр

Очевидний вибір для пошуку на статичному сайті — Pagefind, а до нього MiniSearch, FlexSearch, Fuse чи Orama. Жоден тут себе не виправдовує.

483 записи відповідають на запит із чотирьох токенів за 0,07 мс простим перебором. Префіксне дерево чи таблиця BM25 купили б ранжування, якого цей інтерфейс не використовує — результати тут не список, який треба впорядкувати, а позначки, що зберігають своє місце в часі, — і витратили б байти на проблему, якої немає. Pagefind був найближчим до вибору й не підійшов з іншої причини: він індексує відрендерений HTML і повертає URL сторінок. Осі потрібні ідентифікатори записів, щоб підсвітити позначки. Список посилань поруч із віссю — це друга навігація, а не пошук по першій.

Наперед обчислюється те, по чому шукають, бо стемінг — повільна половина: 12,8 мс один раз, коли приходить відкладений текст, далі 0,15–0,26 мс на натискання клавіші.

Українська — причина, чому стемер узагалі потрібен

Мова відмінює суфікс. «Модель», «моделі» й «моделями» — одне слово для читача і три для підрядкового збігу, а читач, який друкує будь-яке з них, має на увазі всі три. Англійська відмінює додаванням у кінці, що вже покриває префіксний збіг, тож для неї стемера немає.

У Snowball української немає взагалі — а це тихо відкидає Pagefind і кожного іншого споживача rust-stemmers, бо для головної мови атласу вони відкотилися б до повної відсутності стемінгу. Orama постачає стемер окремим модулем без залежностей: 731 байт у стисненому вигляді. Його вендорено байт-у-байт, а не встановлено, бо пакет несе двадцять вісім мов, щоб дати одну, і виключено з Prettier, щоб він лишався тотожним випуску, з якого прийшов.

Він приносить із собою одну річ, яку варто знати. «Роботи» — праці, у родовому відмінку — і «робот» мають спільну основу. Пошук роботів повертає записи про наукову роботу. Це те, чим стемінг є, а не хиба в підключенні; розвести їх зможе тема, за якою вісь уже розфарбована.

У розкладці не було місця, тож поле його й не займає

Панель зміряна до пікселя: нижче 420px вона вже віддала лічильник записів, нижче 380px — скидання. Сітка під нею віддає смузі кожен решту рядок, а саме це міряє прийомка першого екрана. Рядка, куди можна було б покласти поле пошуку, не забравши його в одного з цих двох, не існувало.

Тому панель плаває над смугою, кнопка, що її відкриває, нижче 420px стає гліфом, зберігаючи доступне ім’я, а результати не перелічуються взагалі. Позначки-збіги лишаються яскравими, решта падає до 22%, а підпис називає кількість. Погашена позначка — це так само запис на своїй даті, і вона так само відкривається; пошук міняє наголос, а не мапу. У списку місць зберігати нема, тож там той самий пошук прибирає рядки, а не сірить їх.

Одне видно лише на телефоні: на вузькому екрані час іде вгору, тож найновіше десятиліття — те, яким відповідає більшість пошуків, — стоїть рівно там, де плаває панель. Поки поле відкрите, смуга починається на 108px нижче. Саме відступом на кресленні, а не полем на рамці: виміряна коробка рамки керує малюванням, і її зменшення перепаковувало б кожну позначку на кожне відкриття.

Три речі, які виявив прохід

Острівець досі складав time, event і mode вручну — рівно той розхід, який шапка замороженого модуля передбачила письмово. Тепер обидва йдуть через контракт, а виклики називають лише те поле, яке змінюють.

Поле пошуку — перший текстовий ввід на цій сторінці за весь час, а вісь прив’язує звичайні друковані клавіші як команди. Набір «GPT-4» віддаляв вісь. Тепер обробник відступає всередині поля вводу — помилка, якої до цього проходу не могло існувати і яка поїхала б у прод без ручного проходу по клавіатурі.

Брама публічного артефакту навідріз відмовилася збирати, доки names не з’явилося в її дозвільному списку. Це брама, що працює як задумано: поле не залишає цю збірку лише тому, що якийсь код поклав його в проєкцію.

Чого це коштувало

2426 байтів JavaScript у стисненому вигляді за всю можливість разом зі стемером — 88 747 із бюджету 184 320. Імена сутностей додали 7036 байтів до українського data.json: 51 389 зі 122 880. LCP 1803 мс, CLS 0,026, 63 браузерні випадки зелені.

Сторінка «Про проєкт» десять днів казала «пошук і фільтри відкладено». На першому кроці її не чіпали, бо готовність контракту — не те саме, що можливість читача друкувати, а сторінка, яка заявляє про можливість, якої немає, — це єдине, чим цьому атласу бути не можна. Вона змінилася на другому кроці, тим самим комітом, який поставив поле на екран.

Запис зроблено 21 вересня 2026 р.

Коміти, про які цей запис

  • 9071111
  • 5825a78