import { visit } from 'unist-util-visit'
/**
* A remark plugin that converts custom directives to embedded media HTML elements
* Supports: link cards, Spotify, YouTube, Bilibili, X posts, and GitHub repository cards
*/
const embedHandlers = {
// Link Card
link: (node) => {
const url = node.attributes?.url
if (!url) {
return false
}
// Create the LinkCard HTML structure - all metadata will be fetched by JavaScript
return `
`
},
// Spotify
spotify: (node) => {
const url = node.attributes?.url ?? ''
if (!url) {
return false
}
if (!/^https:\/\/open\.spotify\.com\//.test(url)) {
return false
}
let embedUrl = url.replace('open.spotify.com/', 'open.spotify.com/embed/')
if (!embedUrl.includes('utm_source=')) {
embedUrl += (embedUrl.includes('?') ? '&' : '?') + 'utm_source=generator'
}
let height = '152'
if (url.includes('/album/') || url.includes('/playlist/') || url.includes('/artist/') || url.includes('/show/')) {
height = '352'
}
return `
`
},
// Youtube
youtube: (node) => {
let videoId = node.attributes?.id ?? ''
const url = node.attributes?.url ?? ''
if (!videoId && url) {
const match = url.match(/(?:v=|\/embed\/|youtu\.be\/)([\w-]{11})/)
if (match) videoId = match[1]
}
if (!videoId) {
return false
}
return `
`
},
// Bilibili
bilibili: (node) => {
let bvid = node.attributes?.id ?? ''
const url = node.attributes?.url ?? ''
if (!bvid && url) {
const match = url.match(/\/BV([\w]+)/)
if (match) bvid = 'BV' + match[1]
}
if (!bvid) {
return false
}
return `
`
},
// X Post Card
x: (node) => {
const xUrl = node.attributes?.url ?? ''
if (!xUrl) {
return false
}
const twitterUrl = xUrl.replace(/(\w+:\/\/)?x\.com\//g, '$1twitter.com/')
const uniqueId = `x-card-${Math.random().toString(36).slice(2, 11)}`
return `