|
|
|
|
@ -18,6 +18,7 @@ type EmbeddedLink =
@@ -18,6 +18,7 @@ type EmbeddedLink =
|
|
|
|
|
| ({ |
|
|
|
|
aspectRatio: { w: number; h: number }; |
|
|
|
|
warning?: string; |
|
|
|
|
sandbox?: { allowSameOrigin?: boolean }; |
|
|
|
|
} & ( |
|
|
|
|
| { type: "video" | "generic"; link: string } |
|
|
|
|
| { type: "document"; srcdoc: (theme: Theme) => string } |
|
|
|
|
@ -30,20 +31,20 @@ const RE_YOUTUBE =
@@ -30,20 +31,20 @@ const RE_YOUTUBE =
|
|
|
|
|
/^(?:http(?:s)?:\/\/)?(?:www\.)?youtu(?:be\.com|\.be)\/(embed\/|watch\?v=|shorts\/|playlist\?list=|embed\/videoseries\?list=)?([a-zA-Z0-9_-]+)(?:\?t=|&t=|\?start=|&start=)?([a-zA-Z0-9_-]+)?[^\s]*$/; |
|
|
|
|
|
|
|
|
|
const RE_VIMEO = |
|
|
|
|
/^(?:http(?:s)?:\/\/)?(?:(?:w){3}.)?(?:player\.)?vimeo\.com\/(?:video\/)?([^?\s]+)(?:\?.*)?$/; |
|
|
|
|
/^(?:http(?:s)?:\/\/)?(?:(?:w){3}\.)?(?:player\.)?vimeo\.com\/(?:video\/)?([^?\s]+)(?:\?.*)?$/; |
|
|
|
|
const RE_FIGMA = /^https:\/\/(?:www\.)?figma\.com/; |
|
|
|
|
|
|
|
|
|
const RE_GH_GIST = /^https:\/\/gist\.github\.com/; |
|
|
|
|
const RE_GH_GIST_EMBED = |
|
|
|
|
/^<script[\s\S]*?\ssrc=["'](https:\/\/gist.github.com\/.*?)\.js["']/i; |
|
|
|
|
/https?:\/\/gist\.github\.com\/([\w_-]+)\/([\w_-]+)\.js["']/i; |
|
|
|
|
|
|
|
|
|
// not anchored to start to allow <blockquote> twitter embeds
|
|
|
|
|
const RE_TWITTER = /(?:http(?:s)?:\/\/)?(?:(?:w){3}.)?twitter.com/; |
|
|
|
|
const RE_TWITTER = /(?:https?:\/\/)?(?:(?:w){3}\.)?(?:twitter|x)\.com/; |
|
|
|
|
const RE_TWITTER_EMBED = |
|
|
|
|
/^<blockquote[\s\S]*?\shref=["'](https:\/\/twitter.com\/[^"']*)/i; |
|
|
|
|
/^<blockquote[\s\S]*?\shref=["'](https?:\/\/(?:twitter|x)\.com\/[^"']*)/i; |
|
|
|
|
|
|
|
|
|
const RE_VALTOWN = |
|
|
|
|
/^https:\/\/(?:www\.)?val.town\/(v|embed)\/[a-zA-Z_$][0-9a-zA-Z_$]+\.[a-zA-Z_$][0-9a-zA-Z_$]+/; |
|
|
|
|
/^https:\/\/(?:www\.)?val\.town\/(v|embed)\/[a-zA-Z_$][0-9a-zA-Z_$]+\.[a-zA-Z_$][0-9a-zA-Z_$]+/; |
|
|
|
|
|
|
|
|
|
const RE_GENERIC_EMBED = |
|
|
|
|
/^<(?:iframe|blockquote)[\s\S]*?\s(?:src|href)=["']([^"']*)["'][\s\S]*?>$/i; |
|
|
|
|
@ -143,46 +144,27 @@ export const getEmbedLink = (link: string | null | undefined): EmbeddedLink => {
@@ -143,46 +144,27 @@ export const getEmbedLink = (link: string | null | undefined): EmbeddedLink => {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (RE_TWITTER.test(link)) { |
|
|
|
|
let ret: EmbeddedLink; |
|
|
|
|
// assume embed code
|
|
|
|
|
if (/<blockquote/.test(link)) { |
|
|
|
|
const srcDoc = createSrcDoc(link); |
|
|
|
|
ret = { |
|
|
|
|
type: "document", |
|
|
|
|
srcdoc: () => srcDoc, |
|
|
|
|
aspectRatio: { w: 480, h: 480 }, |
|
|
|
|
}; |
|
|
|
|
// assume regular tweet url
|
|
|
|
|
} else { |
|
|
|
|
ret = { |
|
|
|
|
type: "document", |
|
|
|
|
srcdoc: (theme: string) => |
|
|
|
|
createSrcDoc( |
|
|
|
|
`<blockquote class="twitter-tweet" data-dnt="true" data-theme="${theme}"><a href="${link}"></a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>`, |
|
|
|
|
), |
|
|
|
|
aspectRatio: { w: 480, h: 480 }, |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
// the embed srcdoc still supports twitter.com domain only
|
|
|
|
|
link = link.replace(/\bx.com\b/, "twitter.com"); |
|
|
|
|
|
|
|
|
|
const ret: EmbeddedLink = { |
|
|
|
|
type: "document", |
|
|
|
|
srcdoc: (theme: string) => |
|
|
|
|
createSrcDoc( |
|
|
|
|
`<blockquote class="twitter-tweet" data-dnt="true" data-theme="${theme}"><a href="${link}"></a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>`, |
|
|
|
|
), |
|
|
|
|
aspectRatio: { w: 480, h: 480 }, |
|
|
|
|
sandbox: { allowSameOrigin: true }, |
|
|
|
|
}; |
|
|
|
|
embeddedLinkCache.set(originalLink, ret); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (RE_GH_GIST.test(link)) { |
|
|
|
|
let ret: EmbeddedLink; |
|
|
|
|
// assume embed code
|
|
|
|
|
if (/<script>/.test(link)) { |
|
|
|
|
const srcDoc = createSrcDoc(link); |
|
|
|
|
ret = { |
|
|
|
|
type: "document", |
|
|
|
|
srcdoc: () => srcDoc, |
|
|
|
|
aspectRatio: { w: 550, h: 720 }, |
|
|
|
|
}; |
|
|
|
|
// assume regular url
|
|
|
|
|
} else { |
|
|
|
|
ret = { |
|
|
|
|
type: "document", |
|
|
|
|
srcdoc: () => |
|
|
|
|
createSrcDoc(` |
|
|
|
|
const ret: EmbeddedLink = { |
|
|
|
|
type: "document", |
|
|
|
|
srcdoc: () => |
|
|
|
|
createSrcDoc(` |
|
|
|
|
<script src="${link}.js"></script> |
|
|
|
|
<style type="text/css"> |
|
|
|
|
* { margin: 0px; } |
|
|
|
|
@ -190,9 +172,8 @@ export const getEmbedLink = (link: string | null | undefined): EmbeddedLink => {
@@ -190,9 +172,8 @@ export const getEmbedLink = (link: string | null | undefined): EmbeddedLink => {
|
|
|
|
|
.gist .gist-file { height: calc(100vh - 2px); padding: 0px; display: grid; grid-template-rows: 1fr auto; } |
|
|
|
|
</style> |
|
|
|
|
`),
|
|
|
|
|
aspectRatio: { w: 550, h: 720 }, |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
aspectRatio: { w: 550, h: 720 }, |
|
|
|
|
}; |
|
|
|
|
embeddedLinkCache.set(link, ret); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
@ -310,8 +291,8 @@ export const extractSrc = (htmlString: string): string => {
@@ -310,8 +291,8 @@ export const extractSrc = (htmlString: string): string => {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const gistMatch = htmlString.match(RE_GH_GIST_EMBED); |
|
|
|
|
if (gistMatch && gistMatch.length === 2) { |
|
|
|
|
return gistMatch[1]; |
|
|
|
|
if (gistMatch && gistMatch.length === 3) { |
|
|
|
|
return `https://gist.github.com/${gistMatch[1]}/${gistMatch[2]}`; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (RE_GIPHY.test(htmlString)) { |
|
|
|
|
|