Skip to content

Commit

Permalink
feat: Improve type inference for oEmbed type in TypeScript (#113)
Browse files Browse the repository at this point in the history
Co-authored-by: jack <8209433+jacktuck@users.noreply.github.com>
  • Loading branch information
r4ai and jacktuck committed Feb 13, 2024
1 parent b80b800 commit a1b5a97
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 43 deletions.
59 changes: 44 additions & 15 deletions README.md
Expand Up @@ -58,21 +58,7 @@ type Metadata = {
author?: string
theme_color?: string
canonical_url?: string
oEmbed?: {
type: 'photo' | 'video' | 'link' | 'rich'
version?: string
title?: string
author_name?: string
author_url?: string
provider_name?: string
provider_url?: string
cache_age?: number
thumbnails?: [{
url?: string
width?: number
height?: number
}]
}
oEmbed?: OEmbedPhoto | OEmbedVideo | OEmbedLink | OEmbedRich
twitter_card: {
card: string
site?: string
Expand Down Expand Up @@ -147,6 +133,49 @@ type Metadata = {
}
}
}

type OEmbedBase = {
type: "photo" | "video" | "link" | "rich"
version: string
title?: string
author_name?: string
author_url?: string
provider_name?: string
provider_url?: string
cache_age?: number
thumbnails?: [
{
url?: string
width?: number
height?: number
}
]
}

type OEmbedPhoto = OEmbedBase & {
type: "photo"
url: string
width: number
height: number
}

type OEmbedVideo = OEmbedBase & {
type: "video"
html: string
width: number
height: number
}

type OEmbedLink = OEmbedBase & {
type: "link"
}

type OEmbedRich = OEmbedBase & {
type: "rich"
html: string
width: number
height: number
}
```
## The who 💖
Expand Down
63 changes: 44 additions & 19 deletions src/types.ts
Expand Up @@ -24,25 +24,7 @@ export type Metadata = {
author?: string;
theme_color?: string;
canonical_url?: string;
oEmbed?: {
type: "photo" | "video" | "link" | "rich";
width?: number;
height?: number;
version?: string;
title?: string;
author_name?: string;
author_url?: string;
provider_name?: string;
provider_url?: string;
cache_age?: number;
thumbnails?: [
{
url?: string;
width?: number;
height?: number;
}
];
};
oEmbed?: OEmbedPhoto | OEmbedVideo | OEmbedLink | OEmbedRich;
twitter_card: {
card: string;
site?: string;
Expand Down Expand Up @@ -117,3 +99,46 @@ export type Metadata = {
};
};
};

type OEmbedBase = {
type: "photo" | "video" | "link" | "rich";
version: string;
title?: string;
author_name?: string;
author_url?: string;
provider_name?: string;
provider_url?: string;
cache_age?: number;
thumbnails?: [
{
url?: string;
width?: number;
height?: number;
}
];
};

type OEmbedPhoto = OEmbedBase & {
type: "photo";
url: string;
width: number;
height: number;
};

type OEmbedVideo = OEmbedBase & {
type: "video";
html: string;
width: number;
height: number;
};

type OEmbedLink = OEmbedBase & {
type: "link";
};

type OEmbedRich = OEmbedBase & {
type: "rich";
html: string;
width: number;
height: number;
};
26 changes: 17 additions & 9 deletions test/oembed/test.ts
Expand Up @@ -32,11 +32,15 @@ test("width/height should be numbers", async () => {

const result = await unfurl("http://localhost/html/oembed");

expect(result.oEmbed.width).toEqual(640);
expect(result.oEmbed.height).toEqual(640);
expect(result.oEmbed?.type).toEqual("video");
const oEmbed =
result.oEmbed?.type === "video" ? result.oEmbed : (result.oEmbed as never);

expect(result.oEmbed.thumbnails[0].width).toEqual(200);
expect(result.oEmbed.thumbnails[0].height).toEqual(200);
expect(oEmbed.width).toEqual(640);
expect(oEmbed.height).toEqual(640);

expect(oEmbed.thumbnails?.[0].width).toEqual(200);
expect(oEmbed.thumbnails?.[0].height).toEqual(200);
});

test("should decode entities in OEmbed URL", async () => {
Expand All @@ -54,11 +58,15 @@ test("should decode entities in OEmbed URL", async () => {

const result = await unfurl("http://localhost/html/oembed");

expect(result.oEmbed.width).toEqual(640);
expect(result.oEmbed.height).toEqual(640);
expect(result.oEmbed?.type).toEqual("video");
const oEmbed =
result.oEmbed?.type === "video" ? result.oEmbed : (result.oEmbed as never);

expect(oEmbed.width).toEqual(640);
expect(oEmbed.height).toEqual(640);

expect(result.oEmbed.thumbnails[0].width).toEqual(200);
expect(result.oEmbed.thumbnails[0].height).toEqual(200);
expect(oEmbed.thumbnails?.[0].width).toEqual(200);
expect(oEmbed.thumbnails?.[0].height).toEqual(200);
});

test("should prefer fetching JSON oEmbed", async () => {
Expand Down Expand Up @@ -118,7 +126,7 @@ test("should upgrade to HTTPS if needed", async () => {

const result = await unfurl("http://localhost/html/oembed-http");

expect(result.oEmbed.version).toEqual("1.0");
expect(result.oEmbed?.version).toEqual("1.0");
});

test("should build oEmbed from JSON", async () => {
Expand Down

0 comments on commit a1b5a97

Please sign in to comment.