diff --git a/bskyogcard/package.json b/bskyogcard/package.json index 670883d413..a46cf17d60 100644 --- a/bskyogcard/package.json +++ b/bskyogcard/package.json @@ -15,6 +15,7 @@ "@resvg/resvg-js": "^2.6.2", "express": "^4.19.2", "http-terminator": "^3.2.0", + "node-vibrant": "^4.0.3", "pino": "^9.2.0", "react": "^18.3.1", "satori": "^0.10.13", diff --git a/bskyogcard/src/components/Post.tsx b/bskyogcard/src/components/Post.tsx index c59c3f4345..6867fe8eb6 100644 --- a/bskyogcard/src/components/Post.tsx +++ b/bskyogcard/src/components/Post.tsx @@ -6,7 +6,7 @@ import { import {ModeratorData} from '../data/getModeratorData.js' import {PostData} from '../data/getPostData.js' -import {atoms as a, gradient, theme as t} from '../theme/index.js' +import {atoms as a, theme as t} from '../theme/index.js' import {formatCount} from '../util/formatCount.js' import {formatDate} from '../util/formatDate.js' import {moderatePost} from '../util/moderatePost.js' @@ -24,13 +24,20 @@ export function Post({ post, data, moderatorData, + displayOptions: opts = { + mat: false, + }, }: { post: AppBskyFeedDefs.PostView data: PostData moderatorData: ModeratorData + displayOptions?: { + mat?: boolean + } }) { if (AppBskyFeedPost.isValidRecord(post.record)) { const avatar = data.images.get(post.author.avatar) + console.log(avatar.colors.vibrant) const rt = post.record.text ? new RichTextApi({ text: post.record.text, @@ -47,10 +54,13 @@ export function Post({ a.align_center, a.w_full, a.h_full, - a.p_3xl, - { - backgroundImage: `linear-gradient(to bottom, ${gradient('sky')})`, - }, + opts.mat && [ + a.p_xl, + { + borderRadius: '22px', + backgroundImage: `linear-gradient(to bottom, ${avatar.colors.muted} 0%, ${avatar.colors.lightMuted} 100%)`, + }, + ], ]}> ) { } } +export async function getImageColors(image: Buffer) { + const palette = await Vibrant.from(image).getPalette() + return { + vibrant: palette.Vibrant?.hex, + darkVibrant: palette.DarkVibrant?.hex, + lightVibrant: palette.LightVibrant?.hex, + muted: palette.Muted?.hex, + darkMuted: palette.DarkMuted?.hex, + lightMuted: palette.LightMuted?.hex, + } +} + export async function getPostData( post: AppBskyFeedDefs.PostView, ): Promise { const images: Map = new Map() - console.log(JSON.stringify(post, null, 2)) if (post.author.avatar) { images.set(post.author.avatar, { @@ -146,12 +166,14 @@ export async function getPostData( const resolved = await Promise.all( deduped.map(async ([url, meta]) => { try { - const image = await getImage(url) + const imageData = await getImage(url) + const palette = await getImageColors(imageData.image) return [ url, { + colors: palette, ...meta, - ...image, + ...imageData, }, ] as const } catch (err) { diff --git a/bskyogcard/src/routes/index.ts b/bskyogcard/src/routes/index.ts index 666b14140a..08fa8244f7 100644 --- a/bskyogcard/src/routes/index.ts +++ b/bskyogcard/src/routes/index.ts @@ -10,6 +10,6 @@ export * from './util.js' export default function (ctx: AppContext, app: Express) { app = health(ctx, app) // GET /_health app = starterPack(ctx, app) // GET /start/:actor/:rkey - app = post(ctx, app) // POST /post + app = post(ctx, app) // POST /profile/:handle/post/:rkey return app } diff --git a/bskyogcard/src/routes/post.tsx b/bskyogcard/src/routes/post.tsx index c792656f50..4f6a1e9984 100644 --- a/bskyogcard/src/routes/post.tsx +++ b/bskyogcard/src/routes/post.tsx @@ -10,13 +10,15 @@ import {getPost} from '../data/getPost.js' import {getPostData} from '../data/getPostData.js' import {httpLogger} from '../logger.js' import {loadEmojiAsSvg} from '../util.js' +import { + getRenderOptions, + parseDisplayOptionsFromQuery, +} from '../util/postDisplayOptions.js' import {handler, originVerifyMiddleware} from './util.js' -const WIDTH = 600 - export default function (ctx: AppContext, app: Express) { return app.get( - '/:actor/post/:rkey', + '/profile/:actor/post/:rkey', originVerifyMiddleware(ctx), handler(async (req, res) => { let {actor, rkey} = req.params @@ -42,12 +44,19 @@ export default function (ctx: AppContext, app: Express) { getPostData(post), getModeratorData(ctx.appviewAgent), ]) + const displayOptions = parseDisplayOptionsFromQuery(req.query) + const {width} = getRenderOptions(displayOptions) const svg = await satori( - , + , { fonts: ctx.fonts, - width: WIDTH, + width, loadAdditionalAsset: async (code, text) => { if (code === 'emoji') { return await loadEmojiAsSvg(text) @@ -58,7 +67,7 @@ export default function (ctx: AppContext, app: Express) { const output = await resvg.renderAsync(svg, { fitTo: { mode: 'width', - value: WIDTH * 2, + value: width * 2, }, logLevel: 'trace', }) diff --git a/bskyogcard/src/theme/atoms.ts b/bskyogcard/src/theme/atoms.ts index 028e0d6fcd..88bf5f7180 100644 --- a/bskyogcard/src/theme/atoms.ts +++ b/bskyogcard/src/theme/atoms.ts @@ -68,6 +68,9 @@ export const atoms = { rounded_md: { borderRadius: tokens.borderRadius.md, }, + rounded_lg: { + borderRadius: tokens.borderRadius.lg, + }, rounded_full: { borderRadius: tokens.borderRadius.full, }, diff --git a/bskyogcard/src/theme/index.ts b/bskyogcard/src/theme/index.ts index cc1bde60cc..e83439ccd4 100644 --- a/bskyogcard/src/theme/index.ts +++ b/bskyogcard/src/theme/index.ts @@ -87,7 +87,7 @@ export const theme = { } export function style(styleObjects: Record[]) { - return Object.assign({}, ...styleObjects.filter(Boolean)) + return Object.assign({}, ...styleObjects.filter(Boolean).flat()) } export function gradient(color: keyof typeof tokens.gradients) { diff --git a/bskyogcard/src/theme/tokens.ts b/bskyogcard/src/theme/tokens.ts index 9bfaa6cc4b..b52af1045e 100644 --- a/bskyogcard/src/theme/tokens.ts +++ b/bskyogcard/src/theme/tokens.ts @@ -35,6 +35,7 @@ export const borderRadius = { xs: 4, sm: 8, md: 12, + lg: 20, full: 999, } as const @@ -101,4 +102,11 @@ export const gradients = { ], hover_value: '#755B62', }, + neutral: { + values: [ + [0, '#E0E5EB'], + [1, '#EFF2F5'], + ], + hover_value: '#755B62', + }, } as const diff --git a/bskyogcard/src/util/postDisplayOptions.ts b/bskyogcard/src/util/postDisplayOptions.ts new file mode 100644 index 0000000000..19d438b90b --- /dev/null +++ b/bskyogcard/src/util/postDisplayOptions.ts @@ -0,0 +1,29 @@ +import {ParsedQs} from 'qs' + +export type DisplayOptions = { + mat: boolean +} + +export function parseDisplayOptionsFromQuery(query: ParsedQs): DisplayOptions { + const opts: DisplayOptions = { + mat: false, + } + + ;['mat'].forEach(key => { + const val = query[key] + if (val === 'true' || val === '1') { + opts[key] = true + } else { + opts[key] = false + } + }) + + return opts +} + +export function getRenderOptions(options: DisplayOptions) { + return { + // must match width + padding of Post.tsx + width: options.mat ? 400 : 360, + } +} diff --git a/bskyogcard/yarn.lock b/bskyogcard/yarn.lock index 9a3a6eb9bc..25b3d431cb 100644 --- a/bskyogcard/yarn.lock +++ b/bskyogcard/yarn.lock @@ -117,6 +117,93 @@ cborg "^1.6.0" multiformats "^9.5.4" +"@jimp/bmp@^0.22.12": + version "0.22.12" + resolved "https://registry.yarnpkg.com/@jimp/bmp/-/bmp-0.22.12.tgz#0316044dc7b1a90274aef266d50349347fb864d4" + integrity sha512-aeI64HD0npropd+AR76MCcvvRaa+Qck6loCOS03CkkxGHN5/r336qTM5HPUdHKMDOGzqknuVPA8+kK1t03z12g== + dependencies: + "@jimp/utils" "^0.22.12" + bmp-js "^0.1.0" + +"@jimp/core@^0.22.12": + version "0.22.12" + resolved "https://registry.yarnpkg.com/@jimp/core/-/core-0.22.12.tgz#70785ea7d10b138fb65bcfe9f712826f00a10e1d" + integrity sha512-l0RR0dOPyzMKfjUW1uebzueFEDtCOj9fN6pyTYWWOM/VS4BciXQ1VVrJs8pO3kycGYZxncRKhCoygbNr8eEZQA== + dependencies: + "@jimp/utils" "^0.22.12" + any-base "^1.1.0" + buffer "^5.2.0" + exif-parser "^0.1.12" + file-type "^16.5.4" + isomorphic-fetch "^3.0.0" + pixelmatch "^4.0.2" + tinycolor2 "^1.6.0" + +"@jimp/custom@^0.22.12": + version "0.22.12" + resolved "https://registry.yarnpkg.com/@jimp/custom/-/custom-0.22.12.tgz#236f2a3f016b533c50869ff22ad1ac00dd0c36be" + integrity sha512-xcmww1O/JFP2MrlGUMd3Q78S3Qu6W3mYTXYuIqFq33EorgYHV/HqymHfXy9GjiCJ7OI+7lWx6nYFOzU7M4rd1Q== + dependencies: + "@jimp/core" "^0.22.12" + +"@jimp/gif@^0.22.12": + version "0.22.12" + resolved "https://registry.yarnpkg.com/@jimp/gif/-/gif-0.22.12.tgz#6caccb45df497fb971b7a88690345596e22163c0" + integrity sha512-y6BFTJgch9mbor2H234VSjd9iwAhaNf/t3US5qpYIs0TSbAvM02Fbc28IaDETj9+4YB4676sz4RcN/zwhfu1pg== + dependencies: + "@jimp/utils" "^0.22.12" + gifwrap "^0.10.1" + omggif "^1.0.9" + +"@jimp/jpeg@^0.22.12": + version "0.22.12" + resolved "https://registry.yarnpkg.com/@jimp/jpeg/-/jpeg-0.22.12.tgz#b5c74a5aac9826245311370dda8c71a1fcca05ed" + integrity sha512-Rq26XC/uQWaQKyb/5lksCTCxXhtY01NJeBN+dQv5yNYedN0i7iYu+fXEoRsfaJ8xZzjoANH8sns7rVP4GE7d/Q== + dependencies: + "@jimp/utils" "^0.22.12" + jpeg-js "^0.4.4" + +"@jimp/plugin-resize@^0.22.12": + version "0.22.12" + resolved "https://registry.yarnpkg.com/@jimp/plugin-resize/-/plugin-resize-0.22.12.tgz#f92acbf73beb97dd1fe93b166ef367a323b81e81" + integrity sha512-3NyTPlPbTnGKDIbaBgQ3HbE6wXbAlFfxHVERmrbqAi8R3r6fQPxpCauA8UVDnieg5eo04D0T8nnnNIX//i/sXg== + dependencies: + "@jimp/utils" "^0.22.12" + +"@jimp/png@^0.22.12": + version "0.22.12" + resolved "https://registry.yarnpkg.com/@jimp/png/-/png-0.22.12.tgz#e033586caf38d9c9d33808e92eb87c4d7f0aa1eb" + integrity sha512-Mrp6dr3UTn+aLK8ty/dSKELz+Otdz1v4aAXzV5q53UDD2rbB5joKVJ/ChY310B+eRzNxIovbUF1KVrUsYdE8Hg== + dependencies: + "@jimp/utils" "^0.22.12" + pngjs "^6.0.0" + +"@jimp/tiff@^0.22.12": + version "0.22.12" + resolved "https://registry.yarnpkg.com/@jimp/tiff/-/tiff-0.22.12.tgz#67cac3f2ded6fde3ef631fbf74bea0fa53800123" + integrity sha512-E1LtMh4RyJsoCAfAkBRVSYyZDTtLq9p9LUiiYP0vPtXyxX4BiYBUYihTLSBlCQg5nF2e4OpQg7SPrLdJ66u7jg== + dependencies: + utif2 "^4.0.1" + +"@jimp/types@^0.22.12": + version "0.22.12" + resolved "https://registry.yarnpkg.com/@jimp/types/-/types-0.22.12.tgz#6f83761ba171cb8cd5998fa66a5cbfb0b22d3d8c" + integrity sha512-wwKYzRdElE1MBXFREvCto5s699izFHNVvALUv79GXNbsOVqlwlOxlWJ8DuyOGIXoLP4JW/m30YyuTtfUJgMRMA== + dependencies: + "@jimp/bmp" "^0.22.12" + "@jimp/gif" "^0.22.12" + "@jimp/jpeg" "^0.22.12" + "@jimp/png" "^0.22.12" + "@jimp/tiff" "^0.22.12" + timm "^1.6.1" + +"@jimp/utils@^0.22.12": + version "0.22.12" + resolved "https://registry.yarnpkg.com/@jimp/utils/-/utils-0.22.12.tgz#8ffaed8f2dc2962539ccaf14727ac60793c7a537" + integrity sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q== + dependencies: + regenerator-runtime "^0.13.3" + "@jridgewell/resolve-uri@^3.0.3": version "3.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" @@ -221,6 +308,11 @@ fflate "^0.7.3" string.prototype.codepointat "^0.2.1" +"@tokenizer/token@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276" + integrity sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A== + "@tsconfig/node10@^1.0.7": version "1.0.11" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" @@ -241,6 +333,18 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== +"@types/node@16.9.1": + version "16.9.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.1.tgz#0611b37db4246c937feef529ddcc018cf8e35708" + integrity sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g== + +"@types/node@^18.15.3": + version "18.19.80" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.80.tgz#6d6008e8920dddcd23f9dd33da24684ef57d487c" + integrity sha512-kEWeMwMeIvxYkeg1gTc01awpwLbfMRZXdIhwRcakd/KlK53jmRC26LqcbIt7fnAQTu5GzlnWmzA3H6+l1u6xxQ== + dependencies: + undici-types "~5.26.4" + "@types/node@^20.14.3": version "20.14.3" resolved "https://registry.npmjs.org/@types/node/-/node-20.14.3.tgz" @@ -248,6 +352,92 @@ dependencies: undici-types "~5.26.4" +"@vibrant/color@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@vibrant/color/-/color-4.0.0.tgz#f804da47caf0072bc9bafddd94aa42650b0d1e25" + integrity sha512-S9ItdqS1135wTXoIIqAJu8df9dqlOo6Boc5Y4MGsBTu9UmUOvOwfj5b4Ga6S5yrLAKmKYIactkz7zYJdMddkig== + +"@vibrant/core@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@vibrant/core/-/core-4.0.0.tgz#a13a56b223c7f12543773b8d8ba2263096c6f5ce" + integrity sha512-fqlVRUTDjEws9VNKvI3cDXM4wUT7fMFS+cVqEjJk3im+R5EvjJzPF6OAbNhfPzW04NvHNE555eY9FfhYuX3PRw== + dependencies: + "@vibrant/color" "^4.0.0" + "@vibrant/generator" "^4.0.0" + "@vibrant/image" "^4.0.0" + "@vibrant/quantizer" "^4.0.0" + "@vibrant/worker" "^4.0.0" + +"@vibrant/generator-default@^4.0.3": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@vibrant/generator-default/-/generator-default-4.0.3.tgz#2634a4c0b17698515666bed993100d6b85e9eef9" + integrity sha512-HZlfp19sDokODEkZF4p70QceARHgjP3a1Dmxg+dlblYMJM98jPq+azA0fzqKNR7R17JJNHxexpJEepEsNlG0gw== + dependencies: + "@vibrant/color" "^4.0.0" + "@vibrant/generator" "^4.0.0" + +"@vibrant/generator@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@vibrant/generator/-/generator-4.0.0.tgz#2fad5054c76695750d32c88056ab0bd823733c3e" + integrity sha512-CqKAjmgHVDXJVo3Q5+9pUJOvksR7cN3bzx/6MbURYh7lA4rhsIewkUK155M6q0vfcUN3ETi/eTneCi0tLuM2Sg== + dependencies: + "@vibrant/color" "^4.0.0" + "@vibrant/types" "^4.0.0" + +"@vibrant/image-browser@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@vibrant/image-browser/-/image-browser-4.0.0.tgz#9f62901ebbbf147b7c00aae84b5965479731f1b7" + integrity sha512-mXckzvJWiP575Y/wNtP87W/TPgyJoGlPBjW4E9YmNS6n4Jb6RqyHQA0ZVulqDslOxjSsihDzY7gpAORRclaoLg== + dependencies: + "@vibrant/image" "^4.0.0" + +"@vibrant/image-node@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@vibrant/image-node/-/image-node-4.0.0.tgz#3d60221f97215eebd5a7d6c34d563b7992da1e94" + integrity sha512-m7yfnQtmo2y8z+tOjRFBx6q/qGnhl/ax2uCaj4TBkm4TtXfR4Dsn90wT6OWXmCFFzxIKHXKKEBShkxR+4RHseA== + dependencies: + "@jimp/custom" "^0.22.12" + "@jimp/plugin-resize" "^0.22.12" + "@jimp/types" "^0.22.12" + "@vibrant/image" "^4.0.0" + +"@vibrant/image@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@vibrant/image/-/image-4.0.0.tgz#2c16047a760d5969c59c5686981a972b0fb37c4d" + integrity sha512-Asv/7R/L701norosgvbjOVkodFiwcFihkXixA/gbAd6C+5GCts1Wm1NPk14FNKnM7eKkfAN+0wwPkdOH+PY/YA== + dependencies: + "@vibrant/color" "^4.0.0" + +"@vibrant/quantizer-mmcq@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@vibrant/quantizer-mmcq/-/quantizer-mmcq-4.0.0.tgz#b82469653d21827233dbc243b7cebc3d4b761cd9" + integrity sha512-TZqNiRoGGyCP8fH1XE6rvhFwLNv9D8MP1Xhz3K8tsuUweC6buWax3qLfrfEnkhtQnPJHaqvTfTOlIIXVMfRpow== + dependencies: + "@vibrant/color" "^4.0.0" + "@vibrant/image" "^4.0.0" + "@vibrant/quantizer" "^4.0.0" + +"@vibrant/quantizer@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@vibrant/quantizer/-/quantizer-4.0.0.tgz#48cb29feca2cea98c1129ce46f85995a8e206462" + integrity sha512-YDGxmCv/RvHFtZghDlVRwH5GMxdGGozWS1JpUOUt73/F5zAKGiiier8F31K1npIXARn6/Gspvg/Rbg7qqyEr2A== + dependencies: + "@vibrant/color" "^4.0.0" + "@vibrant/image" "^4.0.0" + "@vibrant/types" "^4.0.0" + +"@vibrant/types@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@vibrant/types/-/types-4.0.0.tgz#8c5a777d827d5df986644abe5c05d16b4114012f" + integrity sha512-tA5TAbuROXcPkt+PWjmGfoaiEXyySVaNnCZovf6vXhCbMdrTTCQXvNCde2geiVl6YwtuU/Qrj9iZxS5jZ6yVIw== + +"@vibrant/worker@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@vibrant/worker/-/worker-4.0.0.tgz#ca60568f5b607af5786be9ce625efc397087fbdb" + integrity sha512-nSaZZwWQKOgN/nPYUAIRF0/uoa7KpK91A+gjLmZZDgfN1enqxaiihmn+75ayNadW0c6cxAEpEFEHTONR5u9tMw== + dependencies: + "@vibrant/types" "^4.0.0" + abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz" @@ -275,6 +465,11 @@ acorn@^8.11.0, acorn@^8.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.0.tgz#1627bfa2e058148036133b8d9b51a700663c294c" integrity sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw== +any-base@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/any-base/-/any-base-1.1.0.tgz#ae101a62bc08a597b4c9ab5b7089d456630549fe" + integrity sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg== + arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -305,6 +500,11 @@ base64-js@^1.3.1: resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +bmp-js@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.1.0.tgz#e05a63f796a6c1ff25f4771ec7adadc148c07233" + integrity sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw== + body-parser@1.20.2: version "1.20.2" resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz" @@ -328,6 +528,14 @@ boolean@^3.1.4: resolved "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz" integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw== +buffer@^5.2.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + buffer@^6.0.3: version "6.0.3" resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz" @@ -544,6 +752,11 @@ events@^3.3.0: resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== +exif-parser@^0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/exif-parser/-/exif-parser-0.1.12.tgz#58a9d2d72c02c1f6f02a0ef4a9166272b7760922" + integrity sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw== + express@^4.19.2: version "4.19.2" resolved "https://registry.npmjs.org/express/-/express-4.19.2.tgz" @@ -608,6 +821,15 @@ fflate@^0.7.3: resolved "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz" integrity sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw== +file-type@^16.5.4: + version "16.5.4" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-16.5.4.tgz#474fb4f704bee427681f98dd390058a172a6c2fd" + integrity sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw== + dependencies: + readable-web-to-node-stream "^3.0.0" + strtok3 "^6.2.4" + token-types "^4.1.1" + finalhandler@1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz" @@ -656,6 +878,14 @@ get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: has-symbols "^1.0.3" hasown "^2.0.0" +gifwrap@^0.10.1: + version "0.10.1" + resolved "https://registry.yarnpkg.com/gifwrap/-/gifwrap-0.10.1.tgz#9ed46a5d51913b482d4221ce9c727080260b681e" + integrity sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw== + dependencies: + image-q "^4.0.0" + omggif "^1.0.10" + gopd@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz" @@ -735,11 +965,18 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -ieee754@^1.2.1: +ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== +image-q@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/image-q/-/image-q-4.0.0.tgz#31e075be7bae3c1f42a85c469b4732c358981776" + integrity sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw== + dependencies: + "@types/node" "16.9.1" + inherits@2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" @@ -755,11 +992,24 @@ iso-datestring-validator@^2.2.2: resolved "https://registry.npmjs.org/iso-datestring-validator/-/iso-datestring-validator-2.2.2.tgz" integrity sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA== +isomorphic-fetch@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz#0267b005049046d2421207215d45d6a262b8b8b4" + integrity sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA== + dependencies: + node-fetch "^2.6.1" + whatwg-fetch "^3.4.1" + joycon@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== +jpeg-js@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.4.tgz#a9f1c6f1f9f0fa80cdb3484ed9635054d28936aa" + integrity sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg== + "js-tokens@^3.0.0 || ^4.0.0": version "4.0.0" resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" @@ -858,6 +1108,13 @@ negotiator@0.6.3: resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== +node-fetch@^2.6.1: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-gyp-build-optional-packages@5.1.1: version "5.1.1" resolved "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz" @@ -865,11 +1122,28 @@ node-gyp-build-optional-packages@5.1.1: dependencies: detect-libc "^2.0.1" +node-vibrant@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/node-vibrant/-/node-vibrant-4.0.3.tgz#0737480f2eaceee6336915388541d04f6af308c7" + integrity sha512-kzoIuJK90BH/k65Avt077JCX4Nhqz1LNc8cIOm2rnYEvFdJIYd8b3SQwU1MTpzcHtr8z8jxkl1qdaCfbP3olFg== + dependencies: + "@types/node" "^18.15.3" + "@vibrant/core" "^4.0.0" + "@vibrant/generator-default" "^4.0.3" + "@vibrant/image-browser" "^4.0.0" + "@vibrant/image-node" "^4.0.0" + "@vibrant/quantizer-mmcq" "^4.0.0" + object-inspect@^1.13.1: version "1.13.1" resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz" integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== +omggif@^1.0.10, omggif@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/omggif/-/omggif-1.0.10.tgz#ddaaf90d4a42f532e9e7cb3a95ecdd47f17c7b19" + integrity sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw== + on-exit-leak-free@^2.1.0: version "2.1.2" resolved "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz" @@ -913,6 +1187,11 @@ pako@^0.2.5: resolved "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz" integrity sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA== +pako@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + parse-css-color@^0.2.1: version "0.2.1" resolved "https://registry.npmjs.org/parse-css-color/-/parse-css-color-0.2.1.tgz" @@ -931,6 +1210,11 @@ path-to-regexp@0.1.7: resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== +peek-readable@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-4.1.0.tgz#4ece1111bf5c2ad8867c314c81356847e8a62e72" + integrity sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg== + pino-abstract-transport@^1.0.0, pino-abstract-transport@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz" @@ -1003,6 +1287,23 @@ pino@^9.2.0: sonic-boom "^4.0.1" thread-stream "^3.0.0" +pixelmatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-4.0.2.tgz#8f47dcec5011b477b67db03c243bc1f3085e8854" + integrity sha512-J8B6xqiO37sU/gkcMglv6h5Jbd9xNER7aHzpfRdNmV4IbQBzBpe4l9XmbG+xPF/znacgu2jfEw+wHffaq/YkXA== + dependencies: + pngjs "^3.0.0" + +pngjs@^3.0.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" + integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== + +pngjs@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-6.0.0.tgz#ca9e5d2aa48db0228a52c419c3308e87720da821" + integrity sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg== + postcss-value-parser@^4.0.2, postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" @@ -1079,11 +1380,34 @@ readable-stream@^4.0.0: process "^0.11.10" string_decoder "^1.3.0" +readable-stream@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.7.0.tgz#cedbd8a1146c13dfff8dab14068028d58c15ac91" + integrity sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg== + dependencies: + abort-controller "^3.0.0" + buffer "^6.0.3" + events "^3.3.0" + process "^0.11.10" + string_decoder "^1.3.0" + +readable-web-to-node-stream@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz#392ba37707af5bf62d725c36c1b5d6ef4119eefc" + integrity sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw== + dependencies: + readable-stream "^4.7.0" + real-require@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz" integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== +regenerator-runtime@^0.13.3: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + roarr@^7.0.4: version "7.21.1" resolved "https://registry.npmjs.org/roarr/-/roarr-7.21.1.tgz" @@ -1231,6 +1555,14 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strtok3@^6.2.4: + version "6.3.0" + resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-6.3.0.tgz#358b80ffe6d5d5620e19a073aa78ce947a90f9a0" + integrity sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw== + dependencies: + "@tokenizer/token" "^0.3.0" + peek-readable "^4.1.0" + thread-stream@^2.6.0: version "2.7.0" resolved "https://registry.npmjs.org/thread-stream/-/thread-stream-2.7.0.tgz" @@ -1245,11 +1577,21 @@ thread-stream@^3.0.0: dependencies: real-require "^0.2.0" +timm@^1.6.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/timm/-/timm-1.7.1.tgz#96bab60c7d45b5a10a8a4d0f0117c6b7e5aff76f" + integrity sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw== + tiny-inflate@^1.0.0: version "1.0.3" resolved "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz" integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw== +tinycolor2@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e" + integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw== + tlds@^1.234.0: version "1.252.0" resolved "https://registry.npmjs.org/tlds/-/tlds-1.252.0.tgz" @@ -1260,6 +1602,19 @@ toidentifier@1.0.1: resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +token-types@^4.1.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/token-types/-/token-types-4.2.1.tgz#0f897f03665846982806e138977dbe72d44df753" + integrity sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ== + dependencies: + "@tokenizer/token" "^0.3.0" + ieee754 "^1.2.1" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + ts-node@^10.9.2: version "10.9.2" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" @@ -1342,6 +1697,13 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +utif2@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/utif2/-/utif2-4.1.0.tgz#e768d37bd619b995d56d9780b5d2b4611a3d932b" + integrity sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w== + dependencies: + pako "^1.0.11" + utils-merge@1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" @@ -1357,11 +1719,29 @@ vary@~1.1.2: resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-fetch@^3.4.1: + version "3.6.20" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70" + integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg== + whatwg-mimetype@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz#bc1bf94a985dc50388d54a9258ac405c3ca2fc0a" integrity sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"