Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni
🤖🚫 AI-free content. This post is 100% written by a human, as is everything on my blog. Enjoy!27.08.2023
Розширення парсера Remark
Останній раз я писав про Remark з точки зору споживача. Проте, довелося також його й дописувати. Документації тут бракує, а екосистема складна, тому не так вже воно й легко.
Мені, власне, потрібно впровадити підтримку знайомого по GitHub синтаксису задач - [ ] To do
. Для такого вже є рішення. Проте є нюанс: в Obsidian дозволено ставити статусом задачі не тільки хрестик, але й інші символи (наприклад, -
для скасованих задач.) А всі плагіни, що існують, мають семантику “пробіл або хрестик”. Тому взяв за основу gfm-task-list-item та модифікував його так, щоб інші символи теж були дозволені.
Перший сюрприз - Remark використовує парсер micromark. Нестандартний синтаксис майже напевно потребує особливої обробки токенів, тому доведеться робити розширення для Micromark, що мене здивувало, бо це ціла окрема бібліотека (збирався робити на Remark, а опинився в Micromark). Micromark це взагалі повноцінний парсер, але Remark бере від нього саме токенізатор.
Доповнення для токенізатора складається з символу-тригера та логіки, яка споживає символи та генерує токени власних типів. Так, доповнення gfm-task-list-item
споживало маркер задачі та перевіряло, чи то пробіл або хрестик. Якщо так, то генерувало токен “задача зроблена/не зроблена”, а в протилежному чині — відмовлялася від обробки. Я поміняв це на простішу логіку, що просто зберігає символ між квадратними дужками в токен taskListItemValue
.
Щоб перетворити ці токени на елементи дерева AST, потрібне друге доповнення для іншого етапу, яке називається тут fromMarkdownExtension
. Таке доповнення реагує на потік токенів та будує дерево. Відповідно, в моєму випадку воно слухає вихід з taskListItemValue
(тобто коли вже відомо, що токен прочитаний повністю) та переносить символ маркера з токена в атрибут вузла listItem
.
Все це треба робити тому, що без особливої обробки рядок [ ]
не є вірним Markown - це посилання без адреси. Тому не можна просто шукати його в тексті вже по готовому дереву.