lexical-remark
Version:
This package contains Markdown helpers and functionality for Lexical using remark-parse.
79 lines (78 loc) • 2.46 kB
JavaScript
import { visit } from 'unist-util-visit';
/**
* A regular expression to detect a YouTube url and parse out the video id as the sixth capture group
*
* @example
* function getVideoId(value: string) {
* const match = value.match(YOUTUBE_URL_REGEX);
* return !!match ? match[6] : null;
* }
*/
export const YOUTUBE_URL_REGEX = /^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube(-nocookie)?\.com|youtu.be))(\/(?:watch\?v=|embed\/|shorts\/|v\/)?)([\w\-]+)(\S+)?$/;
/**
* A remark plugin to enrich an mdast node tree by converting paragraph nodes containing only a YouTube url into YouTube nodes
*/
export const remarkYoutube = () => {
return convertYoutubeParagraphs;
};
function convertYoutubeParagraphs(tree) {
const videoId = isYoutubeParagraphNode(tree);
if (videoId) {
tree.children = [
{
type: 'youtube',
videoId,
},
];
}
visit(tree, function (node) {
const visitedVideoId = isYoutubeParagraphNode(node);
if (visitedVideoId) {
node.children = [
{
type: 'youtube',
videoId: visitedVideoId,
},
];
}
});
}
function isYoutubeParagraphNode(node) {
if (node.type === 'paragraph' && node.children.length === 1 && node.children[0].type === 'text') {
const match = node.children[0].value.match(YOUTUBE_URL_REGEX);
return !!match && match[6];
}
return false;
}
/**
* A remark plugin to simplify an mdast node tree by converting YouTube nodes back to paragraph nodes
*/
export function youtubeRemark() {
return convertToYoutubeParagraphs;
}
function convertToYoutubeParagraphs(tree) {
if (tree.type === 'youtube') {
tree.type = 'paragraph';
tree.children = [
{
type: 'text',
value: `https://www.youtube.com/watch?v=${tree.videoId}`,
},
];
// @ts-expect-error casting to Youtube
delete tree.videoId;
}
visit(tree, function (node) {
if (node.type === 'youtube') {
node.type = 'paragraph';
node.children = [
{
type: 'text',
value: `https://www.youtube.com/watch?v=${node.videoId}`,
},
];
// @ts-expect-error casting to Youtube
delete node.videoId;
}
});
}