diff --git a/README.md b/README.md index 71d769d..99e8026 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -// LOGO OR BANNER GOES HERE +![next-gdrive-index](./public/og.png) ## Status ### Project halted at the moment. @@ -13,7 +13,7 @@ I'm currently working on a workaround for this, but it's not a priority for me a ~~You can check the demo [here](https://drive.mbaharip.com).~~ ## What is this? -gudora-index is an indexer for Google Drive, it's a simple project that I made to index my files in Google Drive. +`next-gdrive-index` is an indexer for Google Drive, it's a simple project that I made to index my files in Google Drive. It's aim to simplify the process of sharing files using Google Drive, and also implements some features that I think is useful for sharing files. This project are **HEAVILY INSPIRED** by [onedrive-vercel-index](https://github.com/spencerwooo/onedrive-vercel-index) by SpencerWooo. @@ -46,7 +46,7 @@ I know there are a lot of people selling cheap edu account for Google Drive and ## TODO - [ ] Aim for max 1.5s response time for every API routes - Fetch all routes - 600~900ms - - Fetch file or folder - + - Fetch file or folder - 700~1400ms - [x] Navigate through folders - [ ] File preview - [x] Audio diff --git a/package.json b/package.json index d3d3a15..2fee51f 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@types/react": "18.0.35", "@types/react-dom": "18.0.11", "@upstash/redis": "^1.20.4", + "@vercel/og": "^0.5.4", "autoprefixer": "10.4.14", "axios": "^1.3.5", "cors": "^2.8.5", diff --git a/public/favicon.png b/public/favicon.png new file mode 100644 index 0000000..a9c4021 Binary files /dev/null and b/public/favicon.png differ diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..5c31a8a --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1,713 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/fonts/Exo2-Bold.ttf b/public/fonts/Exo2-Bold.ttf new file mode 100644 index 0000000..8404285 Binary files /dev/null and b/public/fonts/Exo2-Bold.ttf differ diff --git a/public/fonts/Exo2-Regular.ttf b/public/fonts/Exo2-Regular.ttf new file mode 100644 index 0000000..63bc4bb Binary files /dev/null and b/public/fonts/Exo2-Regular.ttf differ diff --git a/public/logo.svg b/public/logo.svg new file mode 100644 index 0000000..6885c17 --- /dev/null +++ b/public/logo.svg @@ -0,0 +1,700 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/og.png b/public/og.png new file mode 100644 index 0000000..ad92661 Binary files /dev/null and b/public/og.png differ diff --git a/src/config/site.config.js b/src/config/site.config.js index 130aff1..b900ae8 100644 --- a/src/config/site.config.js +++ b/src/config/site.config.js @@ -3,13 +3,13 @@ import { BsDiscord, BsGithub, BsPaypal } from "react-icons/bs"; const config = { /* Site MetaData */ // The name of the site - siteName: "My Drive Linker", + siteName: "mbahArip Stash", // The description of the site // Used in meta tags and document head - siteDescription: "My Drive Linker", + siteDescription: "Personal Stash of mbahArip, a place to store my files.", // Fav icon of the site // Also used as the logo of the site on the navbar - siteIcon: "/favicon.ico", + siteIcon: "/favicon.svg", // Navbar menu links navbarLinks: [ { @@ -38,8 +38,8 @@ const config = { ], // Footer text // It will be rendered as - // {year} {footerText} - Powered by guDora-index {version} ❤️ - footerText: "gDrive Linker", + // {year} {footerText} - Powered by next-gdrive-index ❤️ + footerText: "mbahArip Stash", /* Experimental: Render Banner */ banner: { diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index dd00d37..b4275a2 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -51,9 +51,10 @@ export default function App({ Component, pageProps }: AppProps) { type: "website", title: config.siteName, description: config.siteDescription, + url: process.env.NEXT_PUBLIC_DOMAIN, images: [ { - url: `${process.env.NEXT_PUBLIC_DOMAIN}/og-image.png`, + url: `${process.env.NEXT_PUBLIC_DOMAIN}/api/og`, width: 1200, height: 630, alt: config.siteName, diff --git a/src/pages/api/files/[id]/index.ts b/src/pages/api/files/[id]/index.ts index 79c6259..830208c 100644 --- a/src/pages/api/files/[id]/index.ts +++ b/src/pages/api/files/[id]/index.ts @@ -16,7 +16,7 @@ export default initMiddleware(async function handler( const _start = Date.now(); try { - const { id, pageToken, download } = request.query; + const { id, pageToken, download, thumbnail, banner } = request.query; const [name, partialId] = (id as string).split(":"); @@ -49,6 +49,9 @@ export default initMiddleware(async function handler( response.setHeader("Cache-Control", apiConfig.cache); if (file.mimeType !== "application/vnd.google-apps.folder") { + if (thumbnail === "1") { + return response.status(301).redirect(file.thumbnailLink as string); + } if (download === "1") { // Check size if (Number(file.size as string) > apiConfig.maxResponseSize) { @@ -109,6 +112,38 @@ export default initMiddleware(async function handler( const isReadmeExists = !!fetchFolderContents.data.files?.find( (file) => file.name === ".readme.md", ); + const isBannerExists = !!fetchFolderContents.data.files?.find((file) => + file.name?.startsWith(".banner"), + ); + + if (banner === "1") { + if (!isBannerExists) { + throw new ExtendedError("Banner not found.", 404, "notFound"); + } + const bannerFile = fetchFolderContents.data.files?.find((file) => + file.name?.startsWith(".banner"), + ); + const bannerFileStream = await driveClient.files.get( + { + fileId: bannerFile?.id as string, + alt: "media", + }, + { responseType: "stream" }, + ); + response.setHeader( + "Content-Type", + bannerFile?.mimeType || "application/octet-stream", + ); + response.setHeader( + "Content-Disposition", + `attachment; filename=${encodeURIComponent( + bannerFile?.name as string, + )}`, + ); + response.setHeader("Content-Length", bannerFile?.size as string); + return response.status(200).send(bannerFileStream.data); + } + // Get only folder, since we order the folder to be first, we can just get all the folder first const folderList = fetchFolderContents.data.files @@ -126,7 +161,10 @@ export default initMiddleware(async function handler( ?.filter( (item) => !item.mimeType?.startsWith("application/vnd.google-apps") && - !hiddenFiles.includes(item.name as string), + // !hiddenFiles.includes(item.name as string), + !hiddenFiles.some((hiddenFile) => + item.name?.startsWith(hiddenFile), + ), ) .map((item) => ({ ...item, diff --git a/src/pages/api/files/index.ts b/src/pages/api/files/index.ts index d97eeeb..0e39c00 100644 --- a/src/pages/api/files/index.ts +++ b/src/pages/api/files/index.ts @@ -47,7 +47,10 @@ export default initMiddleware(async function handler( ?.filter( (item) => !item.mimeType?.startsWith("application/vnd.google-apps") && - !hiddenFiles.includes(item.name as string), + // !hiddenFiles.includes(item.name as string), + !hiddenFiles.some((hiddenFile) => + item.name?.startsWith(hiddenFile), + ), ) .map((item) => ({ ...item, diff --git a/src/pages/api/og-folder.tsx b/src/pages/api/og-folder.tsx new file mode 100644 index 0000000..cbccf29 --- /dev/null +++ b/src/pages/api/og-folder.tsx @@ -0,0 +1,181 @@ +import { ImageResponse } from "@vercel/og"; +import siteConfig from "config/site.config"; +import { NextRequest } from "next/server"; + +export const config = { + runtime: "edge", +}; + +const fontBold = fetch( + new URL("../../../public/fonts/Exo2-Bold.ttf", import.meta.url), +).then((res) => res.arrayBuffer()); +const fontRegular = fetch( + new URL("../../../public/fonts/Exo2-Regular.ttf", import.meta.url), +).then((res) => res.arrayBuffer()); + +export default async function handler(request: NextRequest) { + try { + const exoFont = await fontRegular; + const exoFontBold = await fontBold; + + const { searchParams } = new URL(request.url); + + const siteName = searchParams.get("siteName") || siteConfig.siteName; + const fileId = searchParams.get("fileId") || null; + const fileName = + searchParams.get("fileName") || fileId?.split(":")[0] || null; + + console.log("Creating og image for", fileName); + + let fileImage; + if (fileId) { + await fetch( + `${process.env.NEXT_PUBLIC_DOMAIN}/api/files/${fileId}?banner=1`, + ) + .then((res) => { + if (res.headers.get("content-type")?.startsWith("image")) { + return { success: true }; + } + return res.json(); + }) + .then((data) => { + if (!data.success) { + throw new Error("File not found"); + } + fileImage = `${process.env.NEXT_PUBLIC_DOMAIN}/api/files/${fileId}?banner=1`; + }) + .catch((err) => { + throw new Error(err); + }); + } else { + throw new Error("Default image"); + } + + return new ImageResponse( + ( +
+
+ {""} +
+
+
+ {""} +
+
+ {siteName} +
+
+ {fileName} +
+
+
+ {""} +
+ +
+
Powered by
+ {""} +
+ next-gdrive-index +
+
+
+ ), + { + width: 1200, + height: 630, + fonts: [ + { + name: "Exo2", + data: exoFont, + weight: 400, + style: "normal", + }, + { + name: "Exo2", + data: exoFontBold, + weight: 700, + style: "normal", + }, + ], + }, + ); + } catch (e) { + return new ImageResponse( + ( +
+ {""} +
+ ), + { + width: 1200, + height: 630, + }, + ); + } +} diff --git a/src/pages/api/og.tsx b/src/pages/api/og.tsx new file mode 100644 index 0000000..cbcdc5f --- /dev/null +++ b/src/pages/api/og.tsx @@ -0,0 +1,189 @@ +import { ImageResponse } from "@vercel/og"; +import siteConfig from "config/site.config"; +import { NextRequest } from "next/server"; + +export const config = { + runtime: "edge", +}; + +const fontBold = fetch( + new URL("../../../public/fonts/Exo2-Bold.ttf", import.meta.url), +).then((res) => res.arrayBuffer()); +const fontRegular = fetch( + new URL("../../../public/fonts/Exo2-Regular.ttf", import.meta.url), +).then((res) => res.arrayBuffer()); + +export default async function handler(request: NextRequest) { + try { + const exoFont = await fontRegular; + const exoFontBold = await fontBold; + + const { searchParams } = new URL(request.url); + + const siteName = searchParams.get("siteName") || siteConfig.siteName; + const fileId = searchParams.get("fileId") || null; + const fileName = + searchParams.get("fileName") || fileId?.split(":")[0] || null; + const fileExt = fileName?.split(".").pop() || null; + + const isImage = ["jpg", "jpeg", "png", "gif", "webp"].includes( + fileExt || "", + ); + + console.log("Creating og image for", fileName); + console.log(fileId, isImage); + + let fileImage; + if (fileId && isImage) { + fileImage = `${process.env.NEXT_PUBLIC_DOMAIN}/api/files/${fileId}?download=1`; + } else if (fileId && !isImage) { + await fetch( + `${process.env.NEXT_PUBLIC_DOMAIN}/api/files/${fileId}?thumbnail=1`, + ) + .then((res) => { + if (res.headers.get("content-type")?.startsWith("image")) { + return { success: true }; + } + return res.json(); + }) + .then((data) => { + if (!data.success) { + throw new Error("File not found"); + } + }) + .catch((err) => { + throw new Error(err); + }); + fileImage = `${process.env.NEXT_PUBLIC_DOMAIN}/api/files/${fileId}?thumbnail=1`; + } else { + throw new Error("Default image"); + } + + return new ImageResponse( + ( +
+
+ {""} +
+
+
+ {""} +
+
+ {siteName} +
+
+ {fileName} +
+
+
+ {""} +
+ +
+
Powered by
+ {""} +
+ next-gdrive-index +
+
+
+ ), + { + width: 1200, + height: 630, + fonts: [ + { + name: "Exo2", + data: exoFont, + weight: 400, + style: "normal", + }, + { + name: "Exo2", + data: exoFontBold, + weight: 700, + style: "normal", + }, + ], + }, + ); + } catch (e) { + return new ImageResponse( + ( +
+ {""} +
+ ), + { + width: 1200, + height: 630, + }, + ); + } +} diff --git a/src/pages/api/search.ts b/src/pages/api/search.ts index cd20cb7..8b81aa3 100644 --- a/src/pages/api/search.ts +++ b/src/pages/api/search.ts @@ -39,7 +39,10 @@ export default async function handler( searchFile.data.files ?.filter( (item) => - !hiddenFiles.includes(item.name as string) && + // !hiddenFiles.includes(item.name as string), + !hiddenFiles.some((hiddenFile) => + item.name?.startsWith(hiddenFile), + ) && (!item.mimeType?.startsWith("application/vnd.google-apps") || item.mimeType === "application/vnd.google-apps.folder"), ) diff --git a/src/utils/driveHelper.ts b/src/utils/driveHelper.ts index d41aa59..37e977b 100644 --- a/src/utils/driveHelper.ts +++ b/src/utils/driveHelper.ts @@ -1,4 +1,4 @@ -export const hiddenFiles = [".password", ".readme.md"]; +export const hiddenFiles = [".password", ".readme.md", ".banner"]; export class ExtendedError extends Error { code?: number; diff --git a/tsconfig.json b/tsconfig.json index 399192c..f831cee 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,6 +25,6 @@ "types/*": ["types/*"], } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"], "exclude": ["node_modules", ".next"] } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index d28a886..aaf561c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -347,11 +347,24 @@ suspend-react "^0.0.8" zustand "^3.7.1" +"@resvg/resvg-wasm@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@resvg/resvg-wasm/-/resvg-wasm-2.4.1.tgz#88f7a08107bf5ea691b016e55e6db955c85d845c" + integrity sha512-yi6R0HyHtsoWTRA06Col4WoDs7SvlXU3DLMNP2bdAgs7HK18dTEVl1weXgxRzi8gwLteGUbIg29zulxIB3GSdg== + "@rushstack/eslint-patch@^1.1.3": version "1.2.0" resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz#8be36a1f66f3265389e90b5f9c9962146758f728" integrity sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg== +"@shuding/opentype.js@1.4.0-beta.0": + version "1.4.0-beta.0" + resolved "https://registry.yarnpkg.com/@shuding/opentype.js/-/opentype.js-1.4.0-beta.0.tgz#5d1e7e9e056f546aad41df1c5043f8f85d39e24b" + integrity sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA== + dependencies: + fflate "^0.7.3" + string.prototype.codepointat "^0.2.1" + "@swc/helpers@0.4.14": version "0.4.14" resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.14.tgz#1352ac6d95e3617ccb7c1498ff019654f1e12a74" @@ -614,6 +627,15 @@ dependencies: "@use-gesture/core" "10.2.26" +"@vercel/og@^0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@vercel/og/-/og-0.5.4.tgz#71de6335b94d0032b325936337c0259d85b9de19" + integrity sha512-o4Zjgw66HPtfGFYG4CFcKfnCcK6qCY+3FC6g22Z1SdAN5jN8XjbHCh3hRVHH5IGBQp8mxH941EcH53KimAm+wg== + dependencies: + "@resvg/resvg-wasm" "2.4.1" + satori "0.7.2" + yoga-wasm-web "0.3.3" + "@webgpu/glslang@^0.0.15": version "0.0.15" resolved "https://registry.yarnpkg.com/@webgpu/glslang/-/glslang-0.0.15.tgz#f5ccaf6015241e6175f4b90906b053f88483d1f2" @@ -868,6 +890,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64-js@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" + integrity sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw== + base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -980,6 +1007,11 @@ camelcase-css@^2.0.1: resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== +camelize@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3" + integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ== + camera-controls@^2.3.1: version "2.3.4" resolved "https://registry.yarnpkg.com/camera-controls/-/camera-controls-2.3.4.tgz#f372b5a4012b474df0ed0c67da7a3198d7efee0b" @@ -1175,6 +1207,30 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +css-background-parser@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/css-background-parser/-/css-background-parser-0.1.0.tgz#48a17f7fe6d4d4f1bca3177ddf16c5617950741b" + integrity sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA== + +css-box-shadow@1.0.0-3: + version "1.0.0-3" + resolved "https://registry.yarnpkg.com/css-box-shadow/-/css-box-shadow-1.0.0-3.tgz#9eaeb7140947bf5d649fc49a19e4bbaa5f602713" + integrity sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg== + +css-color-keywords@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05" + integrity sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg== + +css-to-react-native@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.2.0.tgz#cdd8099f71024e149e4f6fe17a7d46ecd55f1e32" + integrity sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ== + dependencies: + camelize "^1.0.0" + css-color-keywords "^1.0.0" + postcss-value-parser "^4.0.2" + cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -1400,6 +1456,11 @@ electron-to-chromium@^1.4.284: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.365.tgz#ccd9e352d4493aa288d87e6ea36f3edf350c045e" integrity sha512-FRHZO+1tUNO4TOPXmlxetkoaIY8uwHzd1kKopK/Gx2SKn1L47wJXWD44wxP5CGRyyP98z/c8e1eBzJrgPeiBOg== +emoji-regex@^10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.2.1.tgz#a41c330d957191efd3d9dfe6e1e8e1e9ab048b3f" + integrity sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -1841,6 +1902,11 @@ fflate@^0.6.9, fflate@~0.6.9: resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.6.10.tgz#5f40f9659205936a2d18abf88b2e7781662b6d43" integrity sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg== +fflate@^0.7.3: + version "0.7.4" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.7.4.tgz#61587e5d958fdabb5a9368a302c25363f4f69f50" + integrity sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw== + figures@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" @@ -2349,6 +2415,11 @@ hastscript@^7.0.0: property-information "^6.0.0" space-separated-tokens "^2.0.0" +hex-rgb@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/hex-rgb/-/hex-rgb-4.3.0.tgz#af5e974e83bb2fefe44d55182b004ec818c07776" + integrity sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw== + html-void-elements@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-2.0.1.tgz#29459b8b05c200b6c5ee98743c41b979d577549f" @@ -2899,6 +2970,14 @@ lilconfig@^2.0.5, lilconfig@^2.0.6: resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== +linebreak@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/linebreak/-/linebreak-1.1.0.tgz#831cf378d98bced381d8ab118f852bd50d81e46b" + integrity sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ== + dependencies: + base64-js "0.0.8" + unicode-trie "^2.0.0" + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -3778,6 +3857,11 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" +pako@^0.2.5: + version "0.2.9" + resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" + integrity sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -3785,6 +3869,14 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse-css-color@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/parse-css-color/-/parse-css-color-0.2.1.tgz#b687a583f2e42e66ffdfce80a570706966e807c9" + integrity sha512-bwS/GGIFV3b6KS4uwpzCFj4w297Yl3uqnSgIPsoQkx7GMLROXfMnWvxfNkL0oh8HVhZA4hvJoEoEIqonfJ3BWg== + dependencies: + color-name "^1.1.4" + hex-rgb "^4.1.0" + parse-entities@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-4.0.1.tgz#4e2a01111fb1c986549b944af39eeda258fc9e4e" @@ -3911,7 +4003,7 @@ postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.11: cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0: +postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== @@ -4406,6 +4498,21 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +satori@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/satori/-/satori-0.7.2.tgz#1d935f3520ad22009b7b19e4c2e73c55660d6534" + integrity sha512-Eltg0/i3OEbBLaveCnYi2j+p0J9Bb5rmDMXddq4Zy0/NYHbpTkPIlPYGgb+DKamhmvXhiGvWGiFdqHVjJCaCpA== + dependencies: + "@shuding/opentype.js" "1.4.0-beta.0" + css-background-parser "^0.1.0" + css-box-shadow "1.0.0-3" + css-to-react-native "^3.0.0" + emoji-regex "^10.2.1" + linebreak "^1.1.0" + parse-css-color "^0.2.1" + postcss-value-parser "^4.2.0" + yoga-wasm-web "^0.3.3" + scheduler@^0.21.0: version "0.21.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.21.0.tgz#6fd2532ff5a6d877b6edb12f00d8ab7e8f308820" @@ -4777,7 +4884,7 @@ tiny-glob@^0.2.9: globalyzer "0.1.0" globrex "^0.1.2" -tiny-inflate@^1.0.3: +tiny-inflate@^1.0.0, tiny-inflate@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4" integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw== @@ -4924,6 +5031,14 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +unicode-trie@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-trie/-/unicode-trie-2.0.0.tgz#8fd8845696e2e14a8b67d78fa9e0dd2cad62fec8" + integrity sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ== + dependencies: + pako "^0.2.5" + tiny-inflate "^1.0.0" + unified@^10.0.0: version "10.1.2" resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.2.tgz#b1d64e55dafe1f0b98bb6c719881103ecf6c86df" @@ -5234,6 +5349,11 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +yoga-wasm-web@0.3.3, yoga-wasm-web@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/yoga-wasm-web/-/yoga-wasm-web-0.3.3.tgz#eb8e9fcb18e5e651994732f19a220cb885d932ba" + integrity sha512-N+d4UJSJbt/R3wqY7Coqs5pcV0aUj2j9IaQ3rNj9bVCLld8tTGKRa2USARjnvZJWVx1NDmQev8EknoczaOQDOA== + zstddec@^0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/zstddec/-/zstddec-0.0.2.tgz#57e2f28dd1ff56b750e07d158a43f0611ad9eeb4"