Skip to content

Commit

Permalink
Fix youtube links match
Browse files Browse the repository at this point in the history
  • Loading branch information
cesardeazevedo committed Sep 30, 2024
1 parent 6deef11 commit ea0dc95
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 9 deletions.
4 changes: 2 additions & 2 deletions examples/react/src/components/Youtube/Youtube.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useMemo } from 'react'
import LiteYouTubeEmbed from 'react-lite-youtube-embed'
import 'react-lite-youtube-embed/dist/LiteYouTubeEmbed.css'

const REGEX_VIDEO_ID = /.*(?:youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=)([^#&?]*).*/
const REGEX_VIDEO_ID = /.*(?:youtu.be\/|v\/|u\/\w\/|shorts|embed\/|watch\?v=)([^#&?]*).*/

type Props = {
src: string
Expand All @@ -12,7 +12,7 @@ export function Youtube(props: Props) {
const { src } = props

const embedId = useMemo(() => {
return src.match(REGEX_VIDEO_ID)?.[1]
return src.match(REGEX_VIDEO_ID)?.[1].replace('/', '')
}, [src])

return (
Expand Down
2 changes: 1 addition & 1 deletion src/extensions/LinkExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const LinkExtension = Link.configure({ autolink: false }).extend({
const { nodes, marks } = state.schema
const imeta = this.editor.storage.nostr.imeta
const url = match.data?.href
const kind = getLinkKind(url, url, imeta)
const kind = getLinkKind(url, imeta)
if (kind !== 'text' && nodes[kind]) {
state.tr.replaceWith(from, to, nodes[kind].create({ src: url }))
return
Expand Down
38 changes: 38 additions & 0 deletions src/helpers/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { getLinkKind } from '../utils'

describe('getLinkKind', () => {
test('assert image links', () => {
expect(getLinkKind('https://nostr.com/image')).toBe('text')
expect(getLinkKind('https://nostr.com/image.jpg')).toBe('image')
expect(getLinkKind('https://nostr.com/image.png')).toBe('image')
expect(getLinkKind('https://nostr.com/image.webp')).toBe('image')
expect(getLinkKind('https://nostr.com/imagejpg')).toBe('text')
expect(getLinkKind('https://nostr.com/imagepng')).toBe('text')
})

test('assert video links', () => {
expect(getLinkKind('https://nostr.com/video')).toBe('text')
expect(getLinkKind('https://nostr.com/video.webm')).toBe('video')
expect(getLinkKind('https://nostr.com/video.mp4')).toBe('video')
expect(getLinkKind('https://nostr.com/video.ogg')).toBe('video')
expect(getLinkKind('https://nostr.com/videowebm')).toBe('text')
expect(getLinkKind('https://nostr.com/videomp4')).toBe('text')
})

test('assert youtube links', () => {
expect(getLinkKind('https://youtube.com')).toBe('text')
expect(getLinkKind('https://youtube.com/@user')).toBe('text')
expect(getLinkKind('https://www.youtube.com/@user')).toBe('text')
expect(getLinkKind('https://youtube.com/@user/feature')).toBe('text')
expect(getLinkKind('https://youtube.com/shorts/abcdef12345')).toBe('youtube')
expect(getLinkKind('https://www.youtube.com/watch?v=aA-jiiepOrE&t=924s')).toBe('youtube')
expect(getLinkKind('https://youtube.com/watch?v=aA-jiiepOrE&t=924s')).toBe('youtube')
expect(getLinkKind('https://youtu.be/aA-jiiepOrE?si=YguTWCcr8-fBWq9h')).toBe('youtube')
expect(getLinkKind('https://www.youtube.com/embed/aA-jiiepOrE?si=tVlJ8q_QSP_3yPHM')).toBe('youtube')
})

test('assert twitter links', () => {
expect(getLinkKind('https://x.com/halfin/status/1110302988')).toBe('tweet')
expect(getLinkKind('https://twitter.com/halfin/status/1110302988')).toBe('tweet')
})
})
15 changes: 9 additions & 6 deletions src/helpers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,25 @@ export function parseRelayAttribute(element: HTMLElement) {

export type LinkKinds = 'text' | 'image' | 'video' | 'tweet' | 'youtube'

const IMAGE_EXTENSIONS = /.(jpg|jpeg|gif|png|bmp|svg|webp)$/
const VIDEO_EXTENSIONS = /.(webm|mp4|ogg|mov)$/
const IMAGE_EXTENSIONS = /\.(jpg|jpeg|gif|png|bmp|svg|webp)$/
const VIDEO_EXTENSIONS = /\.(webm|mp4|ogg|mov)$/
const YOUTUBE_EMBED =
/^(?:(?:https?:)?\/\/)?(?:(?:(?:www|m(?:usic)?)\.)?youtu(?:\.be|be\.com)\/(?:shorts\/|live\/|v\/|e(?:mbed)?\/|watch(?:\/|\?(?:\S+=\S+&)*v=)|oembed\?url=https?%3A\/\/(?:www|m(?:usic)?)\.youtube\.com\/watch\?(?:\S+=\S+&)*v%3D|attribution_link\?(?:\S+=\S+&)*u=(?:\/|%2F)watch(?:\?|%3F)v(?:=|%3D))?|www\.youtube-nocookie\.com\/embed\/)([\w-]{1})[?&#]?\S*$/
const TWITTER_EMBED = /^https?:\/\/(twitter|x)\.com\/(?:#!\/)?(\w+)\/status(es)?\/(\d+)/

export function getLinkKind(url: string, href: string, imeta?: IMetaTags): LinkKinds {
export function getLinkKind(url: string, imeta?: IMetaTags): LinkKinds {
const mimetype = imeta?.[url]?.m?.split?.('/')?.[0]
if (mimetype === 'image') {
return 'image'
} else if (mimetype === 'video') {
return 'video'
} else if (/youtube|youtu.be/.test(url)) {
} else if (YOUTUBE_EMBED.test(url)) {
return 'youtube'
} else if (/^https?:\/\/(twitter|x)\.com\/(?:#!\/)?(\w+)\/status(es)?\/(\d+)/.test(url)) {
} else if (TWITTER_EMBED.test(url)) {
return 'tweet'
} else {
try {
const { pathname } = new URL(href)
const { pathname } = new URL(url)
return IMAGE_EXTENSIONS.test(pathname) ? 'image' : VIDEO_EXTENSIONS.test(pathname) ? 'video' : 'text'
} catch (error) {
console.log('url parser error', error)
Expand Down

0 comments on commit ea0dc95

Please sign in to comment.