diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..c4f3e22 --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +FB_APP_TOKEN= + +HASHNODE_GRAPHQL_URL= +HASHNODE_GRAPHQL_USER_ACCESS_TOKEN= \ No newline at end of file diff --git a/.gitignore b/.gitignore index d5a06f7..26fc1be 100644 --- a/.gitignore +++ b/.gitignore @@ -69,8 +69,8 @@ web_modules/ .yarn-integrity # dotenv environment variables file -.env -.env.test +.env* +!.env.example # parcel-bundler cache (https://parceljs.org/) .cache @@ -113,4 +113,6 @@ dist .yarn/unplugged .yarn/build-state.yml .yarn/install-state.gz -.pnp.* \ No newline at end of file +.pnp.* + +.DS_Store diff --git a/README.md b/README.md index 3f54ed8..e78acce 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,10 @@ -# Webembeds (⚠️ Not to be used in production yet) +![webembeds logo](https://user-images.githubusercontent.com/12823517/167348331-92344edd-e253-4bf7-ba1a-b92daae8ab3b.png) + + +# Webembeds + +**(⚠️ Not to be used in production yet)** + Built and supported by [Hashnode](https://hashnode.com) - Checkout demo here https://webembeds.com/demo diff --git a/example.md b/example.md index f1cad9a..ef0f691 100644 --- a/example.md +++ b/example.md @@ -1,5 +1,11 @@ ## Markdown embed examples +%[https://opensea.io/assets/0x1301566b3cb584e550a02d09562041ddc4989b91/28] + +%[https://opensea.io/assets/0x495f947276749ce646f68ac8c248420045cb7b5e/103558253085473991925726424936776054683291300677177700259118885402889773121537] + +%[https://opensea.io/collection/cyberpunk-vol-1] + %[https://codesandbox.io/s/y2lrywpk21] %[https://codepen.io/szs/pen/JhgKC] @@ -13,6 +19,8 @@ %[https://soundcloud.com/hit-jatt/jatt-disde-arjan-dhillon] %[https://repl.it/@GirishPatil4/AdvancedRespectfulGigahertz] +%[https://replit.com/@BearGrappler/playground] + %[https://runkit.com/runkit/welcome] @@ -38,4 +46,14 @@ %[https://www.canva.com/design/DAEWRhUKdvg/view] -%[https://giphy.com/gifs/cbsnews-inauguration-2021-XEMbxm9vl9JIIMcE7M] \ No newline at end of file +%[https://giphy.com/gifs/cbsnews-inauguration-2021-XEMbxm9vl9JIIMcE7M] + +%[https://www.instagram.com/p/CL8vNB_n_I3/] + +%[https://www.facebook.com/barackobama/posts/10158541668386749] + +%[https://fb.watch/4yOE3vHgMr] + +%[https://www.instagram.com/reel/CMgbGuOgo9 + +%[https://snappify.com/view/bcc54061-6e8f-44c5-a4f4-1abcad520108] diff --git a/packages/webembeds-core/package.json b/packages/webembeds-core/package.json index f474bcf..a9bd5d8 100644 --- a/packages/webembeds-core/package.json +++ b/packages/webembeds-core/package.json @@ -5,7 +5,7 @@ "license": "MIT", "types": "build/index.d.ts", "scripts": { - "watch": "NODE_ENV=development node_modules/.bin/webpack --watch", + "watch": "rimraf ./build && NODE_ENV=development node_modules/.bin/webpack --watch", "build": "NODE_ENV=production node_modules/.bin/webpack", "test": "jest" }, @@ -38,6 +38,8 @@ "node-fetch": "^2.6.1", "oembed": "^0.1.2", "request": "^2.88.2", + "rimraf": "^5.0.0", + "sanitize-html": "^2.6.1", "url-metadata": "^2.5.0", "url-parse": "^1.4.7" } diff --git a/packages/webembeds-core/src/modules/WebembedHandler.ts b/packages/webembeds-core/src/modules/WebembedHandler.ts index e4967a2..cf46312 100644 --- a/packages/webembeds-core/src/modules/WebembedHandler.ts +++ b/packages/webembeds-core/src/modules/WebembedHandler.ts @@ -1,3 +1,4 @@ +/* eslint-disable camelcase */ import oembed from "oembed"; import tryEach from "async/tryEach"; import Platform from "./Platform"; @@ -16,7 +17,11 @@ export default class WebembedHandler { finalResponse: {} = {}; - queryParams: {} = {}; + queryParams: { + forceFallback: boolean, + } = { + forceFallback: false, + }; platform: any = {}; @@ -28,7 +33,9 @@ export default class WebembedHandler { constructor(incomingURL: string, options: any) { const { queryParams = {} } = options; - this.embedURL = incomingURL; + // Replace x.com with twitter.com before doing anything as Provider is setup for twitter.com + const twitterXRegex = new RegExp(/https?:\/\/([a-zA-Z0-9-]+\.)*x\.com/); + this.embedURL = incomingURL.match(twitterXRegex) ? incomingURL.replace(twitterXRegex, "https://twitter.com") : incomingURL; this.options = options; this.queryParams = queryParams; this.providerDetails = this.detectProvider(); @@ -41,29 +48,37 @@ export default class WebembedHandler { * must be made with embedURL, if no targetURL found, it will be the embedURL itself. */ detectProvider = () => { - let destinationProvider: { endpoints: any; } | null = null; + let destinationProvider: { endpoints: any, provider_name: string } | null = null; let targetURL = null; // The endpoint that the embedURL should be queried upon - oEmbedProviders.forEach((provider: { endpoints: any[]; }) => { - provider.endpoints.forEach((endpoint) => { - if (endpoint.schemes && endpoint.schemes.length > 0) { - endpoint.schemes.forEach((scheme: string) => { - // eslint-disable-next-line no-useless-escape - if (this.embedURL.match(scheme.replace(/\*/g, ".*").replace(/\//g, "\/").replace(/\//g, "\\/"))) { - // TODO: Pattern match here - targetURL = endpoint.url; - destinationProvider = provider; - } - }); - } else if (endpoint.url.match(this.embedURL)) { + let found = false; + oEmbedProviders.some((provider: { endpoints: any[], provider_name: string }) => { + provider.endpoints.some((endpoint) => { + if (!endpoint.schemes || endpoint.schemes.length === 0) { // If there are no schemes Ex. https://www.beautiful.ai/ // Consider the url to be the targetURL - destinationProvider = provider; - targetURL = endpoint.url; + + if (this.embedURL.match(endpoint.url.replace(/\*/g, ".*").replace(/\//g, "\/").replace(/\//g, "\\/"))) { + targetURL = endpoint.url; + destinationProvider = provider; + return true; + } + return false; } + + found = endpoint.schemes.some((scheme: string) => { + // eslint-disable-next-line no-useless-escape + if (this.embedURL.match(scheme.replace(/\*/g, ".*").replace(/\//g, "\/").replace(/\//g, "\\/"))) { + targetURL = endpoint.url; + destinationProvider = provider; + return true; + } + return false; + }); + return found; }); + return found; }); - return { provider: destinationProvider, targetURL: targetURL || this.embedURL, @@ -147,7 +162,27 @@ export default class WebembedHandler { */ // eslint-disable-next-line max-len generateOutput = async (): Promise => new Promise((resolve, reject) => { - tryEach([this.generateOEmbed, this.generateManually, this.generateFallback], + if (this.queryParams.forceFallback) { + tryEach([this.generateFallback], + (error: any, results: any): void => { + if (error) { + return reject(error); + } + return resolve(results); + }); + } + + const { provider } = this.providerDetails; + + let actions: any = []; + + if (provider && provider.provider_name === "Twitter") { + actions = [this.generateManually, this.generateFallback]; + } else { + actions = [this.generateOEmbed, this.generateManually, this.generateFallback]; + } + + tryEach(actions, (error: any, results: any): void => { if (error) { reject(error); diff --git a/packages/webembeds-core/src/types.ts b/packages/webembeds-core/src/types.ts index 1987a16..5589187 100644 --- a/packages/webembeds-core/src/types.ts +++ b/packages/webembeds-core/src/types.ts @@ -35,6 +35,7 @@ type Provider = { customClass?: any, discover: boolean, noCustomWrap: boolean, + provider_name: string, } type PlatformType = { diff --git a/packages/webembeds-core/src/utils/graphql.ts b/packages/webembeds-core/src/utils/graphql.ts new file mode 100644 index 0000000..cbacd1c --- /dev/null +++ b/packages/webembeds-core/src/utils/graphql.ts @@ -0,0 +1,55 @@ +/* eslint-disable import/prefer-default-export */ + +const { HASHNODE_GRAPHQL_URL, HASHNODE_GRAPHQL_USER_ACCESS_TOKEN } = process.env; + +if (!HASHNODE_GRAPHQL_URL) { + throw new Error("HASHNODE_GRAPHQL_URL is not defined"); +} + +if (!HASHNODE_GRAPHQL_USER_ACCESS_TOKEN) { + throw new Error("HASHNODE_GRAPHQL_USER_ACCESS_TOKEN is not defined"); +} + +// client tracking (https://dev.stellate.co/docs/graphql-metrics/clients) +const STELLATE_CLIENT_NAME_HEADER = "x-graphql-client-name"; +const STELLATE_CLIENT_VERSION_HEADER = "x-graphql-client-version"; + +const isServer = typeof window === "undefined"; + +/** + * Executes a GraphQL query and returns the data and errors. + */ +export const fetchGraphQL = async (options: { + query: string; + variables?: Record +}) => { + const { query, variables = {} } = options || {}; + + try { + const response = await fetch(HASHNODE_GRAPHQL_URL, { + method: "POST", + headers: { + "Content-Type": "application/json", + "hn-trace-app": "Embeds", + [STELLATE_CLIENT_NAME_HEADER]: "webembeds", + [STELLATE_CLIENT_VERSION_HEADER]: isServer ? "server" : "browser", + Authorization: HASHNODE_GRAPHQL_USER_ACCESS_TOKEN, + }, + body: JSON.stringify({ + query, + ...(variables ? { variables } : {}), + }), + }); + + if (!response.ok) { + throw new Error(`Error fetching GraphQL. Status code: ${response.status}.`); + } + + const json = await response.json(); + const { data, errors } = json; + return { data, errors }; + } catch (error) { + console.error("Error fetching GraphQL", { error }); + throw error; + } +}; diff --git a/packages/webembeds-core/src/utils/html.utils.ts b/packages/webembeds-core/src/utils/html.utils.ts index a0e6e2d..daee7ac 100644 --- a/packages/webembeds-core/src/utils/html.utils.ts +++ b/packages/webembeds-core/src/utils/html.utils.ts @@ -1,9 +1,9 @@ +/* eslint-disable no-useless-escape */ /* eslint-disable no-tabs */ -import request from "request"; import urlMetadata from "url-metadata"; import cheerio from "cheerio"; -import fetch from "node-fetch"; import type { CustomAtrributes, OEmbedResponseType } from "../types"; +import { fetchGraphQL } from "./graphql"; const isProd = process.env.NODE_ENV === "production"; @@ -101,178 +101,109 @@ export const wrapHTML = (oembedResponse: OEmbedResponseType, iframe.attr("class", "webembed-iframe"); $("iframe").wrap( - `
`, + `
`, ); } return $.html(); }; -/** - * Promise based request - * @param {*} url - */ -function doRequest(url) { - return new Promise((resolve, reject) => { - request.get( - { url, encoding: "binary" }, - (error: any, imageResponse: { headers: { [x: string]: any } }, imageBody: string) => { - if (error) { - return reject(error); +async function uploadImageByUrl(url: string) { + let properURL: URL; + try { + properURL = new URL(url); + if (properURL.hostname.includes("hashnode.com") || properURL.hostname.includes("images.unsplash.com")) { + return url; + } + } catch (error) { + throw new Error(`Invalid URL: ${url}`); + } + + const { data, errors } = await fetchGraphQL({ + query: ` + mutation UploadImageByURL($input: UploadImageInput!) { + uploadImageByURL(input: $input) { + imageURL } - const imageType = imageResponse.headers["content-type"]; - const base64 = new Buffer(imageBody, "binary").toString("base64"); - const dataURI = `data:${imageType};base64,${base64}`; - const payload = { - data: dataURI, - isDev: process.env.NODE_ENV === "development", - }; - const hnURL = "https://uploads.hashnode.com/api/upload"; - const cdnURL = "https://cdn.hashnode.com/"; - fetch(hnURL, { - method: "POST", - headers: { - "content-type": "application/json", - "Cloudmate-Authorization": process.env.cloudmateKey || "", - Accept: "*/*", - }, - body: JSON.stringify(payload), - }) - .then((response) => response.json()) - .then((data) => { - if (!data.Key) { - console.log("No cloudmate key"); - return; - } - const imageUrl = cdnURL + data.Key; - resolve(imageUrl); - }); + } + `, + variables: { + input: { + url: properURL.toString(), }, - ); + }, }); + + if (!data || !data.uploadImageByURL?.imageURL || !!errors) { + console.error("Unexpected response uploading image", { data, errors }); + throw new Error("Error uploading image"); + } + + return data.uploadImageByURL.imageURL; } export const wrapFallbackHTML = async (data: urlMetadata.Result) => { let mainURL; - let coverImage: any = data["og:image"] || data["og:image"]; + let isGitHubLink = false; + + const desc = data["og:description"] || data.description; + let coverImage: any = data["og:image"] || data.image; if (isProd) { - coverImage = (await doRequest(data["og:image"])) || data["og:image"]; // Download the image and upload to our CDN + // Download the image and upload to our CDN + coverImage = (await uploadImageByUrl(coverImage)) || coverImage; } try { - mainURL = new URL(data["og:url"]).hostname; + mainURL = new URL(data["og:url"] || data.url).hostname; } catch (error) { mainURL = "/"; } - const description = `${data["og:description"].substring(0, 150)}${ - data["og:description"].length > 150 ? "..." : "" + const description = `${desc.substring(0, 150)}${ + desc.length > 150 ? "..." : "" }`; - return ` - - - - - ${data["og:title"]} - - - - - - - - + return ` + + + `; }; diff --git a/packages/webembeds-core/src/utils/providers/facebook.provider.ts b/packages/webembeds-core/src/utils/providers/facebook.provider.ts new file mode 100644 index 0000000..c286b87 --- /dev/null +++ b/packages/webembeds-core/src/utils/providers/facebook.provider.ts @@ -0,0 +1,34 @@ +import { makeRequest } from "../requestHandler"; +import Platform from "../../modules/Platform"; +import type { OEmbedResponseType, PlatformType } from "../../types"; + +const { FB_APP_TOKEN } = process.env; + +export default class Facebook extends Platform { + hasError: boolean = false; + + // eslint-disable-next-line no-useless-constructor + constructor(args: PlatformType) { + super(args); + if (!FB_APP_TOKEN) { + this.hasError = true; + } + } + + run = async (): Promise => { + if (this.hasError) { + return null; + } + + const response = await makeRequest(`${this.targetURL}?url=${encodeURIComponent(this.embedURL)}&access_token=${FB_APP_TOKEN}`); + const data = response ? response.data : null; + + if (!data) { + return null; + } + + return data; + } +} + +export {}; diff --git a/packages/webembeds-core/src/utils/providers/giphy.provider.ts b/packages/webembeds-core/src/utils/providers/giphy.provider.ts index 4b68f18..1c417a7 100644 --- a/packages/webembeds-core/src/utils/providers/giphy.provider.ts +++ b/packages/webembeds-core/src/utils/providers/giphy.provider.ts @@ -2,7 +2,6 @@ import { makeRequest } from "../requestHandler"; import Platform from "../../modules/Platform"; import type { OEmbedResponseType, PlatformType } from "../../types"; import { wrapHTML } from "../html.utils"; -import Loom from "./loom.provider"; export default class Giphy extends Platform { // eslint-disable-next-line no-useless-constructor @@ -36,10 +35,7 @@ export default class Giphy extends Platform { html, }; - const wrappedHTML = wrapHTML(temp, { - width: data.width || "100%", - height: data.height || "100%", - }); + const wrappedHTML = wrapHTML(temp); return { ...temp, diff --git a/packages/webembeds-core/src/utils/providers/index.ts b/packages/webembeds-core/src/utils/providers/index.ts index 4fac646..256dfbf 100644 --- a/packages/webembeds-core/src/utils/providers/index.ts +++ b/packages/webembeds-core/src/utils/providers/index.ts @@ -4,6 +4,9 @@ import * as Giphy from "./giphy.provider"; import * as Instagram from "./instagram.provider"; import * as Twitch from "./twitch.provider"; import * as Glitch from "./glitch.provider"; +import * as Facebook from "./facebook.provider"; +import * as Opensea from "./opensea.provider"; +import * as Snappify from "./snappify.provider"; export default { GithubGist, @@ -12,4 +15,7 @@ export default { Instagram, Twitch, Glitch, + Facebook, + Opensea, + Snappify, }; diff --git a/packages/webembeds-core/src/utils/providers/instagram.provider.ts b/packages/webembeds-core/src/utils/providers/instagram.provider.ts index ae1f693..c9a5fe7 100644 --- a/packages/webembeds-core/src/utils/providers/instagram.provider.ts +++ b/packages/webembeds-core/src/utils/providers/instagram.provider.ts @@ -1,21 +1,36 @@ +/* eslint-disable camelcase */ +import { makeRequest } from "../requestHandler"; import Platform from "../../modules/Platform"; import type { OEmbedResponseType, PlatformType } from "../../types"; +import { wrapHTML } from "../html.utils"; + +const { FB_APP_TOKEN } = process.env; export default class Instagram extends Platform { + hasError: boolean = false; + // eslint-disable-next-line no-useless-constructor constructor(args: PlatformType) { super(args); + if (!FB_APP_TOKEN) { + this.hasError = true; + } } - run = async (): Promise => { - console.log("Custom Instagram pull"); + run = async (): Promise => { + if (this.hasError) { + return null; + } + + const response = await makeRequest(`${this.targetURL}?url=${encodeURIComponent(this.embedURL)}&access_token=${FB_APP_TOKEN}`); + const data = response ? response.data : null; - // const id = this.embedURL.replace("https://www.instagram.com/p/", "").trim().replace(/\//g, ""); - return { - version: 0.1, - type: "rich", - title: "Instagram", - html: "

Not supported yet

", - }; + if (!data) { + return null; + } + + return data; } } + +export {}; diff --git a/packages/webembeds-core/src/utils/providers/oembed.providers.js b/packages/webembeds-core/src/utils/providers/oembed.providers.js index 77e36ba..b00542e 100644 --- a/packages/webembeds-core/src/utils/providers/oembed.providers.js +++ b/packages/webembeds-core/src/utils/providers/oembed.providers.js @@ -6,6 +6,10 @@ import Twitch from "./twitch.provider"; import Glitch from "./glitch.provider"; import Loom from "./loom.provider"; import Codepen from "./codepen.provider"; +import Facebook from "./facebook.provider"; +import Opensea from "./opensea.provider"; +import Snappify from "./snappify.provider"; +import Tenor from "./tenor.provider"; const oEmbedProviders = [ { @@ -875,42 +879,6 @@ const oEmbedProviders = [ }, ], }, - // { - // provider_name: "Facebook", - // provider_url: "https://www.facebook.com/", - // endpoints: [ - // { - // schemes: [ - // "https://www.facebook.com/*/posts/*", - // "https://www.facebook.com/*/activity/*", - // "https://www.facebook.com/photo.php?fbid=*", - // "https://www.facebook.com/photos/*", - // "https://www.facebook.com/permalink.php?story_fbid=*", - // "https://www.facebook.com/media/set?set=*", - // "https://www.facebook.com/questions/*", - // "https://www.facebook.com/notes/*/*/*", - // ], - // url: "https://graph.facebook.com/v8.0/oembed_post", - // discovery: false, - // }, - // { - // schemes: [ - // "https://www.facebook.com/*/videos/*", - // "https://www.facebook.com/video.php?id=*", - // "https://www.facebook.com/video.php?v=*", - // ], - // url: "https://graph.facebook.com/v8.0/oembed_video", - // discovery: false, - // }, - // { - // schemes: [ - // "https://www.facebook.com/*", - // ], - // url: "https://graph.facebook.com/v8.0/oembed_page", - // discovery: false, - // }, - // ], - // }, { provider_name: "Fader", provider_url: "https://app.getfader.com", @@ -1383,70 +1351,6 @@ const oEmbedProviders = [ }, ], }, - // { - // provider_name: "Instagram", - // provider_url: "https://instagram.com", - // custom: true, - // customClass: Instagram, - // endpoints: [ - // { - // schemes: [ - // "http://instagram.com/*/p/*,", - // "http://www.instagram.com/*/p/*,", - // "https://instagram.com/*/p/*,", - // "https://www.instagram.com/*/p/*,", - // "http://instagram.com/p/*", - // "http://instagr.am/p/*", - // "http://www.instagram.com/p/*", - // "http://www.instagr.am/p/*", - // "https://instagram.com/p/*", - // "https://instagr.am/p/*", - // "https://www.instagram.com/p/*", - // "https://www.instagr.am/p/*", - // "http://instagram.com/tv/*", - // "http://instagr.am/tv/*", - // "http://www.instagram.com/tv/*", - // "http://www.instagr.am/tv/*", - // "https://instagram.com/tv/*", - // "https://instagr.am/tv/*", - // "https://www.instagram.com/tv/*", - // "https://www.instagr.am/tv/*", - // ], - // url: "https://api.instagram.com/oembed", - // formats: [ - // "json", - // ], - // }, - // // { - // // schemes: [ - // // "http://instagram.com/*/p/*,", - // // "http://www.instagram.com/*/p/*,", - // // "https://instagram.com/*/p/*,", - // // "https://www.instagram.com/*/p/*,", - // // "http://instagram.com/p/*", - // // "http://instagr.am/p/*", - // // "http://www.instagram.com/p/*", - // // "http://www.instagr.am/p/*", - // // "https://instagram.com/p/*", - // // "https://instagr.am/p/*", - // // "https://www.instagram.com/p/*", - // // "https://www.instagr.am/p/*", - // // "http://instagram.com/tv/*", - // // "http://instagr.am/tv/*", - // // "http://www.instagram.com/tv/*", - // // "http://www.instagr.am/tv/*", - // // "https://instagram.com/tv/*", - // // "https://instagr.am/tv/*", - // // "https://www.instagram.com/tv/*", - // // "https://www.instagr.am/tv/*", - // // ], - // // url: "https://graph.facebook.com/v8.0/instagram_oembed", - // // formats: [ - // // "json", - // // ], - // // }, - // ], - // }, { provider_name: "Issuu", provider_url: "https://issuu.com/", @@ -2434,14 +2338,18 @@ const oEmbedProviders = [ }, { provider_name: "Replit", - provider_url: "https://repl.it/", + provider_url: "https://replit.com/", endpoints: [ { schemes: [ "https://repl.it/@*/*", + "https://replit.com/@*/*", ], - url: "https://repl.it/data/oembed", + url: "https://replit.com/data/oembed", discovery: true, + example_urls: [ + "https://replit.com/data/oembed/?url=https://replit.com/@replitfaris/python-hello-world", + ], }, ], }, @@ -2792,6 +2700,19 @@ const oEmbedProviders = [ }, ], }, + { + provider_name: "snappify", + provider_url: "https://snappify.com/", + custom: true, + customClass: Snappify, + endpoints: [ + { + schemes: ["https://snappify.io/view/*", "https://snappify.io/embed/*", "https://snappify.com/view/*", "https://snappify.com/embed/*"], + url: "https://api.snappify.com/oembed/", + discovery: false, + }, + ], + }, { provider_name: "SocialExplorer", provider_url: "https://www.socialexplorer.com/", @@ -3779,6 +3700,20 @@ const oEmbedProviders = [ }, ], }, + { + provider_name: "StackBlitz", + provider_url: "https://stackblitz.com", + endpoints: [ + { + schemes: [ + "http://stackblitz.com/edit/*", + "https://stackblitz.com/edit/*", + ], + url: "https://stackblitz.com/api/oembed", + discovery: true, + }, + ], + }, ]; const additionalOEmbedProviders = [ @@ -3872,6 +3807,20 @@ const customProviders = [ }, ], }, + { + provider_name: "Tenor", + provider_url: "https://tenor.com", + custom: true, + customClass: Tenor, + endpoints: [ + { + schemes: [ + "https://tenor.com/*", + ], + url: "https://tenor.com", + }, + ], + }, { provider_name: "Loom", provider_url: "https://loom.com", @@ -3887,6 +3836,21 @@ const customProviders = [ }, ], }, + { + provider_name: "Opensea", + provider_url: "https://opensea.io/", + custom: true, + customClass: Opensea, + endpoints: [ + { + schemes: [ + "https://opensea.io/*", + ], + url: "https://opensea.io", + discovery: false, + }, + ], + }, { provider_name: "Codepen", provider_url: "https://codepen.io", @@ -3903,6 +3867,85 @@ const customProviders = [ }, ], }, + { + provider_name: "Facebook", + provider_url: "https://www.facebook.com/", + endpoints: [ + { + schemes: [ + "https://www.facebook.com/*/posts/*", + "https://www.facebook.com/*/activity/*", + "https://www.facebook.com/photo.php?fbid=*", + "https://www.facebook.com/photos/*", + "https://www.facebook.com/permalink.php?story_fbid=*", + "https://www.facebook.com/media/set?set=*", + "https://www.facebook.com/questions/*", + "https://www.facebook.com/notes/*/*/*", + ], + url: "https://graph.facebook.com/v10.0/oembed_post", + discovery: false, + }, + { + schemes: [ + "https://www.facebook.com/*/videos/*", + "https://www.facebook.com/*/videos/{video-id}", + "https://www.facebook.com/video.php?id=*", + "https://www.facebook.com/video.php?v=*", + "https://fb.watch/*", + ], + url: "https://graph.facebook.com/v10.0/oembed_video", + discovery: false, + }, + { + schemes: [ + "https://www.facebook.com/*", + ], + url: "https://graph.facebook.com/v10.0/oembed_page", + discovery: false, + }, + ], + custom: true, + customClass: Facebook, + }, + { + provider_name: "Instagram", + provider_url: "https://instagram.com", + endpoints: [ + { + schemes: [ + "http://instagram.com/*/p/*,", + "http://www.instagram.com/*/p/*,", + "https://instagram.com/*/p/*,", + "https://www.instagram.com/*/p/*,", + "http://instagram.com/p/*", + "http://instagr.am/p/*", + "http://www.instagram.com/p/*", + "http://www.instagr.am/p/*", + "https://instagram.com/p/*", + "https://instagr.am/p/*", + "https://www.instagram.com/p/*", + "https://www.instagr.am/p/*", + "http://instagram.com/tv/*", + "http://instagr.am/tv/*", + "http://www.instagram.com/tv/*", + "http://www.instagr.am/tv/*", + "https://instagram.com/tv/*", + "https://instagr.am/tv/*", + "https://www.instagram.com/tv/*", + "https://www.instagr.am/tv/*", + "https://www.instagram.com/reel/*", + "https://instagram.com/reel/*", + "https://www.instagr.am/reel/*", + ], + url: "https://graph.facebook.com/v9.0/instagram_oembed", + formats: [ + "json", + ], + }, + ], + custom: true, + customClass: Instagram, + }, ]; export default [...oEmbedProviders, ...additionalOEmbedProviders, ...customProviders]; diff --git a/packages/webembeds-core/src/utils/providers/opensea.provider.ts b/packages/webembeds-core/src/utils/providers/opensea.provider.ts new file mode 100644 index 0000000..bda8ded --- /dev/null +++ b/packages/webembeds-core/src/utils/providers/opensea.provider.ts @@ -0,0 +1,44 @@ +import sanitizeHtml from "sanitize-html"; + +import Platform from "../../modules/Platform"; +import type { OEmbedResponseType, PlatformType } from "../../types"; + +export default class Opensea extends Platform { + // eslint-disable-next-line no-useless-constructor + constructor(args: PlatformType) { + super(args); + } + + run = async (): Promise => { + const url = new URL(this.embedURL); + url.searchParams.set("embed", "true"); + + let html = ""; + + if (url.pathname.includes("/assets")) { + const pathnameChunks = url.pathname.split("/"); + + const hasNetwork = pathnameChunks.length === 5; + const network = hasNetwork ? pathnameChunks[2] : "mainnet"; + const contractAddress = hasNetwork ? pathnameChunks[3] : pathnameChunks[2]; + const tokenId = hasNetwork ? pathnameChunks[4] : pathnameChunks[3]; + + html = ` + + `; + } else { + html = `
`; + } + + return { + version: 0.1, + type: "rich", + title: "Opensea", + html, + }; + }; +} diff --git a/packages/webembeds-core/src/utils/providers/snappify.provider.ts b/packages/webembeds-core/src/utils/providers/snappify.provider.ts new file mode 100644 index 0000000..e5e6cc4 --- /dev/null +++ b/packages/webembeds-core/src/utils/providers/snappify.provider.ts @@ -0,0 +1,36 @@ +import Platform from "../../modules/Platform"; +import type { OEmbedResponseType, PlatformType } from "../../types"; +import { makeRequest } from "../requestHandler"; + +export default class Snappify extends Platform { + // eslint-disable-next-line no-useless-constructor + constructor(args: PlatformType) { + super(args); + } + + run = async (): Promise => { + const response = await makeRequest(`${this.targetURL}?url=${encodeURIComponent(this.embedURL)}`); + const data = response ? response.data : null; + + if (!data || !data.width || !data.height) { + return null; + } + + const host = "https://snappify.com/"; + let path = this.embedURL.split(host)[1]; + path = path.replace("view", "embed"); + + const aspectRatioPercentage = (1 / (data.width / data.height)) * 100; + + const wrapperDivStyle = `position:relative;overflow:hidden;margin-left:auto;margin-right:auto;border-radius:10px;width:100%;max-width:${data.width}px`; + const aspectRatioDivStyle = `width:100%;padding-bottom:${aspectRatioPercentage}%`; + const iframeStyle = "position:absolute;left:0;top:0;width:100%"; + + return { + version: 0.1, + type: "rich", + title: "snappify", + html: `
`, + }; + }; +} diff --git a/packages/webembeds-core/src/utils/providers/tenor.provider.ts b/packages/webembeds-core/src/utils/providers/tenor.provider.ts new file mode 100644 index 0000000..7a276d4 --- /dev/null +++ b/packages/webembeds-core/src/utils/providers/tenor.provider.ts @@ -0,0 +1,37 @@ +import Platform from "../../modules/Platform"; +import type { + OEmbedResponseType, + PlatformType, +} from "../../types"; +import { wrapHTML } from "../html.utils"; + +export default class Tenor extends Platform { + // eslint-disable-next-line no-useless-constructor + constructor(args: PlatformType) { + super(args); + } + + run = async (): Promise => { + const splits = this.embedURL.split("/"); + const lastPart = splits[splits.length - 1]; + const extractedID = lastPart.substring( + lastPart.lastIndexOf("-") + 1, + ); + + const html = ``; + + const temp = { + version: 0.1, + type: "rich", + title: "Tenor", + html, + }; + + const wrappedHTML = wrapHTML(temp); + + return { + ...temp, + html: wrappedHTML, + }; + }; +} diff --git a/packages/webembeds-core/src/utils/requestHandler.ts b/packages/webembeds-core/src/utils/requestHandler.ts index 443ec4a..21e64e2 100644 --- a/packages/webembeds-core/src/utils/requestHandler.ts +++ b/packages/webembeds-core/src/utils/requestHandler.ts @@ -19,6 +19,7 @@ export const makeRequest = async (url: string): Promise => }); return response; } catch (error) { + // console.log(error); return null; } }; @@ -26,7 +27,8 @@ export const makeRequest = async (url: string): Promise => // eslint-disable-next-line max-len export const getMetaData = (url: string): Promise => new Promise((resolve, reject) => { urlMetaData(url).then( - (metadata: urlMetaData.Result) => { // success handler + (metadata: urlMetaData.Result) => { + // success handler // if (!metadata["og:image:width"] || !metadata["og:image:height"]) { // FastImage(metadata["og:image"], (error: any, imageData: any): any => { // if (error) { diff --git a/packages/webembeds-website/pages/_app.tsx b/packages/webembeds-website/pages/_app.tsx index 5828744..8ee1d7b 100644 --- a/packages/webembeds-website/pages/_app.tsx +++ b/packages/webembeds-website/pages/_app.tsx @@ -1,10 +1,23 @@ import React from "react"; import { AppProps } from "next/app"; +import Head from "next/head"; import "../styles/main.css"; // eslint-disable-next-line react/jsx-props-no-spreading -const WebembedsApp = ({ Component, pageProps }: AppProps) => ; +const WebembedsApp = ({ + Component, + pageProps, +}: AppProps) => { + return ( + <> + + Webembeds + + + + ); +}; -export default WebembedsApp; \ No newline at end of file +export default WebembedsApp; diff --git a/packages/webembeds-website/pages/_document.tsx b/packages/webembeds-website/pages/_document.tsx index f799f75..02c4fc5 100644 --- a/packages/webembeds-website/pages/_document.tsx +++ b/packages/webembeds-website/pages/_document.tsx @@ -5,7 +5,21 @@ class CustomDocument extends Document { render() { return ( - + + + + + + + + + + + + + + +
diff --git a/packages/webembeds-website/pages/api/embed.ts b/packages/webembeds-website/pages/api/embed.ts index 156a98d..d11d0fa 100644 --- a/packages/webembeds-website/pages/api/embed.ts +++ b/packages/webembeds-website/pages/api/embed.ts @@ -11,7 +11,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Headers", "*"); - res.setHeader("Cache-Control", "s-maxage=2592000"); + res.setHeader("Cache-Control", "public, s-maxage=31540000"); // 1 year // Twitch needs a parent url where the embed is being used. @@ -22,5 +22,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< ...restOfTheQueryParams, }, }); + res.json({ data: embedResponse }); } diff --git a/packages/webembeds-website/pages/demo.tsx b/packages/webembeds-website/pages/demo.tsx deleted file mode 100644 index 119ee7e..0000000 --- a/packages/webembeds-website/pages/demo.tsx +++ /dev/null @@ -1,234 +0,0 @@ -/* eslint-disable no-console */ -import React, { useState, useEffect, useRef } from "react"; -import Loader from "../components/Loader"; - -const links: any = { - spotify: "https://open.spotify.com/track/3G8o2zm7LaF6eeVuvLlrkJ?si=Sx1sCnhDT6GXqSLIwSLOeQ", - gist: "https://gist.github.com/theevilhead/908d9f761a82809a33fcede797d06334", - // canva1: "https://www.canva.com/design/DAEWSa9kfIs/view", - // canva2: "https://www.canva.com/design/DAEWRhUKdvg/view", - twitter: "https://twitter.com/hashnode/status/1352525138659430400", - expo: "https://snack.expo.io/@girishhashnode/unnamed-snack", - runkit: "https://runkit.com/runkit/welcome", - canva: "https://www.canva.com/design/DAET1m0_11c/jFBlYrKc8CQCb2boU9KC-A/view", - codepen: "https://codepen.io/bsehovac/pen/EMyWVv", - youtube: "https://www.youtube.com/watch?v=32I0Qso4sDg", - glitch: "https://glitch.com/edit/#!/remote-hands", - twitch: "https://www.twitch.tv/fresh", - giphy: "https://giphy.com/gifs/cbsnews-inauguration-2021-XEMbxm9vl9JIIMcE7M", - metascraper: "https://metascraper.js.org/", - repl: "https://repl.it/@GirishPatil4/AdvancedRespectfulGigahertz", - soundcloud: "https://soundcloud.com/hit-jatt/jatt-disde-arjan-dhillon", - anchor: "https://anchor.fm/startapodcast/episodes/Whats-your-podcast-about-e17krq/a-a2q3ft", - loom: "https://www.loom.com/share/0281766fa2d04bb788eaf19e65135184", - vimeo: "https://vimeo.com/485593347", - fallback: "https://github.com", -}; - -function Demo() { - const urlRef = useRef(null); - const [result, setResult] = useState<{ output?: { html?: string }; error: boolean } | null>(); - const [isLoading, setLoading] = useState(false); - let parentNode: HTMLElement | null = null; - - useEffect(() => { - parentNode = document.getElementById("embed-platform"); - - window.adjustIframeSize = function(id: string, newHeight: string) { - const ele = document.getElementById(id); - if (!ele) return; - ele.style.height = parseInt(newHeight) + "px"; - } - - // Can be ported to others too - window.addEventListener("message", function(e) { - if (e.origin !== "https://runkit.com") - return; - - try { - var data = JSON.parse(e.data); - } catch (e) { - return false; - } - - if (data.context !== "iframe.resize") { - return false; - } - - var iframe = document.querySelector("iframe[src=\"" + data.src + "\"]"); - - if (!iframe) { - return false; - } - - iframe.width = "100%"; - - if (data.height) { - console.log("height", data.height) - iframe.height = data.height; - } - }); - - handleURL(links.vimeo); - }, []); - - const handleURL = async (incomingURL?: string) => { - if (null === urlRef) { - return; - } - - if (null === urlRef.current) { - return; - } - - parentNode = document.getElementById("embed-platform"); - if (!parentNode) { - return; - } - - console.log("parentNode", parentNode) - const url = incomingURL || (urlRef !== null ? urlRef.current.value : null); - - if (!url) { - return; - } - - setLoading(true); - setResult(null); - parentNode.innerHTML = ""; - - const requestURL = `/api/embed?url=${encodeURIComponent(url)}&customHost=${encodeURIComponent(window.location.hostname)}`; - const response = await fetch(requestURL, { - method: "GET", - headers: { - Accept: "application/json", - "Content-Type": "application/json", - }, - }); - const json = await response.json(); - - setLoading(false); - - if(parentNode && !url.includes("gist.github.com")) { - parentNode.innerHTML = json.data.output.html; - Array.from(parentNode.querySelectorAll("script")).forEach( async oldScript => { - const newScript = document.createElement("script"); - Array.from(oldScript.attributes).forEach( attr => newScript.setAttribute(attr.name, attr.value) ); - - if (oldScript.innerHTML) { - newScript.appendChild(document.createTextNode(oldScript.innerHTML)); - } - - if (oldScript && oldScript.parentNode) { - oldScript.parentNode.replaceChild(newScript, oldScript); - } - }); - } else { - - const gistFrame = document.createElement("iframe"); - gistFrame.setAttribute("width", "100%"); - gistFrame.setAttribute("frameBorder", "0"); - gistFrame.setAttribute("scrolling", "no"); - gistFrame.id = `gist-${new Date().getTime()}`; - - parentNode.innerHTML = ""; - parentNode.appendChild(gistFrame); - - // Create the iframe's document - const gistFrameHTML = `${json.data.output.html}`; - - // Set iframe's document with a trigger for this document to adjust the height - let gistFrameDoc = gistFrame.document; - - if (gistFrame.contentDocument) { - gistFrameDoc = gistFrame.contentDocument; - } else if (gistFrame.contentWindow) { - gistFrameDoc = gistFrame.contentWindow.document; - } - - if (!gistFrameDoc) { - return; - } - gistFrameDoc.open(); - gistFrameDoc.writeln(gistFrameHTML); - gistFrameDoc.close(); - } - - // setResult(json ? json.data : null); - setLoading(false); - }; - - return ( -
-
- Webembeds -
- {/* Follow @hashnode -   */} - Star us on Github -
-
- -
- {/*
- {result ?
{JSON.stringify(result)}
: "No result"} -
*/} - {isLoading ? : null} - {/* {result && !result.error && !isLoading ? ( */} -
- {/* ) : null} */} - {result && result.error ? "Something went wrong" : ""} -
- -
- -
-
- - -
- -

Or select from below

- -
- {Object.keys(links).map((key, index) => { - return ( - - ); - })} -
-
-
- Made with ❤️   by{" "} - - Hashnode - -
-
- ); -} - -export default Demo; diff --git a/packages/webembeds-website/pages/index.tsx b/packages/webembeds-website/pages/index.tsx index 0fd0ed6..27be18d 100644 --- a/packages/webembeds-website/pages/index.tsx +++ b/packages/webembeds-website/pages/index.tsx @@ -1,14 +1,236 @@ /* eslint-disable no-console */ -import React from "react"; +import React, { useState, useEffect, useRef } from "react"; +import Loader from "../components/Loader"; + +const links: any = { + spotify: "https://open.spotify.com/track/3G8o2zm7LaF6eeVuvLlrkJ?si=Sx1sCnhDT6GXqSLIwSLOeQ", + gist: "https://gist.github.com/theevilhead/908d9f761a82809a33fcede797d06334", + // canva1: "https://www.canva.com/design/DAEWSa9kfIs/view", + // canva2: "https://www.canva.com/design/DAEWRhUKdvg/view", + twitter: "https://twitter.com/hashnode/status/1352525138659430400", + expo: "https://snack.expo.io/@girishhashnode/unnamed-snack", + runkit: "https://runkit.com/runkit/welcome", + canva: "https://www.canva.com/design/DAET1m0_11c/jFBlYrKc8CQCb2boU9KC-A/view", + codepen: "https://codepen.io/bsehovac/pen/EMyWVv", + youtube: "https://www.youtube.com/watch?v=32I0Qso4sDg", + glitch: "https://glitch.com/edit/#!/remote-hands", + twitch: "https://www.twitch.tv/fresh", + giphy: "https://giphy.com/gifs/cbsnews-inauguration-2021-XEMbxm9vl9JIIMcE7M", + metascraper: "https://metascraper.js.org/", + repl: "https://repl.it/@GirishPatil4/AdvancedRespectfulGigahertz", + soundcloud: "https://soundcloud.com/hit-jatt/jatt-disde-arjan-dhillon", + anchor: "https://anchor.fm/startapodcast/episodes/Whats-your-podcast-about-e17krq/a-a2q3ft", + loom: "https://www.loom.com/share/0281766fa2d04bb788eaf19e65135184", + vimeo: "https://vimeo.com/485593347", + snappify: "https://snappify.com/view/bcc54061-6e8f-44c5-a4f4-1abcad520108", + fallback: "https://github.com", +}; + +function Demo() { + const urlRef = useRef(null); + const [result, setResult] = useState<{ output?: { html?: string }; error: boolean } | null>(); + const [isLoading, setLoading] = useState(false); + let parentNode: HTMLElement | null = null; + + useEffect(() => { + parentNode = document.getElementById("embed-platform"); + + if (!window) { + return; + } + + (window as any).adjustIframeSize = function(id: string, newHeight: string) { + const ele = document.getElementById(id); + if (!ele) return; + ele.style.height = parseInt(newHeight) + "px"; + } + + // Can be ported to others too + window.addEventListener("message", function(e) { + if (e.origin !== "https://runkit.com") return; + + try { + var data = JSON.parse(e.data); + } catch (e) { + return false; + } + + if (data.context !== "iframe.resize") { + return false; + } + + const iframe: HTMLIFrameElement | null = document.querySelector("iframe[src=\"" + data.src + "\"]"); + + if (!iframe) { + return false; + } + + iframe.setAttribute("width", "100%"); + + if (data.height) { + iframe.setAttribute("height", data.height); + } + }); + + handleURL(links.vimeo); + }, []); + + const handleURL = async (incomingURL?: string) => { + if (null === urlRef) { + return; + } + + if (null === urlRef.current) { + return; + } + + parentNode = document.getElementById("embed-platform"); + if (!parentNode) { + return; + } + + const url = incomingURL || (urlRef !== null ? urlRef.current.value : null); + + if (!url) { + return; + } + + setLoading(true); + setResult(null); + parentNode.innerHTML = ""; + + const requestURL = `/api/embed?url=${encodeURIComponent(url)}&customHost=${encodeURIComponent(window.location.hostname)}`; + const response = await fetch(requestURL, { + method: "GET", + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + }); + const json = await response.json(); + + setLoading(false); + + if(parentNode && !url.includes("gist.github.com")) { + parentNode.innerHTML = json.data.output.html; + Array.from(parentNode.querySelectorAll("script")).forEach( async oldScript => { + const newScript = document.createElement("script"); + Array.from(oldScript.attributes).forEach( attr => newScript.setAttribute(attr.name, attr.value) ); + + if (oldScript.innerHTML) { + newScript.appendChild(document.createTextNode(oldScript.innerHTML)); + } + + if (oldScript && oldScript.parentNode) { + oldScript.parentNode.replaceChild(newScript, oldScript); + } + }); + } else { + + const gistFrame = document.createElement("iframe"); + gistFrame.setAttribute("width", "100%"); + gistFrame.setAttribute("frameBorder", "0"); + gistFrame.setAttribute("scrolling", "no"); + gistFrame.id = `gist-${new Date().getTime()}`; + + parentNode.innerHTML = ""; + parentNode.appendChild(gistFrame); + + // Create the iframe's document + const gistFrameHTML = `${json.data.output.html}`; + + // Set iframe's document with a trigger for this document to adjust the height + let gistFrameDoc = gistFrame.contentWindow?.document; + + if (gistFrame.contentDocument) { + gistFrameDoc = gistFrame.contentDocument; + } else if (gistFrame.contentWindow) { + gistFrameDoc = gistFrame.contentWindow.document; + } + + if (!gistFrameDoc) { + return; + } + gistFrameDoc.open(); + gistFrameDoc.writeln(gistFrameHTML); + gistFrameDoc.close(); + } + + // setResult(json ? json.data : null); + setLoading(false); + }; -function Index() { return ( -
-

Webembeds

-
-

Easiest embeds

+
+
+ Webembeds +
+ {/* Follow @hashnode +   */} + Star us on Github +
+
+ +
+ {/*
+ {result ?
{JSON.stringify(result)}
: "No result"} +
*/} + {isLoading ? : null} + {/* {result && !result.error && !isLoading ? ( */} +
+ {/* ) : null} */} + {result && result.error ? "Something went wrong" : ""} +
+ +
+ +
+
+ + +
+ +

Or select from below

+ +
+ {Object.keys(links).map((key, index) => { + return ( + + ); + })} +
+
+
+ Made with ❤️   by{" "} + + Hashnode + +
); } -export default Index; +export default Demo; diff --git a/packages/webembeds-website/public/favicons/android-icon-144x144.png b/packages/webembeds-website/public/favicons/android-icon-144x144.png new file mode 100644 index 0000000..716bfce Binary files /dev/null and b/packages/webembeds-website/public/favicons/android-icon-144x144.png differ diff --git a/packages/webembeds-website/public/favicons/android-icon-192x192.png b/packages/webembeds-website/public/favicons/android-icon-192x192.png new file mode 100644 index 0000000..76c6514 Binary files /dev/null and b/packages/webembeds-website/public/favicons/android-icon-192x192.png differ diff --git a/packages/webembeds-website/public/favicons/android-icon-36x36.png b/packages/webembeds-website/public/favicons/android-icon-36x36.png new file mode 100644 index 0000000..a795eee Binary files /dev/null and b/packages/webembeds-website/public/favicons/android-icon-36x36.png differ diff --git a/packages/webembeds-website/public/favicons/android-icon-48x48.png b/packages/webembeds-website/public/favicons/android-icon-48x48.png new file mode 100644 index 0000000..718fe71 Binary files /dev/null and b/packages/webembeds-website/public/favicons/android-icon-48x48.png differ diff --git a/packages/webembeds-website/public/favicons/android-icon-72x72.png b/packages/webembeds-website/public/favicons/android-icon-72x72.png new file mode 100644 index 0000000..48803e0 Binary files /dev/null and b/packages/webembeds-website/public/favicons/android-icon-72x72.png differ diff --git a/packages/webembeds-website/public/favicons/android-icon-96x96.png b/packages/webembeds-website/public/favicons/android-icon-96x96.png new file mode 100644 index 0000000..54264e1 Binary files /dev/null and b/packages/webembeds-website/public/favicons/android-icon-96x96.png differ diff --git a/packages/webembeds-website/public/favicons/apple-icon-114x114.png b/packages/webembeds-website/public/favicons/apple-icon-114x114.png new file mode 100644 index 0000000..d4805a5 Binary files /dev/null and b/packages/webembeds-website/public/favicons/apple-icon-114x114.png differ diff --git a/packages/webembeds-website/public/favicons/apple-icon-120x120.png b/packages/webembeds-website/public/favicons/apple-icon-120x120.png new file mode 100644 index 0000000..1be7d12 Binary files /dev/null and b/packages/webembeds-website/public/favicons/apple-icon-120x120.png differ diff --git a/packages/webembeds-website/public/favicons/apple-icon-144x144.png b/packages/webembeds-website/public/favicons/apple-icon-144x144.png new file mode 100644 index 0000000..716bfce Binary files /dev/null and b/packages/webembeds-website/public/favicons/apple-icon-144x144.png differ diff --git a/packages/webembeds-website/public/favicons/apple-icon-152x152.png b/packages/webembeds-website/public/favicons/apple-icon-152x152.png new file mode 100644 index 0000000..1d4775b Binary files /dev/null and b/packages/webembeds-website/public/favicons/apple-icon-152x152.png differ diff --git a/packages/webembeds-website/public/favicons/apple-icon-180x180.png b/packages/webembeds-website/public/favicons/apple-icon-180x180.png new file mode 100644 index 0000000..c439ec4 Binary files /dev/null and b/packages/webembeds-website/public/favicons/apple-icon-180x180.png differ diff --git a/packages/webembeds-website/public/favicons/apple-icon-57x57.png b/packages/webembeds-website/public/favicons/apple-icon-57x57.png new file mode 100644 index 0000000..5856344 Binary files /dev/null and b/packages/webembeds-website/public/favicons/apple-icon-57x57.png differ diff --git a/packages/webembeds-website/public/favicons/apple-icon-60x60.png b/packages/webembeds-website/public/favicons/apple-icon-60x60.png new file mode 100644 index 0000000..2f773ab Binary files /dev/null and b/packages/webembeds-website/public/favicons/apple-icon-60x60.png differ diff --git a/packages/webembeds-website/public/favicons/apple-icon-72x72.png b/packages/webembeds-website/public/favicons/apple-icon-72x72.png new file mode 100644 index 0000000..48803e0 Binary files /dev/null and b/packages/webembeds-website/public/favicons/apple-icon-72x72.png differ diff --git a/packages/webembeds-website/public/favicons/apple-icon-76x76.png b/packages/webembeds-website/public/favicons/apple-icon-76x76.png new file mode 100644 index 0000000..bbb6995 Binary files /dev/null and b/packages/webembeds-website/public/favicons/apple-icon-76x76.png differ diff --git a/packages/webembeds-website/public/favicons/apple-icon-precomposed.png b/packages/webembeds-website/public/favicons/apple-icon-precomposed.png new file mode 100644 index 0000000..6b79ef6 Binary files /dev/null and b/packages/webembeds-website/public/favicons/apple-icon-precomposed.png differ diff --git a/packages/webembeds-website/public/favicons/apple-icon.png b/packages/webembeds-website/public/favicons/apple-icon.png new file mode 100644 index 0000000..6b79ef6 Binary files /dev/null and b/packages/webembeds-website/public/favicons/apple-icon.png differ diff --git a/packages/webembeds-website/public/favicons/favicon-16x16.png b/packages/webembeds-website/public/favicons/favicon-16x16.png new file mode 100644 index 0000000..e2a3d73 Binary files /dev/null and b/packages/webembeds-website/public/favicons/favicon-16x16.png differ diff --git a/packages/webembeds-website/public/favicons/favicon-32x32.png b/packages/webembeds-website/public/favicons/favicon-32x32.png new file mode 100644 index 0000000..6b44502 Binary files /dev/null and b/packages/webembeds-website/public/favicons/favicon-32x32.png differ diff --git a/packages/webembeds-website/public/favicons/favicon-96x96.png b/packages/webembeds-website/public/favicons/favicon-96x96.png new file mode 100644 index 0000000..54264e1 Binary files /dev/null and b/packages/webembeds-website/public/favicons/favicon-96x96.png differ diff --git a/packages/webembeds-website/public/favicons/favicon.ico b/packages/webembeds-website/public/favicons/favicon.ico new file mode 100644 index 0000000..dc3d597 Binary files /dev/null and b/packages/webembeds-website/public/favicons/favicon.ico differ diff --git a/packages/webembeds-website/public/favicons/ms-icon-144x144.png b/packages/webembeds-website/public/favicons/ms-icon-144x144.png new file mode 100644 index 0000000..716bfce Binary files /dev/null and b/packages/webembeds-website/public/favicons/ms-icon-144x144.png differ diff --git a/packages/webembeds-website/public/favicons/ms-icon-150x150.png b/packages/webembeds-website/public/favicons/ms-icon-150x150.png new file mode 100644 index 0000000..c13adb8 Binary files /dev/null and b/packages/webembeds-website/public/favicons/ms-icon-150x150.png differ diff --git a/packages/webembeds-website/public/favicons/ms-icon-310x310.png b/packages/webembeds-website/public/favicons/ms-icon-310x310.png new file mode 100644 index 0000000..b6749ae Binary files /dev/null and b/packages/webembeds-website/public/favicons/ms-icon-310x310.png differ diff --git a/packages/webembeds-website/public/favicons/ms-icon-70x70.png b/packages/webembeds-website/public/favicons/ms-icon-70x70.png new file mode 100644 index 0000000..93c35ff Binary files /dev/null and b/packages/webembeds-website/public/favicons/ms-icon-70x70.png differ diff --git a/yarn.lock b/yarn.lock index d133e9c..8e86532 100644 --- a/yarn.lock +++ b/yarn.lock @@ -457,6 +457,18 @@ resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.1.1.tgz#9daf5745156fd84b8e9889a2dc721f0c58e894aa" integrity sha512-CAEbWH7OIur6jEOzaai83jq3FmKmv4PmX1JYfs9IrYcGEVI/lyL1EXJGCj7eFVJ0bg5QR8LMxBlEtA+xKiLpFw== +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -708,6 +720,11 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/context-base/-/context-base-0.14.0.tgz#c67fc20a4d891447ca1a855d7d70fa79a3533001" integrity sha512-sDOAZcYwynHFTbLo6n8kIbLiVF3a3BLkrmehJUyEbT9F+Smbi47kLGS2gG2g0fjBLR/Lr1InPD7kXL7FaTqEkw== +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + "@sindresorhus/is@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.0.0.tgz#2ff674e9611b45b528896d820d3d7a812de2f0e4" @@ -1525,6 +1542,16 @@ ansi-regex@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -1544,6 +1571,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" @@ -1965,6 +1997,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + braces@^2.3.1, braces@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" @@ -3337,6 +3376,11 @@ duplexify@^3.4.2, duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -3388,6 +3432,11 @@ emoji-regex@^9.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.0.tgz#a26da8e832b16a9753309f25e35e3c0efb9a066a" integrity sha512-DNc3KFPK18bPdElMJnf/Pkv5TXhxFU3YFDEuGLDRtPmV4rkmCjBkCSEp22u6rBHdSN9Vlp/GK7k98prmE1Jgug== +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" @@ -3553,6 +3602,11 @@ escape-string-regexp@^2.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + escodegen@^1.14.1: version "1.14.3" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" @@ -4356,6 +4410,14 @@ for-in@^1.0.2: resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= +foreground-child@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" + integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -4578,6 +4640,17 @@ glob@7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^10.0.0: + version "10.2.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.2.4.tgz#f5bf7ddb080e3e9039b148a9e2aef3d5ebfc0a25" + integrity sha512-fDboBse/sl1oXSLhIp0FcCJgzW9KmhC/q8ULTKC82zc+DL3TL7FNb8qlt5qqXN53MsKEUSIcb+7DLmEygOE5Yw== + dependencies: + foreground-child "^3.1.0" + jackspeak "^2.0.3" + minimatch "^9.0.0" + minipass "^5.0.0 || ^6.0.0" + path-scurry "^1.7.0" + glob@^7.0.0, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" @@ -5258,6 +5331,11 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + is-potential-custom-element-name@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397" @@ -5392,6 +5470,15 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +jackspeak@^2.0.3: + version "2.2.0" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.2.0.tgz#497cbaedc902ec3f31d5d61be804d2364ff9ddad" + integrity sha512-r5XBrqIJfwRIjRt/Xr5fv9Wh09qyhHfKnYddDlpM+ibRR20qrYActpCAgU6U+d53EOEjzkvxPMVHSlgR7leXrQ== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + jest-changed-files@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.6.2.tgz#f6198479e1cc66f22f9ae1e22acaa0b429c042d0" @@ -6216,6 +6303,11 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lru-cache@^9.1.1: + version "9.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-9.1.1.tgz#c58a93de58630b688de39ad04ef02ef26f1902f1" + integrity sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A== + make-dir@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -6404,11 +6496,23 @@ minimatch@^3.0.3, minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" +minimatch@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.0.tgz#bfc8e88a1c40ffd40c172ddac3decb8451503b56" + integrity sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w== + dependencies: + brace-expansion "^2.0.1" + minimist@1.2.5, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +"minipass@^5.0.0 || ^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-6.0.0.tgz#3b000c121dd32da5dc56156381dc322b4f2ffaa0" + integrity sha512-mvD5U4pUen1aWcjTxUgdoMg6PB98dcV0obc/OiPzls79++IpgNoO+MCbOHRlKfWIOvjIjmjUygjZmSStP7B0Og== + mississippi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" @@ -6502,6 +6606,11 @@ nanoid@^3.1.16, nanoid@^3.1.20: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788" integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw== +nanoid@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c" + integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -7086,6 +7195,11 @@ parse-passwd@^1.0.0: resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= +parse-srcset@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1" + integrity sha1-8r0iH2zJcKk42IVWq8WJyqqiveE= + parse5-htmlparser2-tree-adapter@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" @@ -7163,6 +7277,14 @@ path-parse@^1.0.6: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== +path-scurry@^1.7.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.9.1.tgz#838566bb22e38feaf80ecd49ae06cd12acd782ee" + integrity sha512-UgmoiySyjFxP6tscZDgWGEAgsW5ok8W3F5CJDnnH2pozwSTGE6eH7vwTotMwATWA2r5xqdkKdxYPkwlJjAI/3g== + dependencies: + lru-cache "^9.1.1" + minipass "^5.0.0 || ^6.0.0" + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -7196,6 +7318,11 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" @@ -7430,6 +7557,15 @@ postcss@^8.1.6, postcss@^8.2.1, postcss@^8.2.4: nanoid "^3.1.20" source-map "^0.6.1" +postcss@^8.3.11: + version "8.4.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.6.tgz#c5ff3c3c457a23864f32cb45ac9b741498a09ae1" + integrity sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA== + dependencies: + nanoid "^3.2.0" + picocolors "^1.0.0" + source-map-js "^1.0.2" + prebuild-install@^5.3.5: version "5.3.6" resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.6.tgz#7c225568d864c71d89d07f8796042733a3f54291" @@ -8050,6 +8186,13 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +rimraf@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.0.tgz#5bda14e410d7e4dd522154891395802ce032c2cb" + integrity sha512-Jf9llaP+RvaEVS5nPShYFhtXIrb3LRKP281ib3So0KkeZKo2wIKyq0Re7TOSwanasA423PSr6CCIL4bP6T040g== + dependencies: + glob "^10.0.0" + rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -8138,6 +8281,18 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" +sanitize-html@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.6.1.tgz#5d37c08e189c61c0631560a889b10d9d155d000e" + integrity sha512-DzjSz3H5qDntD7s1TcWCSoRPmNR8UmA+y+xZQOvWgjATe2Br9ZW73+vD3Pj6Snrg0RuEuJdXgrKvnYuiuixRkA== + dependencies: + deepmerge "^4.2.2" + escape-string-regexp "^4.0.0" + htmlparser2 "^6.0.0" + is-plain-object "^5.0.0" + parse-srcset "^1.0.2" + postcss "^8.3.11" + sass-loader@10.0.5: version "10.0.5" resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.0.5.tgz#f53505b5ddbedf43797470ceb34066ded82bb769" @@ -8347,6 +8502,11 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== +signal-exit@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.0.2.tgz#ff55bb1d9ff2114c13b400688fa544ac63c36967" + integrity sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q== + simple-concat@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" @@ -8438,6 +8598,11 @@ source-list-map@^2.0.0, source-list-map@^2.0.1: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" @@ -8654,6 +8819,15 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -8680,6 +8854,15 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + string.prototype.matchall@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz#24243399bc31b0a49d19e2b74171a15653ec996a" @@ -8723,6 +8906,13 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@6.0.0, strip-ansi@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" @@ -8751,6 +8941,13 @@ strip-ansi@^5.1.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" + integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== + dependencies: + ansi-regex "^6.0.1" + strip-bom@4.0.0, strip-bom@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" @@ -9718,6 +9915,15 @@ worker-farm@^1.7.0: dependencies: errno "~0.1.7" +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -9727,6 +9933,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"