[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:
Steve Ruiz 2023-07-31 16:44:33 +01:00 committed by GitHub
parent b3186f5881
commit 03514c00c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 134 additions and 88 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 B

View file

@ -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),
},

View file

@ -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),
},

View file

@ -226,6 +226,7 @@ export type AssetUrls = {
scratch: string
spotify: string
tldraw: string
val_town: string
vimeo: string
youtube: string
}

View file

@ -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),
},

View file

@ -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";

View file

@ -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}&center=${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}&center=${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',