diff --git a/apps/client/src/features/editor/components/embed/embed-view.tsx b/apps/client/src/features/editor/components/embed/embed-view.tsx index 02ae6edf..27ce21d9 100644 --- a/apps/client/src/features/editor/components/embed/embed-view.tsx +++ b/apps/client/src/features/editor/components/embed/embed-view.tsx @@ -15,13 +15,10 @@ import { import { IconEdit } from "@tabler/icons-react"; import { z } from "zod"; import { useForm, zodResolver } from "@mantine/form"; -import { - getEmbedProviderById, - getEmbedUrlAndProvider, -} from "@/features/editor/components/embed/providers.ts"; import { notifications } from "@mantine/notifications"; import { useTranslation } from "react-i18next"; import i18n from "i18next"; +import { getEmbedProviderById, getEmbedUrlAndProvider } from '@docmost/editor-ext'; const schema = z.object({ url: z diff --git a/packages/editor-ext/src/index.ts b/packages/editor-ext/src/index.ts index e9915e78..f2cb776b 100644 --- a/packages/editor-ext/src/index.ts +++ b/packages/editor-ext/src/index.ts @@ -16,4 +16,5 @@ export * from "./lib/drawio"; export * from "./lib/excalidraw"; export * from "./lib/embed"; export * from "./lib/mention"; -export * from "./lib/markdown"; \ No newline at end of file +export * from "./lib/markdown"; +export * from "./lib/embed-provider"; diff --git a/apps/client/src/features/editor/components/embed/providers.ts b/packages/editor-ext/src/lib/embed-provider.ts similarity index 58% rename from apps/client/src/features/editor/components/embed/providers.ts rename to packages/editor-ext/src/lib/embed-provider.ts index abbbf1ca..ab0690d0 100644 --- a/apps/client/src/features/editor/components/embed/providers.ts +++ b/packages/editor-ext/src/lib/embed-provider.ts @@ -7,102 +7,109 @@ export interface IEmbedProvider { export const embedProviders: IEmbedProvider[] = [ { - id: 'loom', - name: 'Loom', + id: "loom", + name: "Loom", regex: /^https?:\/\/(?:www\.)?loom\.com\/(?:share|embed)\/([\da-zA-Z]+)\/?/, getEmbedUrl: (match, url) => { - if(url.includes("/embed/")){ + if (url.includes("/embed/")) { return url; } return `https://loom.com/embed/${match[1]}`; - } + }, }, { - id: 'airtable', - name: 'Airtable', + 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/")){ + 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})/, + 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', + id: "typeform", + name: "Typeform", regex: /^(https?:)?(\/\/)?[\w\.]+\.typeform\.com\/to\/.+/, getEmbedUrl: (match, url: string) => { return url; - } + }, }, { - id: 'miro', - name: 'Miro', + id: "miro", + name: "Miro", regex: /^https:\/\/(www\.)?miro\.com\/app\/board\/([\w-]+=)/, getEmbedUrl: (match, url) => { - if(url.includes("/live-embed/")){ + 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+)?$/, + 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/")){ + 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+)/, + 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', + 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_-]+)\/.*$/, + 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_-]+)\/.*$/, + 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 - } + return url; + }, }, ]; export function getEmbedProviderById(id: string) { - return embedProviders.find(provider => provider.id.toLowerCase() === id.toLowerCase()); + return embedProviders.find( + (provider) => provider.id.toLowerCase() === id.toLowerCase(), + ); } export interface IEmbedResult { @@ -116,14 +123,12 @@ export function getEmbedUrlAndProvider(url: string): IEmbedResult { if (match) { return { embedUrl: provider.getEmbedUrl(match, url), - provider: provider.name.toLowerCase() + provider: provider.name.toLowerCase(), }; } } return { embedUrl: url, - provider: 'iframe', + provider: "iframe", }; } - -