export interface IEmbedProvider { id: string; name: string; regex: RegExp; getEmbedUrl: (match: RegExpMatchArray, url?: string) => string; } export const embedProviders: IEmbedProvider[] = [ { id: 'loom', name: 'Loom', regex: /^https?:\/\/(?:www\.)?loom\.com\/(?:share|embed)\/([\da-zA-Z]+)\/?/, getEmbedUrl: (match, url) => { if(url.includes("/embed/")){ return url; } return `https://loom.com/embed/${match[1]}`; } }, { id: 'airtable', name: 'Airtable', regex: /^https:\/\/(www.)?airtable.com\/([a-zA-Z0-9]{2,})\/.*/, getEmbedUrl: (match, url: string) => { const path = url.split('airtable.com/'); if(url.includes("/embed/")){ return url; } return `https://airtable.com/embed/${path[1]}`; } }, { id: 'figma', name: 'Figma', regex: /^https:\/\/[\w\.-]+\.?figma.com\/(file|proto|board|design|slides|deck)\/([0-9a-zA-Z]{22,128})/, getEmbedUrl: (match, url: string) => { return `https://www.figma.com/embed?url=${url}&embed_host=docmost`; } }, { 'id': 'typeform', name: 'Typeform', regex: /^(https?:)?(\/\/)?[\w\.]+\.typeform\.com\/to\/.+/, getEmbedUrl: (match, url: string) => { return url; } }, { id: 'miro', name: 'Miro', regex: /^https:\/\/(www\.)?miro\.com\/app\/board\/([\w-]+=)/, getEmbedUrl: (match, url) => { if(url.includes("/live-embed/")){ return url; } return `https://miro.com/app/live-embed/${match[2]}?embedMode=view_only_without_ui&autoplay=true&embedSource=docmost`; } }, { id: 'youtube', name: 'YouTube', regex: /^((?:https?:)?\/\/)?((?:www|m|music)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w\-]+\?v=|embed\/|v\/)?)([\w\-]+)(\S+)?$/, getEmbedUrl: (match, url) => { if (url.includes("/embed/")){ return url; } return `https://www.youtube-nocookie.com/embed/${match[5]}`; } }, { id: 'vimeo', name: 'Vimeo', regex: /^(https:)?\/\/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^/]*)\/videos\/|album\/(\d+)\/video\/|video\/|)(\d+)/, getEmbedUrl: (match) => { return `https://player.vimeo.com/video/${match[4]}`; } }, { id: 'framer', name: 'Framer', regex: /^https:\/\/(www\.)?framer\.com\/embed\/([\w-]+)/, getEmbedUrl: (match, url: string) => { return url; } }, { id: 'gdrive', name: 'Google Drive', regex: /^((?:https?:)?\/\/)?((?:www|m)\.)?(drive\.google\.com)\/file\/d\/([a-zA-Z0-9_-]+)\/.*$/, getEmbedUrl: (match) => { return `https://drive.google.com/file/d/${match[4]}/preview`; } }, { id: 'gsheets', name: 'Google Sheets', regex: /^((?:https?:)?\/\/)?((?:www|m)\.)?(docs\.google\.com)\/spreadsheets\/d\/e\/([a-zA-Z0-9_-]+)\/.*$/, getEmbedUrl: (match, url: string) => { return url } }, ]; export function getEmbedProviderById(id: string) { return embedProviders.find(provider => provider.id.toLowerCase() === id.toLowerCase()); } export interface IEmbedResult { embedUrl: string; provider: string; } export function getEmbedUrlAndProvider(url: string): IEmbedResult { for (const provider of embedProviders) { const match = url.match(provider.regex); if (match) { return { embedUrl: provider.getEmbedUrl(match, url), provider: provider.name.toLowerCase() }; } } return { embedUrl: url, provider: 'iframe', }; }