-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
89 lines (78 loc) · 2.33 KB
/
index.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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import { visit } from "unist-util-visit";
import { whitespace } from 'hast-util-whitespace'
import type { Root } from "hast";
/**
* A rehype plugin to extend blockquote syntax to make it simple to mention/cite sources in a semantically correct way.
* More info: [https://github.com/nikitarevenco/remark-semantic-blockquotes](https://github.com/nikitarevenco/remark-semantic-blockquotes)
*/
const rehypeSemanticBlockquotes = (
/**
* Configuration for the plugin
*/
opts = {
/**
* Attribute name for the `<figure>` element
*/
figure: "dataBlockquoteContainer",
/**
* Attribute name for the `<blockquote>` element
*/
blockquote: "dataBlockquoteContent",
/**
* Attribute name for the `<figcaption>` element
*/
figcaption: "dataBlockquoteCredit",
/**
* Syntax to use to trigger the plugin's effect
*/
syntax: "@ ",
}
) => {
return (tree: Root) => {
visit(tree, 'element', (blockquote, index, parent) => {
if (!parent || index === undefined || blockquote.tagName !== "blockquote") {
return;
}
let tailIndex = blockquote.children.length - 1
while (tailIndex > -1 && whitespace(blockquote.children[tailIndex])) {
tailIndex--
}
const tail = blockquote.children[tailIndex]
if (!tail || tail.type !== 'element' || tail.tagName !== 'p') {
return
}
const tailText = tail.children[0]
if (tailText.type !== 'text' || !tailText.value.startsWith(opts.syntax)) {
return
}
tailText.value = tailText.value.slice(opts.syntax.length)
parent.children[index] = {
type: 'element',
tagName: 'figure',
properties: { [opts.figure]: '' },
children: [
{
type: 'element',
tagName: 'blockquote',
properties: { [opts.blockquote]: '' },
children: blockquote.children.slice(0, tailIndex)
},
{
type: 'element',
tagName: 'figcaption',
properties: { [opts.figcaption]: '' },
children: [
{
type: 'element',
tagName: 'p',
properties: {},
children: tail.children
}
]
}
]
}
})
};
}
export default rehypeSemanticBlockquotes