forked from withastro/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrehype-tasklist-enhancer.ts
44 lines (42 loc) · 1.35 KB
/
rehype-tasklist-enhancer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import type { Root } from 'hast';
import { h } from 'hastscript';
import type { Plugin, Transformer } from 'unified';
import { CONTINUE, EXIT, SKIP, visit } from 'unist-util-visit';
/**
* Rehype plugin to enhance the output of GitHub-Flavored Markdown’s task lists.
* This improves possibilities for our `<Checklist>` component.
*
* 1. Wraps checkboxes and siblings in a `<label>` to associate them.
* 2. Wraps sibling nodes after checkboxes in `<span>` to ease styling `:checked ~ *`.
*/
export function rehypeTasklistEnhancer(): Plugin<[], Root> {
const transformer: Transformer<Root> = (tree) => {
// Find task list items.
visit(tree, 'element', (node) => {
if (
!node.properties ||
!Array.isArray(node.properties.className) ||
!node.properties.className.includes('task-list-item')
) {
return CONTINUE;
}
// Find checkboxes inside task list items.
visit(node, 'element', (child, index, parent) => {
if (child.tagName !== 'input' || typeof index !== 'number' || !parent) {
return CONTINUE;
}
// Split children after checkbox.
const [head, tail] = [
parent.children.slice(0, index + 1),
parent.children.slice(index + 1),
];
parent.children = [h('label', {}, ...head, h('span', {}, ...tail))];
return EXIT;
});
return SKIP;
});
};
return function attacher() {
return transformer;
};
}