[feature] Add val town embed (#1777)
This PR adds val town to tldraw's collection of embeddable things. ### Change Type - [x] `minor` — New feature ### Test Plan 1. Add links to val town, e.g. https://www.val.town/v/steveruizok.mathFact ### Release Notes - (feature) val town
This commit is contained in:
parent
b3186f5881
commit
03514c00c4
7 changed files with 134 additions and 88 deletions
BIN
assets/embed-icons/val_town.png
Normal file
BIN
assets/embed-icons/val_town.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 540 B |
|
@ -19,6 +19,7 @@ import embedIconsReplit from './embed-icons/replit.png'
|
|||
import embedIconsScratch from './embed-icons/scratch.png'
|
||||
import embedIconsSpotify from './embed-icons/spotify.png'
|
||||
import embedIconsTldraw from './embed-icons/tldraw.png'
|
||||
import embedIconsValTown from './embed-icons/val_town.png'
|
||||
import embedIconsVimeo from './embed-icons/vimeo.png'
|
||||
import embedIconsYoutube from './embed-icons/youtube.png'
|
||||
import fontsMonospace from './fonts/IBMPlexMono-Medium.woff2'
|
||||
|
@ -451,6 +452,7 @@ export function getAssetUrlsByImport(opts) {
|
|||
scratch: formatAssetUrl(embedIconsScratch, opts),
|
||||
spotify: formatAssetUrl(embedIconsSpotify, opts),
|
||||
tldraw: formatAssetUrl(embedIconsTldraw, opts),
|
||||
val_town: formatAssetUrl(embedIconsValTown, opts),
|
||||
vimeo: formatAssetUrl(embedIconsVimeo, opts),
|
||||
youtube: formatAssetUrl(embedIconsYoutube, opts),
|
||||
},
|
||||
|
|
|
@ -236,6 +236,7 @@ export function getAssetUrls(opts) {
|
|||
scratch: formatAssetUrl('./embed-icons/scratch.png', opts),
|
||||
spotify: formatAssetUrl('./embed-icons/spotify.png', opts),
|
||||
tldraw: formatAssetUrl('./embed-icons/tldraw.png', opts),
|
||||
val_town: formatAssetUrl('./embed-icons/val_town.png', opts),
|
||||
vimeo: formatAssetUrl('./embed-icons/vimeo.png', opts),
|
||||
youtube: formatAssetUrl('./embed-icons/youtube.png', opts),
|
||||
},
|
||||
|
|
1
packages/assets/types.d.ts
vendored
1
packages/assets/types.d.ts
vendored
|
@ -226,6 +226,7 @@ export type AssetUrls = {
|
|||
scratch: string
|
||||
spotify: string
|
||||
tldraw: string
|
||||
val_town: string
|
||||
vimeo: string
|
||||
youtube: string
|
||||
}
|
||||
|
|
|
@ -623,6 +623,7 @@ export function getAssetUrlsByMetaUrl(opts) {
|
|||
scratch: formatAssetUrl(new URL('./embed-icons/scratch.png', import.meta.url).href, opts),
|
||||
spotify: formatAssetUrl(new URL('./embed-icons/spotify.png', import.meta.url).href, opts),
|
||||
tldraw: formatAssetUrl(new URL('./embed-icons/tldraw.png', import.meta.url).href, opts),
|
||||
val_town: formatAssetUrl(new URL('./embed-icons/val_town.png', import.meta.url).href, opts),
|
||||
vimeo: formatAssetUrl(new URL('./embed-icons/vimeo.png', import.meta.url).href, opts),
|
||||
youtube: formatAssetUrl(new URL('./embed-icons/youtube.png', import.meta.url).href, opts),
|
||||
},
|
||||
|
|
|
@ -213,6 +213,38 @@ export const EMBED_DEFINITIONS: readonly [{
|
|||
readonly canUnmount: true;
|
||||
readonly toEmbedUrl: (url: string) => string | undefined;
|
||||
readonly fromEmbedUrl: (url: string) => string | undefined;
|
||||
}, {
|
||||
readonly type: "figma";
|
||||
readonly title: "Figma";
|
||||
readonly hostnames: readonly ["figma.com"];
|
||||
readonly width: 720;
|
||||
readonly height: 500;
|
||||
readonly doesResize: true;
|
||||
readonly canUnmount: true;
|
||||
readonly toEmbedUrl: (url: string) => string | undefined;
|
||||
readonly fromEmbedUrl: (url: string) => string | undefined;
|
||||
}, {
|
||||
readonly type: "google_maps";
|
||||
readonly title: "Google Maps";
|
||||
readonly hostnames: readonly ["google.*"];
|
||||
readonly width: 720;
|
||||
readonly height: 500;
|
||||
readonly doesResize: true;
|
||||
readonly canUnmount: false;
|
||||
readonly toEmbedUrl: (url: string) => string | undefined;
|
||||
readonly fromEmbedUrl: (url: string) => string | undefined;
|
||||
}, {
|
||||
readonly type: "val_town";
|
||||
readonly title: "Val Town";
|
||||
readonly hostnames: readonly ["val.town"];
|
||||
readonly minWidth: 260;
|
||||
readonly minHeight: 100;
|
||||
readonly width: 720;
|
||||
readonly height: 500;
|
||||
readonly doesResize: true;
|
||||
readonly canUnmount: false;
|
||||
readonly toEmbedUrl: (url: string) => string | undefined;
|
||||
readonly fromEmbedUrl: (url: string) => string | undefined;
|
||||
}, {
|
||||
readonly type: "codesandbox";
|
||||
readonly title: "CodeSandbox";
|
||||
|
@ -261,26 +293,6 @@ export const EMBED_DEFINITIONS: readonly [{
|
|||
readonly isAspectRatioLocked: true;
|
||||
readonly toEmbedUrl: (url: string) => string | undefined;
|
||||
readonly fromEmbedUrl: (url: string) => string | undefined;
|
||||
}, {
|
||||
readonly type: "figma";
|
||||
readonly title: "Figma";
|
||||
readonly hostnames: readonly ["figma.com"];
|
||||
readonly width: 720;
|
||||
readonly height: 500;
|
||||
readonly doesResize: true;
|
||||
readonly canUnmount: true;
|
||||
readonly toEmbedUrl: (url: string) => string | undefined;
|
||||
readonly fromEmbedUrl: (url: string) => string | undefined;
|
||||
}, {
|
||||
readonly type: "google_maps";
|
||||
readonly title: "Google Maps";
|
||||
readonly hostnames: readonly ["google.*"];
|
||||
readonly width: 720;
|
||||
readonly height: 500;
|
||||
readonly doesResize: true;
|
||||
readonly canUnmount: false;
|
||||
readonly toEmbedUrl: (url: string) => string | undefined;
|
||||
readonly fromEmbedUrl: (url: string) => string | undefined;
|
||||
}, {
|
||||
readonly type: "google_calendar";
|
||||
readonly title: "Google Calendar";
|
||||
|
|
|
@ -40,6 +40,103 @@ export const EMBED_DEFINITIONS = [
|
|||
return
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'figma',
|
||||
title: 'Figma',
|
||||
hostnames: ['figma.com'],
|
||||
width: 720,
|
||||
height: 500,
|
||||
doesResize: true,
|
||||
canUnmount: true,
|
||||
toEmbedUrl: (url) => {
|
||||
if (
|
||||
!!url.match(
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
/https:\/\/([\w\.-]+\.)?figma.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/.*)?$/
|
||||
) &&
|
||||
!url.includes('figma.com/embed')
|
||||
) {
|
||||
return `https://www.figma.com/embed?embed_host=share&url=${url}`
|
||||
}
|
||||
return
|
||||
},
|
||||
fromEmbedUrl: (url) => {
|
||||
const urlObj = safeParseUrl(url)
|
||||
if (urlObj && urlObj.pathname.match(/^\/embed\/?$/)) {
|
||||
const outUrl = urlObj.searchParams.get('url')
|
||||
if (outUrl) {
|
||||
return outUrl
|
||||
}
|
||||
}
|
||||
return
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'google_maps',
|
||||
title: 'Google Maps',
|
||||
hostnames: ['google.*'],
|
||||
width: 720,
|
||||
height: 500,
|
||||
doesResize: true,
|
||||
canUnmount: false,
|
||||
toEmbedUrl: (url) => {
|
||||
if (url.includes('/maps/')) {
|
||||
const match = url.match(/@(.*),(.*),(.*)z/)
|
||||
let result: string
|
||||
if (match) {
|
||||
const [, lat, lng, z] = match
|
||||
const host = new URL(url).host.replace('www.', '')
|
||||
result = `https://${host}/maps/embed/v1/view?key=${process.env.NEXT_PUBLIC_GC_API_KEY}¢er=${lat},${lng}&zoom=${z}`
|
||||
} else {
|
||||
result = ''
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
return
|
||||
},
|
||||
fromEmbedUrl: (url) => {
|
||||
const urlObj = safeParseUrl(url)
|
||||
if (!urlObj) return
|
||||
|
||||
const matches = urlObj.pathname.match(/^\/maps\/embed\/v1\/view\/?$/)
|
||||
if (matches && urlObj.searchParams.has('center') && urlObj.searchParams.get('zoom')) {
|
||||
const zoom = urlObj.searchParams.get('zoom')
|
||||
const [lat, lon] = urlObj.searchParams.get('center')!.split(',')
|
||||
return `https://www.google.com/maps/@${lat},${lon},${zoom}z`
|
||||
}
|
||||
return
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'val_town',
|
||||
title: 'Val Town',
|
||||
hostnames: ['val.town'],
|
||||
minWidth: 260,
|
||||
minHeight: 100,
|
||||
width: 720,
|
||||
height: 500,
|
||||
doesResize: true,
|
||||
canUnmount: false,
|
||||
toEmbedUrl: (url) => {
|
||||
const urlObj = safeParseUrl(url)
|
||||
// e.g. extract "steveruizok.mathFact" from https://www.val.town/v/steveruizok.mathFact
|
||||
const matches = urlObj && urlObj.pathname.match(/\/v\/([^/]+)\/?/)
|
||||
if (matches) {
|
||||
return `https://www.val.town/embed/${matches[1]}`
|
||||
}
|
||||
return
|
||||
},
|
||||
fromEmbedUrl: (url) => {
|
||||
const urlObj = safeParseUrl(url)
|
||||
// e.g. extract "steveruizok.mathFact" from https://www.val.town/v/steveruizok.mathFact
|
||||
const matches = urlObj && urlObj.pathname.match(/\/embed\/([^/]+)\/?/)
|
||||
if (matches) {
|
||||
return `https://www.val.town/v/${matches[1]}`
|
||||
}
|
||||
return
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'codesandbox',
|
||||
title: 'CodeSandbox',
|
||||
|
@ -166,74 +263,6 @@ export const EMBED_DEFINITIONS = [
|
|||
return
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'figma',
|
||||
title: 'Figma',
|
||||
hostnames: ['figma.com'],
|
||||
width: 720,
|
||||
height: 500,
|
||||
doesResize: true,
|
||||
canUnmount: true,
|
||||
toEmbedUrl: (url) => {
|
||||
if (
|
||||
!!url.match(
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
/https:\/\/([\w\.-]+\.)?figma.com\/(file|proto)\/([0-9a-zA-Z]{22,128})(?:\/.*)?$/
|
||||
) &&
|
||||
!url.includes('figma.com/embed')
|
||||
) {
|
||||
return `https://www.figma.com/embed?embed_host=share&url=${url}`
|
||||
}
|
||||
return
|
||||
},
|
||||
fromEmbedUrl: (url) => {
|
||||
const urlObj = safeParseUrl(url)
|
||||
if (urlObj && urlObj.pathname.match(/^\/embed\/?$/)) {
|
||||
const outUrl = urlObj.searchParams.get('url')
|
||||
if (outUrl) {
|
||||
return outUrl
|
||||
}
|
||||
}
|
||||
return
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'google_maps',
|
||||
title: 'Google Maps',
|
||||
hostnames: ['google.*'],
|
||||
width: 720,
|
||||
height: 500,
|
||||
doesResize: true,
|
||||
canUnmount: false,
|
||||
toEmbedUrl: (url) => {
|
||||
if (url.includes('/maps/')) {
|
||||
const match = url.match(/@(.*),(.*),(.*)z/)
|
||||
let result: string
|
||||
if (match) {
|
||||
const [, lat, lng, z] = match
|
||||
const host = new URL(url).host.replace('www.', '')
|
||||
result = `https://${host}/maps/embed/v1/view?key=${process.env.NEXT_PUBLIC_GC_API_KEY}¢er=${lat},${lng}&zoom=${z}`
|
||||
} else {
|
||||
result = ''
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
return
|
||||
},
|
||||
fromEmbedUrl: (url) => {
|
||||
const urlObj = safeParseUrl(url)
|
||||
if (!urlObj) return
|
||||
|
||||
const matches = urlObj.pathname.match(/^\/maps\/embed\/v1\/view\/?$/)
|
||||
if (matches && urlObj.searchParams.has('center') && urlObj.searchParams.get('zoom')) {
|
||||
const zoom = urlObj.searchParams.get('zoom')
|
||||
const [lat, lon] = urlObj.searchParams.get('center')!.split(',')
|
||||
return `https://www.google.com/maps/@${lat},${lon},${zoom}z`
|
||||
}
|
||||
return
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'google_calendar',
|
||||
title: 'Google Calendar',
|
||||
|
|
Loading…
Reference in a new issue