type DateTime = Date type Url = string export namespace OpenGraph { // Object Types type WebsiteType = "website" type ArticleType = "article" type ProductType = "product" type BookType = "book" type ProfileType = "profile" type MusicType = "music.song" | "music.album" | "music.playlist" | "music.radio_station" type VideoType = "video" | "video.movie" | "video.episode" type ObjectType = WebsiteType | ArticleType | ProductType | BookType | ProfileType | VideoType interface Alternate { alternate: string } interface Basic { // Basic title: string image: Url | Image url: Url // Optional audio?: Url | Audio description?: string determiner?: string locale?: string | Array site_name?: string } interface Image { url: string secure_url?: Url type?: string width?: string height?: string alt?: string } interface Audio { url: string secure_url?: string type?: string } interface Website extends Basic { type: T } interface Article extends Basic { type: T article: { // article:published_time - datetime - When the article was first published. published_time: DateTime // article:modified_time - datetime - When the article was last changed. modified_time: DateTime // article:expiration_time - datetime - When the article is out of date after. expiration_time: DateTime // article:author - profile array - Writers of the article. author: Url | Url[] // article:section - string - A high - level section name.E.g.Technology section: string // article:tag - string array - Tag words associated with this article. tag: string | string[] } } interface Amount { // A decimal number with a '.' as the decimal separator. Values less than 0.01 are not supported. amount: number } interface Currency { // Currency is a string representing the ISO-4217-3 currency code. currency: string } // https://developers.facebook.com/docs/payments/product/ interface Product extends Basic { type: T product: { // product:plural_title - Title of the product when a quantity more than 1 is purchased. plural_title?: string // product:price - Amount | Currency price: Array } } interface Book extends Basic { type: T book: { // book:author - profile array - Who wrote this book. author: Url | Url[] // book:isbn - string - The ISBN isbn: string // book:release_date - datetime - The date the book was released. release_date: DateTime // book:tag - string array - Tag words associated with this book. tag: string | string[] } } interface Profile extends Basic { type: T book: { // profile:first_name - string - A name normally given to an individual by a parent or self-chosen. first_name: string // profile:last_name - string - A name inherited from a family or marriage and by which the individual is commonly known. last_name: string // profile:username - string - A short unique string to identify them. username: string // profile:gender - enum(male, female) - Their gender. gender: "male" | "female" } } interface Music extends Basic { type: T music: Url | Music.Props } interface Video extends Basic { type: T video: Url | Video.Props } namespace Music { interface Disc { // music:song:disc - The disc number this song is on within this album [defaults to ‘1’] disc: number } interface Track { // music:song:track - The track number of this song on this album [relative to the disc number] track: number } export interface Song { // music:duration - integer >= 1 - The song's length in seconds. duration: number // music:album - music.album array - The album this song is from. album: Url | Array // music:musician - profile array - The musician that made this song. musician: Url } export interface Album { // music:song - music.song - The song on this album. song: Url | Url[] | Array // music:musician - profile - The musician that made this song. musician: Url // music:release_date - datetime - The date the album was released. release_date: DateTime } export interface Playlist { // music:song - Identical to the ones on music.album song: Url | Url[] | Array // music:creator - profile - The creator of this playlist. creator: Url } export interface RadioStation { // music:creator - profile - The creator of this station. creator: Url } export type Props = T extends "music.song" ? Music.Song : T extends "music.album" ? Music.Album : T extends "music.playlist" ? Music.Playlist : T extends "music.radio_station" ? Music.RadioStation : never } namespace Video { interface Role { role: string } export interface Base { url: string secure_url?: string type?: string width?: string height?: string } export interface Movie extends Base { // video:actor - profile array - Actors in the movie. actor: string | string[] | Array // video:director - profile array - Directors of the movie. director: Url | Url[] // video:writer - profile array - Writers of the movie. writer: Url | Url[] // video:duration - integer >=1 - The movie's length in seconds. duration: number // video:release_date - datetime - The date the movie was released. release_date: DateTime // video:tag - string array - Tag words associated with this movie. tag: string | string[] } export interface Episode extends Base { // video:actor - profile array - Actors in the movie. actor: string | string[] | Array // video:director - profile array - Directors of the movie. director: string | string[] // video:writer - profile array - Writers of the movie. writer: string | string[] // video:duration - integer >=1 - The movie's length in seconds. duration: number // video:release_date - datetime - The date the movie was released. release_date: DateTime // video:tag - string array - Tag words associated with this movie. tag: string | string[] // video:series - video.tv_show - Which series this episode belongs to. series: string } export type Props = T extends "video" ? Video.Base : T extends "video.movie" ? Video.Movie : T extends "video.episode" ? Video.Episode : never } export type Metadata = T extends WebsiteType ? Website : T extends ArticleType ? Article : T extends ProductType ? Product : T extends BookType ? Book : T extends ProfileType ? Profile : T extends MusicType ? Music : T extends VideoType ? Video : never interface Meta { property: string content: string } const buildIfArray = (object: any[], iterator: (key: string, value: string) => any, parent?: string) => { let data: Meta[] = [] for (const item of object) { const result = build(item, iterator, parent) data = data.concat(result) } return data } const buildIfObject = (object: { [key: string]: any }, iterator: (key: string, value: string) => any, parent?: string) => { let data: Meta[] = [] for (const key of Object.keys(object)) { const value = object[key] const property = parent ? `${parent}:${key}` : key const content = build(value, iterator, property) data = data.concat(content) } return data } export const build = (object: any, iterator: (key: string, value: string) => any, parent?: string) => { let data: Meta[] = [] let property = parent if (Array.isArray(object)) { const content = buildIfArray(object, iterator, property) data = data.concat(content) } else if (typeof object === "object") { const content = buildIfObject(object, iterator, property) data = data.concat(content) } else if (typeof object === "string") { const key = property! const value = `${object}` const content = iterator(key, value) data.push(content) } else if (typeof object === "number") { const key = property! const value = `${object}` const content = iterator(key, value) data.push(content) } return data } }