-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrehype.ts
More file actions
92 lines (81 loc) · 2.53 KB
/
Copy pathrehype.ts
File metadata and controls
92 lines (81 loc) · 2.53 KB
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
90
91
92
import type { Root } from 'hast'
import type {
MdxJsxAttribute,
MdxJsxAttributeValueExpression,
MdxJsxFlowElement,
MdxJsxTextElement,
} from 'mdast-util-mdx-jsx'
import type { Plugin } from 'unified'
import { visit } from 'unist-util-visit'
import { resolveSongWithoutURL } from './resolver'
function isMusicPlayerNode(
node: any,
): node is MdxJsxFlowElement | MdxJsxTextElement {
return (
(node.type === 'mdxJsxFlowElement' || node.type === 'mdxJsxTextElement')
&& typeof node.name === 'string'
)
}
const rehypeMusicPlayer: Plugin<[], Root> = () => {
return async (tree: Root) => {
const promises: Promise<void>[] = []
visit(tree, ['mdxJsxFlowElement', 'mdxJsxTextElement'], (node) => {
if (!isMusicPlayerNode(node)) {
return
}
if (node.name !== 'MusicPlayer') {
return
}
const attrs = node.attributes || []
const neteaseAttr = attrs.find(
a => a.type === 'mdxJsxAttribute' && a.name === 'netease',
) as MdxJsxAttribute | undefined
if (!neteaseAttr) {
return
}
// Handle both literal and expression attribute values
let neteaseId: string | undefined
if (typeof neteaseAttr.value === 'string') {
neteaseId = neteaseAttr.value
}
else if (
neteaseAttr.value
&& (neteaseAttr.value as MdxJsxAttributeValueExpression).type
=== 'mdxJsxAttributeValueExpression'
) {
neteaseId = (neteaseAttr.value as MdxJsxAttributeValueExpression).value
}
if (!neteaseId) {
return
}
const p = Promise.resolve(resolveSongWithoutURL({ netease: String(neteaseId) })).then((meta) => {
if (!meta) {
return
}
// Build new attributes
const extraAttrs: MdxJsxAttribute[] = [
{ type: 'mdxJsxAttribute', name: 'name', value: meta.name },
{ type: 'mdxJsxAttribute', name: 'artist', value: meta.artist },
{ type: 'mdxJsxAttribute', name: 'pic', value: meta.pic },
{ type: 'mdxJsxAttribute', name: 'lyric', value: meta.lyric },
]
// Remove duplicates if already present
node.attributes = [
...attrs.filter(
a =>
!(
a.type === 'mdxJsxAttribute'
&& ['name', 'artist', 'pic', 'lyric'].includes(a.name)
),
),
...extraAttrs,
]
})
promises.push(p)
})
if (promises.length > 0) {
await Promise.all(promises)
}
}
}
export default rehypeMusicPlayer