@tldraw/tlschema 4.1.1 → 4.2.0-next.d76c345101d5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/shapes/TLEmbedShape.js +0 -10
- package/dist-cjs/shapes/TLEmbedShape.js.map +2 -2
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/shapes/TLEmbedShape.mjs +0 -10
- package/dist-esm/shapes/TLEmbedShape.mjs.map +2 -2
- package/package.json +5 -5
- package/src/shapes/TLEmbedShape.ts +0 -10
package/dist-cjs/index.js
CHANGED
|
@@ -177,7 +177,7 @@ var import_TLVerticalAlignStyle = require("./styles/TLVerticalAlignStyle");
|
|
|
177
177
|
var import_translations = require("./translations/translations");
|
|
178
178
|
(0, import_utils.registerTldrawLibraryVersion)(
|
|
179
179
|
"@tldraw/tlschema",
|
|
180
|
-
"4.
|
|
180
|
+
"4.2.0-next.d76c345101d5",
|
|
181
181
|
"cjs"
|
|
182
182
|
);
|
|
183
183
|
//# sourceMappingURL=index.js.map
|
|
@@ -214,16 +214,6 @@ const EMBED_DEFINITIONS = [
|
|
|
214
214
|
return;
|
|
215
215
|
}
|
|
216
216
|
},
|
|
217
|
-
{
|
|
218
|
-
hostnames: ["excalidraw.com"],
|
|
219
|
-
fromEmbedUrl: (url) => {
|
|
220
|
-
const urlObj = (0, import_utils.safeParseUrl)(url);
|
|
221
|
-
if (urlObj && urlObj.hash.match(/#room=/)) {
|
|
222
|
-
return url;
|
|
223
|
-
}
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
},
|
|
227
217
|
{
|
|
228
218
|
hostnames: ["observablehq.com"],
|
|
229
219
|
fromEmbedUrl: (url) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/shapes/TLEmbedShape.ts"],
|
|
4
|
-
"sourcesContent": ["import { safeParseUrl } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'\nimport { RecordProps } from '../recordsWithProps'\nimport { TLBaseShape } from './TLBaseShape'\n\n// Only allow multiplayer embeds. If we add additional routes later for example '/help' this won't match\nconst TLDRAW_APP_RE = /(^\\/r\\/[^/]+\\/?$)/\n\nconst EMBED_DEFINITIONS = [\n\t{\n\t\thostnames: ['beta.tldraw.com', 'tldraw.com', 'localhost:3000'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(TLDRAW_APP_RE)) {\n\t\t\t\treturn url\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['figma.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/?$/)) {\n\t\t\t\tconst outUrl = urlObj.searchParams.get('url')\n\t\t\t\tif (outUrl) {\n\t\t\t\t\treturn outUrl\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['google.*'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (!urlObj) return\n\n\t\t\tconst matches = urlObj.pathname.match(/^\\/maps\\/embed\\/v1\\/view\\/?$/)\n\t\t\tif (matches && urlObj.searchParams.has('center') && urlObj.searchParams.get('zoom')) {\n\t\t\t\tconst zoom = urlObj.searchParams.get('zoom')\n\t\t\t\tconst [lat, lon] = urlObj.searchParams.get('center')!.split(',')\n\t\t\t\treturn `https://www.google.com/maps/@${lat},${lon},${zoom}z`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['val.town'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\t// e.g. extract \"steveruizok/mathFact\" from https://www.val.town/v/steveruizok/mathFact\n\t\t\tconst matches = urlObj && urlObj.pathname.match(/\\/embed\\/(.+)\\/?/)\n\t\t\tif (matches) {\n\t\t\t\treturn `https://www.val.town/v/${matches[1]}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['codesandbox.io'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tconst matches = urlObj && urlObj.pathname.match(/\\/embed\\/([^/]+)\\/?/)\n\t\t\tif (matches) {\n\t\t\t\treturn `https://codesandbox.io/s/${matches[1]}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['codepen.io'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst CODEPEN_EMBED_REGEXP = /https:\\/\\/codepen.io\\/([^/]+)\\/embed\\/([^/]+)/\n\t\t\tconst matches = url.match(CODEPEN_EMBED_REGEXP)\n\t\t\tif (matches) {\n\t\t\t\tconst [_, user, id] = matches\n\t\t\t\treturn `https://codepen.io/${user}/pen/${id}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['scratch.mit.edu'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst SCRATCH_EMBED_REGEXP = /https:\\/\\/scratch.mit.edu\\/projects\\/embed\\/([^/]+)/\n\t\t\tconst matches = url.match(SCRATCH_EMBED_REGEXP)\n\t\t\tif (matches) {\n\t\t\t\tconst [_, id] = matches\n\t\t\t\treturn `https://scratch.mit.edu/projects/${id}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['*.youtube.com', 'youtube.com', 'youtu.be'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (!urlObj) return\n\n\t\t\tconst hostname = urlObj.hostname.replace(/^www./, '')\n\t\t\tif (hostname === 'youtube.com') {\n\t\t\t\tconst matches = urlObj.pathname.match(/^\\/embed\\/([^/]+)\\/?/)\n\t\t\t\tif (matches) {\n\t\t\t\t\treturn `https://www.youtube.com/watch?v=${matches[1]}`\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['calendar.google.*'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tconst srcQs = urlObj?.searchParams.get('src')\n\n\t\t\tif (urlObj?.pathname.match(/\\/calendar\\/embed/) && srcQs) {\n\t\t\t\turlObj.pathname = '/calendar/u/0'\n\t\t\t\tconst keys = Array.from(urlObj.searchParams.keys())\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\turlObj.searchParams.delete(key)\n\t\t\t\t}\n\t\t\t\turlObj.searchParams.set('cid', srcQs)\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['docs.google.*'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\n\t\t\tif (urlObj?.pathname.match(/^\\/presentation/) && urlObj?.pathname.match(/\\/embed\\/?$/)) {\n\t\t\t\turlObj.pathname = urlObj.pathname.replace(/\\/embed$/, '/pub')\n\t\t\t\tconst keys = Array.from(urlObj.searchParams.keys())\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\turlObj.searchParams.delete(key)\n\t\t\t\t}\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['gist.github.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/\\/([^/]+)\\/([^/]+)/)) {\n\t\t\t\tif (!url.split('/').pop()) return\n\t\t\t\treturn url\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['replit.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (\n\t\t\t\turlObj &&\n\t\t\t\turlObj.pathname.match(/\\/@([^/]+)\\/([^/]+)/) &&\n\t\t\t\turlObj.searchParams.has('embed')\n\t\t\t) {\n\t\t\t\turlObj.searchParams.delete('embed')\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['felt.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/map\\//)) {\n\t\t\t\turlObj.pathname = urlObj.pathname.replace(/^\\/embed/, '')\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['open.spotify.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/(artist|album)\\//)) {\n\t\t\t\treturn urlObj.origin + urlObj.pathname.replace(/^\\/embed/, '')\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['vimeo.com', 'player.vimeo.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.hostname === 'player.vimeo.com') {\n\t\t\t\tconst matches = urlObj.pathname.match(/^\\/video\\/([^/]+)\\/?$/)\n\t\t\t\tif (matches) {\n\t\t\t\t\treturn 'https://vimeo.com/' + matches[1]\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['excalidraw.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.hash.match(/#room=/)) {\n\t\t\t\treturn url\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['observablehq.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/@([^/]+)\\/([^/]+)\\/?$/)) {\n\t\t\t\treturn `${urlObj.origin}${urlObj.pathname.replace('/embed', '')}#cell-*`\n\t\t\t}\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/([^/]+)\\/?$/)) {\n\t\t\t\treturn `${urlObj.origin}${urlObj.pathname.replace('/embed', '/d')}#cell-*`\n\t\t\t}\n\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['desmos.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (\n\t\t\t\turlObj &&\n\t\t\t\turlObj.hostname === 'www.desmos.com' &&\n\t\t\t\turlObj.pathname.match(/^\\/calculator\\/([^/]+)\\/?$/) &&\n\t\t\t\turlObj.search === '?embed' &&\n\t\t\t\turlObj.hash === ''\n\t\t\t) {\n\t\t\t\treturn url.replace('?embed', '')\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n]\n\n/**\n * Properties for the embed shape, which displays embedded content from external services.\n *\n * @public\n */\nexport interface TLEmbedShapeProps {\n\t/** Width of the embed shape in pixels */\n\tw: number\n\t/** Height of the embed shape in pixels */\n\th: number\n\t/** URL of the content to embed (supports YouTube, Figma, CodePen, etc.) */\n\turl: string\n}\n\n/**\n * An embed shape displays external content like YouTube videos, Figma designs, CodePen demos,\n * and other embeddable content within the tldraw canvas.\n *\n * @public\n * @example\n * ```ts\n * const embedShape: TLEmbedShape = {\n * id: createShapeId(),\n * typeName: 'shape',\n * type: 'embed',\n * x: 200,\n * y: 200,\n * rotation: 0,\n * index: 'a1',\n * parentId: 'page:page1',\n * isLocked: false,\n * opacity: 1,\n * props: {\n * w: 560,\n * h: 315,\n * url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'\n * },\n * meta: {}\n * }\n * ```\n */\nexport type TLEmbedShape = TLBaseShape<'embed', TLEmbedShapeProps>\n\n/**\n * Validation schema for embed shape properties.\n *\n * @public\n * @example\n * ```ts\n * // Validate embed shape properties\n * const isValidUrl = embedShapeProps.url.isValid('https://youtube.com/watch?v=abc123')\n * const isValidSize = embedShapeProps.w.isValid(560)\n * ```\n */\nexport const embedShapeProps: RecordProps<TLEmbedShape> = {\n\tw: T.nonZeroNumber,\n\th: T.nonZeroNumber,\n\turl: T.string,\n}\n\nconst Versions = createShapePropsMigrationIds('embed', {\n\tGenOriginalUrlInEmbed: 1,\n\tRemoveDoesResize: 2,\n\tRemoveTmpOldUrl: 3,\n\tRemovePermissionOverrides: 4,\n})\n\n/**\n * Version identifiers for embed shape migrations.\n *\n * @public\n */\nexport { Versions as embedShapeVersions }\n\n/**\n * Migration sequence for embed shape properties across different schema versions.\n * Handles URL transformations and removal of deprecated properties.\n *\n * @public\n */\nexport const embedShapeMigrations = createShapePropsMigrationSequence({\n\tsequence: [\n\t\t{\n\t\t\tid: Versions.GenOriginalUrlInEmbed,\n\t\t\t// add tmpOldUrl property\n\t\t\tup: (props) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst url = props.url\n\t\t\t\t\tconst host = new URL(url).host.replace('www.', '')\n\t\t\t\t\tlet originalUrl\n\t\t\t\t\tfor (const localEmbedDef of EMBED_DEFINITIONS) {\n\t\t\t\t\t\tif (localEmbedDef.hostnames.includes(host)) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\toriginalUrl = localEmbedDef.fromEmbedUrl(url)\n\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\tconsole.warn(err)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tprops.tmpOldUrl = props.url\n\t\t\t\t\tprops.url = originalUrl ?? ''\n\t\t\t\t} catch {\n\t\t\t\t\tprops.url = ''\n\t\t\t\t\tprops.tmpOldUrl = props.url\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemoveDoesResize,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.doesResize\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemoveTmpOldUrl,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.tmpOldUrl\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemovePermissionOverrides,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.overridePermissions\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t],\n})\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import { safeParseUrl } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'\nimport { RecordProps } from '../recordsWithProps'\nimport { TLBaseShape } from './TLBaseShape'\n\n// Only allow multiplayer embeds. If we add additional routes later for example '/help' this won't match\nconst TLDRAW_APP_RE = /(^\\/r\\/[^/]+\\/?$)/\n\nconst EMBED_DEFINITIONS = [\n\t{\n\t\thostnames: ['beta.tldraw.com', 'tldraw.com', 'localhost:3000'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(TLDRAW_APP_RE)) {\n\t\t\t\treturn url\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['figma.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/?$/)) {\n\t\t\t\tconst outUrl = urlObj.searchParams.get('url')\n\t\t\t\tif (outUrl) {\n\t\t\t\t\treturn outUrl\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['google.*'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (!urlObj) return\n\n\t\t\tconst matches = urlObj.pathname.match(/^\\/maps\\/embed\\/v1\\/view\\/?$/)\n\t\t\tif (matches && urlObj.searchParams.has('center') && urlObj.searchParams.get('zoom')) {\n\t\t\t\tconst zoom = urlObj.searchParams.get('zoom')\n\t\t\t\tconst [lat, lon] = urlObj.searchParams.get('center')!.split(',')\n\t\t\t\treturn `https://www.google.com/maps/@${lat},${lon},${zoom}z`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['val.town'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\t// e.g. extract \"steveruizok/mathFact\" from https://www.val.town/v/steveruizok/mathFact\n\t\t\tconst matches = urlObj && urlObj.pathname.match(/\\/embed\\/(.+)\\/?/)\n\t\t\tif (matches) {\n\t\t\t\treturn `https://www.val.town/v/${matches[1]}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['codesandbox.io'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tconst matches = urlObj && urlObj.pathname.match(/\\/embed\\/([^/]+)\\/?/)\n\t\t\tif (matches) {\n\t\t\t\treturn `https://codesandbox.io/s/${matches[1]}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['codepen.io'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst CODEPEN_EMBED_REGEXP = /https:\\/\\/codepen.io\\/([^/]+)\\/embed\\/([^/]+)/\n\t\t\tconst matches = url.match(CODEPEN_EMBED_REGEXP)\n\t\t\tif (matches) {\n\t\t\t\tconst [_, user, id] = matches\n\t\t\t\treturn `https://codepen.io/${user}/pen/${id}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['scratch.mit.edu'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst SCRATCH_EMBED_REGEXP = /https:\\/\\/scratch.mit.edu\\/projects\\/embed\\/([^/]+)/\n\t\t\tconst matches = url.match(SCRATCH_EMBED_REGEXP)\n\t\t\tif (matches) {\n\t\t\t\tconst [_, id] = matches\n\t\t\t\treturn `https://scratch.mit.edu/projects/${id}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['*.youtube.com', 'youtube.com', 'youtu.be'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (!urlObj) return\n\n\t\t\tconst hostname = urlObj.hostname.replace(/^www./, '')\n\t\t\tif (hostname === 'youtube.com') {\n\t\t\t\tconst matches = urlObj.pathname.match(/^\\/embed\\/([^/]+)\\/?/)\n\t\t\t\tif (matches) {\n\t\t\t\t\treturn `https://www.youtube.com/watch?v=${matches[1]}`\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['calendar.google.*'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tconst srcQs = urlObj?.searchParams.get('src')\n\n\t\t\tif (urlObj?.pathname.match(/\\/calendar\\/embed/) && srcQs) {\n\t\t\t\turlObj.pathname = '/calendar/u/0'\n\t\t\t\tconst keys = Array.from(urlObj.searchParams.keys())\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\turlObj.searchParams.delete(key)\n\t\t\t\t}\n\t\t\t\turlObj.searchParams.set('cid', srcQs)\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['docs.google.*'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\n\t\t\tif (urlObj?.pathname.match(/^\\/presentation/) && urlObj?.pathname.match(/\\/embed\\/?$/)) {\n\t\t\t\turlObj.pathname = urlObj.pathname.replace(/\\/embed$/, '/pub')\n\t\t\t\tconst keys = Array.from(urlObj.searchParams.keys())\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\turlObj.searchParams.delete(key)\n\t\t\t\t}\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['gist.github.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/\\/([^/]+)\\/([^/]+)/)) {\n\t\t\t\tif (!url.split('/').pop()) return\n\t\t\t\treturn url\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['replit.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (\n\t\t\t\turlObj &&\n\t\t\t\turlObj.pathname.match(/\\/@([^/]+)\\/([^/]+)/) &&\n\t\t\t\turlObj.searchParams.has('embed')\n\t\t\t) {\n\t\t\t\turlObj.searchParams.delete('embed')\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['felt.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/map\\//)) {\n\t\t\t\turlObj.pathname = urlObj.pathname.replace(/^\\/embed/, '')\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['open.spotify.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/(artist|album)\\//)) {\n\t\t\t\treturn urlObj.origin + urlObj.pathname.replace(/^\\/embed/, '')\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['vimeo.com', 'player.vimeo.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.hostname === 'player.vimeo.com') {\n\t\t\t\tconst matches = urlObj.pathname.match(/^\\/video\\/([^/]+)\\/?$/)\n\t\t\t\tif (matches) {\n\t\t\t\t\treturn 'https://vimeo.com/' + matches[1]\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['observablehq.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/@([^/]+)\\/([^/]+)\\/?$/)) {\n\t\t\t\treturn `${urlObj.origin}${urlObj.pathname.replace('/embed', '')}#cell-*`\n\t\t\t}\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/([^/]+)\\/?$/)) {\n\t\t\t\treturn `${urlObj.origin}${urlObj.pathname.replace('/embed', '/d')}#cell-*`\n\t\t\t}\n\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['desmos.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (\n\t\t\t\turlObj &&\n\t\t\t\turlObj.hostname === 'www.desmos.com' &&\n\t\t\t\turlObj.pathname.match(/^\\/calculator\\/([^/]+)\\/?$/) &&\n\t\t\t\turlObj.search === '?embed' &&\n\t\t\t\turlObj.hash === ''\n\t\t\t) {\n\t\t\t\treturn url.replace('?embed', '')\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n]\n\n/**\n * Properties for the embed shape, which displays embedded content from external services.\n *\n * @public\n */\nexport interface TLEmbedShapeProps {\n\t/** Width of the embed shape in pixels */\n\tw: number\n\t/** Height of the embed shape in pixels */\n\th: number\n\t/** URL of the content to embed (supports YouTube, Figma, CodePen, etc.) */\n\turl: string\n}\n\n/**\n * An embed shape displays external content like YouTube videos, Figma designs, CodePen demos,\n * and other embeddable content within the tldraw canvas.\n *\n * @public\n * @example\n * ```ts\n * const embedShape: TLEmbedShape = {\n * id: createShapeId(),\n * typeName: 'shape',\n * type: 'embed',\n * x: 200,\n * y: 200,\n * rotation: 0,\n * index: 'a1',\n * parentId: 'page:page1',\n * isLocked: false,\n * opacity: 1,\n * props: {\n * w: 560,\n * h: 315,\n * url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'\n * },\n * meta: {}\n * }\n * ```\n */\nexport type TLEmbedShape = TLBaseShape<'embed', TLEmbedShapeProps>\n\n/**\n * Validation schema for embed shape properties.\n *\n * @public\n * @example\n * ```ts\n * // Validate embed shape properties\n * const isValidUrl = embedShapeProps.url.isValid('https://youtube.com/watch?v=abc123')\n * const isValidSize = embedShapeProps.w.isValid(560)\n * ```\n */\nexport const embedShapeProps: RecordProps<TLEmbedShape> = {\n\tw: T.nonZeroNumber,\n\th: T.nonZeroNumber,\n\turl: T.string,\n}\n\nconst Versions = createShapePropsMigrationIds('embed', {\n\tGenOriginalUrlInEmbed: 1,\n\tRemoveDoesResize: 2,\n\tRemoveTmpOldUrl: 3,\n\tRemovePermissionOverrides: 4,\n})\n\n/**\n * Version identifiers for embed shape migrations.\n *\n * @public\n */\nexport { Versions as embedShapeVersions }\n\n/**\n * Migration sequence for embed shape properties across different schema versions.\n * Handles URL transformations and removal of deprecated properties.\n *\n * @public\n */\nexport const embedShapeMigrations = createShapePropsMigrationSequence({\n\tsequence: [\n\t\t{\n\t\t\tid: Versions.GenOriginalUrlInEmbed,\n\t\t\t// add tmpOldUrl property\n\t\t\tup: (props) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst url = props.url\n\t\t\t\t\tconst host = new URL(url).host.replace('www.', '')\n\t\t\t\t\tlet originalUrl\n\t\t\t\t\tfor (const localEmbedDef of EMBED_DEFINITIONS) {\n\t\t\t\t\t\tif (localEmbedDef.hostnames.includes(host)) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\toriginalUrl = localEmbedDef.fromEmbedUrl(url)\n\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\tconsole.warn(err)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tprops.tmpOldUrl = props.url\n\t\t\t\t\tprops.url = originalUrl ?? ''\n\t\t\t\t} catch {\n\t\t\t\t\tprops.url = ''\n\t\t\t\t\tprops.tmpOldUrl = props.url\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemoveDoesResize,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.doesResize\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemoveTmpOldUrl,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.tmpOldUrl\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemovePermissionOverrides,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.overridePermissions\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t],\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist-esm/index.mjs
CHANGED
|
@@ -189,16 +189,6 @@ const EMBED_DEFINITIONS = [
|
|
|
189
189
|
return;
|
|
190
190
|
}
|
|
191
191
|
},
|
|
192
|
-
{
|
|
193
|
-
hostnames: ["excalidraw.com"],
|
|
194
|
-
fromEmbedUrl: (url) => {
|
|
195
|
-
const urlObj = safeParseUrl(url);
|
|
196
|
-
if (urlObj && urlObj.hash.match(/#room=/)) {
|
|
197
|
-
return url;
|
|
198
|
-
}
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
},
|
|
202
192
|
{
|
|
203
193
|
hostnames: ["observablehq.com"],
|
|
204
194
|
fromEmbedUrl: (url) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/shapes/TLEmbedShape.ts"],
|
|
4
|
-
"sourcesContent": ["import { safeParseUrl } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'\nimport { RecordProps } from '../recordsWithProps'\nimport { TLBaseShape } from './TLBaseShape'\n\n// Only allow multiplayer embeds. If we add additional routes later for example '/help' this won't match\nconst TLDRAW_APP_RE = /(^\\/r\\/[^/]+\\/?$)/\n\nconst EMBED_DEFINITIONS = [\n\t{\n\t\thostnames: ['beta.tldraw.com', 'tldraw.com', 'localhost:3000'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(TLDRAW_APP_RE)) {\n\t\t\t\treturn url\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['figma.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/?$/)) {\n\t\t\t\tconst outUrl = urlObj.searchParams.get('url')\n\t\t\t\tif (outUrl) {\n\t\t\t\t\treturn outUrl\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['google.*'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (!urlObj) return\n\n\t\t\tconst matches = urlObj.pathname.match(/^\\/maps\\/embed\\/v1\\/view\\/?$/)\n\t\t\tif (matches && urlObj.searchParams.has('center') && urlObj.searchParams.get('zoom')) {\n\t\t\t\tconst zoom = urlObj.searchParams.get('zoom')\n\t\t\t\tconst [lat, lon] = urlObj.searchParams.get('center')!.split(',')\n\t\t\t\treturn `https://www.google.com/maps/@${lat},${lon},${zoom}z`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['val.town'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\t// e.g. extract \"steveruizok/mathFact\" from https://www.val.town/v/steveruizok/mathFact\n\t\t\tconst matches = urlObj && urlObj.pathname.match(/\\/embed\\/(.+)\\/?/)\n\t\t\tif (matches) {\n\t\t\t\treturn `https://www.val.town/v/${matches[1]}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['codesandbox.io'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tconst matches = urlObj && urlObj.pathname.match(/\\/embed\\/([^/]+)\\/?/)\n\t\t\tif (matches) {\n\t\t\t\treturn `https://codesandbox.io/s/${matches[1]}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['codepen.io'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst CODEPEN_EMBED_REGEXP = /https:\\/\\/codepen.io\\/([^/]+)\\/embed\\/([^/]+)/\n\t\t\tconst matches = url.match(CODEPEN_EMBED_REGEXP)\n\t\t\tif (matches) {\n\t\t\t\tconst [_, user, id] = matches\n\t\t\t\treturn `https://codepen.io/${user}/pen/${id}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['scratch.mit.edu'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst SCRATCH_EMBED_REGEXP = /https:\\/\\/scratch.mit.edu\\/projects\\/embed\\/([^/]+)/\n\t\t\tconst matches = url.match(SCRATCH_EMBED_REGEXP)\n\t\t\tif (matches) {\n\t\t\t\tconst [_, id] = matches\n\t\t\t\treturn `https://scratch.mit.edu/projects/${id}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['*.youtube.com', 'youtube.com', 'youtu.be'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (!urlObj) return\n\n\t\t\tconst hostname = urlObj.hostname.replace(/^www./, '')\n\t\t\tif (hostname === 'youtube.com') {\n\t\t\t\tconst matches = urlObj.pathname.match(/^\\/embed\\/([^/]+)\\/?/)\n\t\t\t\tif (matches) {\n\t\t\t\t\treturn `https://www.youtube.com/watch?v=${matches[1]}`\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['calendar.google.*'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tconst srcQs = urlObj?.searchParams.get('src')\n\n\t\t\tif (urlObj?.pathname.match(/\\/calendar\\/embed/) && srcQs) {\n\t\t\t\turlObj.pathname = '/calendar/u/0'\n\t\t\t\tconst keys = Array.from(urlObj.searchParams.keys())\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\turlObj.searchParams.delete(key)\n\t\t\t\t}\n\t\t\t\turlObj.searchParams.set('cid', srcQs)\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['docs.google.*'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\n\t\t\tif (urlObj?.pathname.match(/^\\/presentation/) && urlObj?.pathname.match(/\\/embed\\/?$/)) {\n\t\t\t\turlObj.pathname = urlObj.pathname.replace(/\\/embed$/, '/pub')\n\t\t\t\tconst keys = Array.from(urlObj.searchParams.keys())\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\turlObj.searchParams.delete(key)\n\t\t\t\t}\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['gist.github.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/\\/([^/]+)\\/([^/]+)/)) {\n\t\t\t\tif (!url.split('/').pop()) return\n\t\t\t\treturn url\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['replit.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (\n\t\t\t\turlObj &&\n\t\t\t\turlObj.pathname.match(/\\/@([^/]+)\\/([^/]+)/) &&\n\t\t\t\turlObj.searchParams.has('embed')\n\t\t\t) {\n\t\t\t\turlObj.searchParams.delete('embed')\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['felt.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/map\\//)) {\n\t\t\t\turlObj.pathname = urlObj.pathname.replace(/^\\/embed/, '')\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['open.spotify.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/(artist|album)\\//)) {\n\t\t\t\treturn urlObj.origin + urlObj.pathname.replace(/^\\/embed/, '')\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['vimeo.com', 'player.vimeo.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.hostname === 'player.vimeo.com') {\n\t\t\t\tconst matches = urlObj.pathname.match(/^\\/video\\/([^/]+)\\/?$/)\n\t\t\t\tif (matches) {\n\t\t\t\t\treturn 'https://vimeo.com/' + matches[1]\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['excalidraw.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.hash.match(/#room=/)) {\n\t\t\t\treturn url\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['observablehq.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/@([^/]+)\\/([^/]+)\\/?$/)) {\n\t\t\t\treturn `${urlObj.origin}${urlObj.pathname.replace('/embed', '')}#cell-*`\n\t\t\t}\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/([^/]+)\\/?$/)) {\n\t\t\t\treturn `${urlObj.origin}${urlObj.pathname.replace('/embed', '/d')}#cell-*`\n\t\t\t}\n\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['desmos.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (\n\t\t\t\turlObj &&\n\t\t\t\turlObj.hostname === 'www.desmos.com' &&\n\t\t\t\turlObj.pathname.match(/^\\/calculator\\/([^/]+)\\/?$/) &&\n\t\t\t\turlObj.search === '?embed' &&\n\t\t\t\turlObj.hash === ''\n\t\t\t) {\n\t\t\t\treturn url.replace('?embed', '')\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n]\n\n/**\n * Properties for the embed shape, which displays embedded content from external services.\n *\n * @public\n */\nexport interface TLEmbedShapeProps {\n\t/** Width of the embed shape in pixels */\n\tw: number\n\t/** Height of the embed shape in pixels */\n\th: number\n\t/** URL of the content to embed (supports YouTube, Figma, CodePen, etc.) */\n\turl: string\n}\n\n/**\n * An embed shape displays external content like YouTube videos, Figma designs, CodePen demos,\n * and other embeddable content within the tldraw canvas.\n *\n * @public\n * @example\n * ```ts\n * const embedShape: TLEmbedShape = {\n * id: createShapeId(),\n * typeName: 'shape',\n * type: 'embed',\n * x: 200,\n * y: 200,\n * rotation: 0,\n * index: 'a1',\n * parentId: 'page:page1',\n * isLocked: false,\n * opacity: 1,\n * props: {\n * w: 560,\n * h: 315,\n * url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'\n * },\n * meta: {}\n * }\n * ```\n */\nexport type TLEmbedShape = TLBaseShape<'embed', TLEmbedShapeProps>\n\n/**\n * Validation schema for embed shape properties.\n *\n * @public\n * @example\n * ```ts\n * // Validate embed shape properties\n * const isValidUrl = embedShapeProps.url.isValid('https://youtube.com/watch?v=abc123')\n * const isValidSize = embedShapeProps.w.isValid(560)\n * ```\n */\nexport const embedShapeProps: RecordProps<TLEmbedShape> = {\n\tw: T.nonZeroNumber,\n\th: T.nonZeroNumber,\n\turl: T.string,\n}\n\nconst Versions = createShapePropsMigrationIds('embed', {\n\tGenOriginalUrlInEmbed: 1,\n\tRemoveDoesResize: 2,\n\tRemoveTmpOldUrl: 3,\n\tRemovePermissionOverrides: 4,\n})\n\n/**\n * Version identifiers for embed shape migrations.\n *\n * @public\n */\nexport { Versions as embedShapeVersions }\n\n/**\n * Migration sequence for embed shape properties across different schema versions.\n * Handles URL transformations and removal of deprecated properties.\n *\n * @public\n */\nexport const embedShapeMigrations = createShapePropsMigrationSequence({\n\tsequence: [\n\t\t{\n\t\t\tid: Versions.GenOriginalUrlInEmbed,\n\t\t\t// add tmpOldUrl property\n\t\t\tup: (props) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst url = props.url\n\t\t\t\t\tconst host = new URL(url).host.replace('www.', '')\n\t\t\t\t\tlet originalUrl\n\t\t\t\t\tfor (const localEmbedDef of EMBED_DEFINITIONS) {\n\t\t\t\t\t\tif (localEmbedDef.hostnames.includes(host)) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\toriginalUrl = localEmbedDef.fromEmbedUrl(url)\n\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\tconsole.warn(err)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tprops.tmpOldUrl = props.url\n\t\t\t\t\tprops.url = originalUrl ?? ''\n\t\t\t\t} catch {\n\t\t\t\t\tprops.url = ''\n\t\t\t\t\tprops.tmpOldUrl = props.url\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemoveDoesResize,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.doesResize\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemoveTmpOldUrl,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.tmpOldUrl\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemovePermissionOverrides,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.overridePermissions\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t],\n})\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import { safeParseUrl } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'\nimport { RecordProps } from '../recordsWithProps'\nimport { TLBaseShape } from './TLBaseShape'\n\n// Only allow multiplayer embeds. If we add additional routes later for example '/help' this won't match\nconst TLDRAW_APP_RE = /(^\\/r\\/[^/]+\\/?$)/\n\nconst EMBED_DEFINITIONS = [\n\t{\n\t\thostnames: ['beta.tldraw.com', 'tldraw.com', 'localhost:3000'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(TLDRAW_APP_RE)) {\n\t\t\t\treturn url\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['figma.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/?$/)) {\n\t\t\t\tconst outUrl = urlObj.searchParams.get('url')\n\t\t\t\tif (outUrl) {\n\t\t\t\t\treturn outUrl\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['google.*'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (!urlObj) return\n\n\t\t\tconst matches = urlObj.pathname.match(/^\\/maps\\/embed\\/v1\\/view\\/?$/)\n\t\t\tif (matches && urlObj.searchParams.has('center') && urlObj.searchParams.get('zoom')) {\n\t\t\t\tconst zoom = urlObj.searchParams.get('zoom')\n\t\t\t\tconst [lat, lon] = urlObj.searchParams.get('center')!.split(',')\n\t\t\t\treturn `https://www.google.com/maps/@${lat},${lon},${zoom}z`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['val.town'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\t// e.g. extract \"steveruizok/mathFact\" from https://www.val.town/v/steveruizok/mathFact\n\t\t\tconst matches = urlObj && urlObj.pathname.match(/\\/embed\\/(.+)\\/?/)\n\t\t\tif (matches) {\n\t\t\t\treturn `https://www.val.town/v/${matches[1]}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['codesandbox.io'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tconst matches = urlObj && urlObj.pathname.match(/\\/embed\\/([^/]+)\\/?/)\n\t\t\tif (matches) {\n\t\t\t\treturn `https://codesandbox.io/s/${matches[1]}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['codepen.io'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst CODEPEN_EMBED_REGEXP = /https:\\/\\/codepen.io\\/([^/]+)\\/embed\\/([^/]+)/\n\t\t\tconst matches = url.match(CODEPEN_EMBED_REGEXP)\n\t\t\tif (matches) {\n\t\t\t\tconst [_, user, id] = matches\n\t\t\t\treturn `https://codepen.io/${user}/pen/${id}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['scratch.mit.edu'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst SCRATCH_EMBED_REGEXP = /https:\\/\\/scratch.mit.edu\\/projects\\/embed\\/([^/]+)/\n\t\t\tconst matches = url.match(SCRATCH_EMBED_REGEXP)\n\t\t\tif (matches) {\n\t\t\t\tconst [_, id] = matches\n\t\t\t\treturn `https://scratch.mit.edu/projects/${id}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['*.youtube.com', 'youtube.com', 'youtu.be'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (!urlObj) return\n\n\t\t\tconst hostname = urlObj.hostname.replace(/^www./, '')\n\t\t\tif (hostname === 'youtube.com') {\n\t\t\t\tconst matches = urlObj.pathname.match(/^\\/embed\\/([^/]+)\\/?/)\n\t\t\t\tif (matches) {\n\t\t\t\t\treturn `https://www.youtube.com/watch?v=${matches[1]}`\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['calendar.google.*'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tconst srcQs = urlObj?.searchParams.get('src')\n\n\t\t\tif (urlObj?.pathname.match(/\\/calendar\\/embed/) && srcQs) {\n\t\t\t\turlObj.pathname = '/calendar/u/0'\n\t\t\t\tconst keys = Array.from(urlObj.searchParams.keys())\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\turlObj.searchParams.delete(key)\n\t\t\t\t}\n\t\t\t\turlObj.searchParams.set('cid', srcQs)\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['docs.google.*'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\n\t\t\tif (urlObj?.pathname.match(/^\\/presentation/) && urlObj?.pathname.match(/\\/embed\\/?$/)) {\n\t\t\t\turlObj.pathname = urlObj.pathname.replace(/\\/embed$/, '/pub')\n\t\t\t\tconst keys = Array.from(urlObj.searchParams.keys())\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\turlObj.searchParams.delete(key)\n\t\t\t\t}\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['gist.github.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/\\/([^/]+)\\/([^/]+)/)) {\n\t\t\t\tif (!url.split('/').pop()) return\n\t\t\t\treturn url\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['replit.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (\n\t\t\t\turlObj &&\n\t\t\t\turlObj.pathname.match(/\\/@([^/]+)\\/([^/]+)/) &&\n\t\t\t\turlObj.searchParams.has('embed')\n\t\t\t) {\n\t\t\t\turlObj.searchParams.delete('embed')\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['felt.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/map\\//)) {\n\t\t\t\turlObj.pathname = urlObj.pathname.replace(/^\\/embed/, '')\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['open.spotify.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/(artist|album)\\//)) {\n\t\t\t\treturn urlObj.origin + urlObj.pathname.replace(/^\\/embed/, '')\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['vimeo.com', 'player.vimeo.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.hostname === 'player.vimeo.com') {\n\t\t\t\tconst matches = urlObj.pathname.match(/^\\/video\\/([^/]+)\\/?$/)\n\t\t\t\tif (matches) {\n\t\t\t\t\treturn 'https://vimeo.com/' + matches[1]\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['observablehq.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/@([^/]+)\\/([^/]+)\\/?$/)) {\n\t\t\t\treturn `${urlObj.origin}${urlObj.pathname.replace('/embed', '')}#cell-*`\n\t\t\t}\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/([^/]+)\\/?$/)) {\n\t\t\t\treturn `${urlObj.origin}${urlObj.pathname.replace('/embed', '/d')}#cell-*`\n\t\t\t}\n\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['desmos.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (\n\t\t\t\turlObj &&\n\t\t\t\turlObj.hostname === 'www.desmos.com' &&\n\t\t\t\turlObj.pathname.match(/^\\/calculator\\/([^/]+)\\/?$/) &&\n\t\t\t\turlObj.search === '?embed' &&\n\t\t\t\turlObj.hash === ''\n\t\t\t) {\n\t\t\t\treturn url.replace('?embed', '')\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n]\n\n/**\n * Properties for the embed shape, which displays embedded content from external services.\n *\n * @public\n */\nexport interface TLEmbedShapeProps {\n\t/** Width of the embed shape in pixels */\n\tw: number\n\t/** Height of the embed shape in pixels */\n\th: number\n\t/** URL of the content to embed (supports YouTube, Figma, CodePen, etc.) */\n\turl: string\n}\n\n/**\n * An embed shape displays external content like YouTube videos, Figma designs, CodePen demos,\n * and other embeddable content within the tldraw canvas.\n *\n * @public\n * @example\n * ```ts\n * const embedShape: TLEmbedShape = {\n * id: createShapeId(),\n * typeName: 'shape',\n * type: 'embed',\n * x: 200,\n * y: 200,\n * rotation: 0,\n * index: 'a1',\n * parentId: 'page:page1',\n * isLocked: false,\n * opacity: 1,\n * props: {\n * w: 560,\n * h: 315,\n * url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'\n * },\n * meta: {}\n * }\n * ```\n */\nexport type TLEmbedShape = TLBaseShape<'embed', TLEmbedShapeProps>\n\n/**\n * Validation schema for embed shape properties.\n *\n * @public\n * @example\n * ```ts\n * // Validate embed shape properties\n * const isValidUrl = embedShapeProps.url.isValid('https://youtube.com/watch?v=abc123')\n * const isValidSize = embedShapeProps.w.isValid(560)\n * ```\n */\nexport const embedShapeProps: RecordProps<TLEmbedShape> = {\n\tw: T.nonZeroNumber,\n\th: T.nonZeroNumber,\n\turl: T.string,\n}\n\nconst Versions = createShapePropsMigrationIds('embed', {\n\tGenOriginalUrlInEmbed: 1,\n\tRemoveDoesResize: 2,\n\tRemoveTmpOldUrl: 3,\n\tRemovePermissionOverrides: 4,\n})\n\n/**\n * Version identifiers for embed shape migrations.\n *\n * @public\n */\nexport { Versions as embedShapeVersions }\n\n/**\n * Migration sequence for embed shape properties across different schema versions.\n * Handles URL transformations and removal of deprecated properties.\n *\n * @public\n */\nexport const embedShapeMigrations = createShapePropsMigrationSequence({\n\tsequence: [\n\t\t{\n\t\t\tid: Versions.GenOriginalUrlInEmbed,\n\t\t\t// add tmpOldUrl property\n\t\t\tup: (props) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst url = props.url\n\t\t\t\t\tconst host = new URL(url).host.replace('www.', '')\n\t\t\t\t\tlet originalUrl\n\t\t\t\t\tfor (const localEmbedDef of EMBED_DEFINITIONS) {\n\t\t\t\t\t\tif (localEmbedDef.hostnames.includes(host)) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\toriginalUrl = localEmbedDef.fromEmbedUrl(url)\n\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\tconsole.warn(err)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tprops.tmpOldUrl = props.url\n\t\t\t\t\tprops.url = originalUrl ?? ''\n\t\t\t\t} catch {\n\t\t\t\t\tprops.url = ''\n\t\t\t\t\tprops.tmpOldUrl = props.url\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemoveDoesResize,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.doesResize\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemoveTmpOldUrl,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.tmpOldUrl\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemovePermissionOverrides,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.overridePermissions\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t],\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tldraw/tlschema",
|
|
3
3
|
"description": "tldraw infinite canvas SDK (schema).",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.2.0-next.d76c345101d5",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "tldraw Inc.",
|
|
7
7
|
"email": "hello@tldraw.com"
|
|
@@ -51,10 +51,10 @@
|
|
|
51
51
|
"vitest": "^3.2.4"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@tldraw/state": "4.
|
|
55
|
-
"@tldraw/store": "4.
|
|
56
|
-
"@tldraw/utils": "4.
|
|
57
|
-
"@tldraw/validate": "4.
|
|
54
|
+
"@tldraw/state": "4.2.0-next.d76c345101d5",
|
|
55
|
+
"@tldraw/store": "4.2.0-next.d76c345101d5",
|
|
56
|
+
"@tldraw/utils": "4.2.0-next.d76c345101d5",
|
|
57
|
+
"@tldraw/validate": "4.2.0-next.d76c345101d5"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
60
|
"react": "^18.2.0 || ^19.0.0",
|
|
@@ -203,16 +203,6 @@ const EMBED_DEFINITIONS = [
|
|
|
203
203
|
return
|
|
204
204
|
},
|
|
205
205
|
},
|
|
206
|
-
{
|
|
207
|
-
hostnames: ['excalidraw.com'],
|
|
208
|
-
fromEmbedUrl: (url: string) => {
|
|
209
|
-
const urlObj = safeParseUrl(url)
|
|
210
|
-
if (urlObj && urlObj.hash.match(/#room=/)) {
|
|
211
|
-
return url
|
|
212
|
-
}
|
|
213
|
-
return
|
|
214
|
-
},
|
|
215
|
-
},
|
|
216
206
|
{
|
|
217
207
|
hostnames: ['observablehq.com'],
|
|
218
208
|
fromEmbedUrl: (url: string) => {
|