mirror of
https://github.com/docmost/docmost.git
synced 2025-11-15 01:21:12 +10:00
feat: third-party embeds (#423)
* wip * Add more providers * icons * unify embed providers (Youtube) * fix case * YT music * remove redundant code
This commit is contained in:
109
apps/client/src/features/editor/components/embed/providers.ts
Normal file
109
apps/client/src/features/editor/components/embed/providers.ts
Normal file
@ -0,0 +1,109 @@
|
||||
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) => {
|
||||
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/');
|
||||
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) => {
|
||||
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) => {
|
||||
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`;
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
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',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user