mandrock-files / tools

mdfocus

Рідер сирого markdown: line focus, bionic reading, ембіент під швидкість скролу, вузька колонка й повернення до місця читання. URL-проксі з SSRF-гардом.

mdfocus

Я скімлю (читаю по діагоналі, вихоплюючи тільки «цікаве»). Довгий технічний текст відкриваю з наміром прочитати, а очі вже летять униз — «де тут цікаве», — і оцінне судження вимикається десь на другому екрані. Для статей це терпимо. Для першоджерел і документації, де половина сенсу в абзаці, який не кричить, — ні. mdfocus я зробив під рівно цю діру: рідер сирого markdown, який не дає тексту проскочити повз.

Три входи: вставити текст, завантажити .md, або кинути лінк на зовнішній .md через ?url=. Далі marked.js рендерить, а зверху лягає шар, який я назвав «токенами» — не LLM-токени і не auth-токени, а одиниці утримання уваги. Назва збігається з двома іншими «токенами», тож одразу уточнюю.

Що всередині

Line focus підсвічує вікно з п'яти блоків навколо рядка читання (по два з кожного боку). Решта тексту лишається з повним контрастом: підсвітка показує, де я зараз, а не карає все поза цією точкою. Progress rail і лічильник секцій по h1/h2 дають масштаб документа; спільний mandrock0-ambient.js reseed-иться лише на зміні секції, не на таймері.

Тепер ембіент реагує і на швидкість скролу. Коли я пролітаю текст, canvas приглушується аж до 25% opacity; після паузи починає повертатись. Швидкість — лише proxy для скіму, не детектор того, що я зрозумів абзац (було б зручно, але браузер такого не знає). При prefers-reduced-motion цю реакцію вимкнено.

Bionic reading теж дійшов до рідера: перемикач робить жирним початок слів у звичайному тексті, не чіпаючи код, заголовки й лінки. Він off за замовчуванням. Незалежного заміру, що такий прийом справді прискорює моє читання, у мене нема — тому не записую його в «доведені покращення», а лишаю ручкою, яку можна вимкнути за секунду. Вузька колонка на 58ch — друга така ручка: коли очі стрибають по рядку, прибираю зайву ширину, не переписуючи сам markdown.

Ще один токен майже невидимий: після скролу позиція зберігається локально для цього тексту. При наступному відкритті з'являється «продовжити читання», але рідер не перекидає мене туди сам — іноді я відкриваю документ саме з початку. Brown/pink noise лишився процедурним через Web Audio API, без аудіофайлів і без автозапуску. Налаштування й позиція живуть у localStorage; бекенд бачить тільки URL, якщо я завантажую зовнішній .md через проксі.

Що я викинув

Було мікро-поле рефлексії після секції — «запиши, що зрозумів». Воно щоразу розривало потік. Викинув 11.09, і ось правило, що з цього випало: токен не має переривати того, кого він тримає. Bionic reading у старій версії був у беклозі саме тому, що я не хотів вмикати спірний прийом усім підряд; тепер він повернувся як opt-in, а поле рефлексії — ні.

Бекенд: проксі й гард, який ніхто не просив

Браузер не вміє fetch-ити чужий .md без CORS, тож ?url= ходить через тонкий проксі на stdlib Python, 0 залежностей, 127.0.0.1:3466 за nginx. Сам проксі — одна функція, але SSRF-гард я туди вклав як окрему роботу: «сходи на будь-який URL від імені сервера» — класична діра у внутрішню мережу й cloud metadata.

Що закриває кожен пункт:

Живе: tools.mandrock.me/mdfocus/. Репо, MIT: github.com/0mandrock1/mdfocus.

MANDROCK.DEV · TELEGRAMЩе більше про код, агентів і те, що ламається красиво.Зазирнути в канал →