Task lists — это особый вид списков в Markdown,
позволяющий создавать интерактивные чекбоксы. Они часто используются для
списков задач, TODO-листов или контрольных списков. В синтаксисе
Markdown каждая задача оформляется как пункт списка с квадратными
скобками, где [ ] обозначает пустой чекбокс, а
[x] — выполненный. Пример базового синтаксиса:
- [ ] Написать документацию
- [x] Настроить сборку проекта
- [ ] Проверить тесты
В этом примере первый и третий пункты остаются невыполненными, второй пункт отмечен как завершённый.
Remark предоставляет мощные инструменты для работы с Markdown через
AST (Abstract Syntax Tree). Для распознавания task
lists в Remark используется плагин remark-gfm,
который включает поддержку расширений GitHub Flavored Markdown,
включая:
Пример конфигурации Remark с remark-gfm:
import { remark } from 'remark';
import remarkGfm from 'remark-gfm';
const markdown = `
- [ ] Купить продукты
- [x] Оплатить счета
`;
remark()
.use(remarkGfm)
.process(markdown)
.then(file => {
console.log(String(file));
});
В AST, формируемом Remark, пункты списка с чекбоксами имеют
дополнительное свойство checked, которое принимает
true или false в зависимости от состояния
чекбокса. Структура элемента выглядит следующим образом:
{
"type": "listItem",
"checked": false,
"children": [
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Купить продукты"
}
]
}
]
}
Это свойство позволяет легко различать выполненные и невыполненные задачи на уровне обработки AST.
После разбора Markdown с помощью Remark можно конвертировать его в
HTML через Rehype. Для сохранения чекбоксов необходимо корректно
обрабатывать поле checked и создавать соответствующие
<input type="checkbox">.
Пример обработки с remark-rehype:
import { remark } from 'remark';
import remarkGfm from 'remark-gfm';
import rehypeStringify from 'rehype-stringify';
import remarkRehype from 'remark-rehype';
const markdown = `
- [ ] Выучить JavaScript
- [x] Настроить окружение
`;
remark()
.use(remarkGfm)
.use(remarkRehype)
.use(rehypeStringify)
.process(markdown)
.then(file => {
console.log(String(file));
});
В результирующем HTML задача с чекбоксом преобразуется в тег
<li> с <input> внутри:
<ul>
<li><input type="checkbox" disabled> Выучить JavaScript</li>
<li><input type="checkbox" checked disabled> Настроить окружение</li>
</ul>
Атрибут disabled используется по умолчанию, так как
Markdown — это статический формат. Для интерактивных списков можно
динамически управлять состоянием чекбоксов через JavaScript.
С помощью Remark можно программно модифицировать AST перед конвертацией в HTML. Например, добавление CSS-классов для разных состояний чекбоксов:
import { visit } from 'unist-util-visit';
remark()
.use(remarkGfm)
.use(() => tree => {
visit(tree, 'listItem', node => {
if (node.checked === true) {
node.data = { hProperties: { class: 'task-completed' } };
} else if (node.checked === false) {
node.data = { hProperties: { class: 'task-pending' } };
}
});
})
.use(remarkRehype)
.use(rehypeStringify)
.process(markdown)
.then(file => {
console.log(String(file));
});
В HTML можно получить:
<ul>
<li class="task-pending"><input type="checkbox" disabled> Выучить JavaScript</li>
<li class="task-completed"><input type="checkbox" checked disabled> Настроить окружение</li>
</ul>
Такой подход позволяет применять стили CSS для визуального различия между выполненными и невыполненными задачами.
Хотя Markdown по умолчанию статичен, после генерации HTML чекбоксы можно сделать интерактивными с помощью Jav * aScript:
document.querySelectorAll('li input[type="checkbox"]').forEach(checkbox => {
checkbox.disabled = false;
checkbox.addEventListener('change', e => {
const li = e.target.closest('li');
li.classList.toggle('task-completed', e.target.checked);
li.classList.toggle('task-pending', !e.target.checked);
});
});
Таким образом, можно синхронизировать состояние чекбоксов с визуальными стилями, реализуя полноценные TODO-листы на сайте.
remark-gfm.checked: Определяет состояние
задачи; отсутствует — считается невыполненной.checked применяется
только к соответствующему listItem.Эти механизмы позволяют строить сложные интерактивные интерфейсы на основе Markdown, сохраняя контроль над структурой и стилем через AST и Rehype.