-
Notifications
You must be signed in to change notification settings - Fork 55
Expand file tree
/
Copy pathremark-plugin.ts
More file actions
70 lines (62 loc) · 1.89 KB
/
Copy pathremark-plugin.ts
File metadata and controls
70 lines (62 loc) · 1.89 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
import { Node, select, selectAll } from 'unist-util-select';
import twitterMatcher from '@astro-community/astro-embed-twitter/matcher';
import vimeoMatcher from '@astro-community/astro-embed-vimeo/matcher';
import youtubeMatcher from '@astro-community/astro-embed-youtube/matcher';
import spotifyMatcher from '@astro-community/astro-embed-spotify/matcher';
const matchers = [
[twitterMatcher, 'Tweet'],
[vimeoMatcher, 'Vimeo'],
[youtubeMatcher, 'YouTube'],
[spotifyMatcher, 'Spotify'],
] as const;
export const componentNames = matchers.map(([, name]) => name);
export default function createPlugin({
importNamespace,
}: {
importNamespace: string;
}) {
/**
* Get the name of the embed component for this URL
* @param {string} url URL to test
* @returns Component node for this URL or undefined if none matched
*/
function getComponent(url: string) {
for (const [matcher, componentName] of matchers) {
const id = matcher(url);
if (id) {
// MDX custom component node.
return {
type: 'mdxJsxFlowElement',
name: `${importNamespace}_${componentName}`,
attributes: [{ type: 'mdxJsxAttribute', name: 'id', value: id }],
children: [],
};
}
}
return undefined;
}
type Link = Node & {
url?: string;
value?: string;
children?: Node[];
};
function transformer(tree: Node) {
const paragraphs = selectAll('paragraph', tree);
paragraphs.forEach((paragraph) => {
const link: Link | null = select(':scope > link:only-child', paragraph);
if (!link) return;
const { url } = link;
// We’re only interested in HTTP links
if (!url?.startsWith('http')) return;
const component = getComponent(url);
if (component) {
// @ts-expect-error We’re overriding the initial node type with arbitrary data.
for (const key in component) paragraph[key] = component[key];
}
});
return tree;
}
return function attacher() {
return transformer;
};
}