diff --git a/.gitignore b/.gitignore index a5ab03e..5b5c794 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ out public/browserconfig.xml public/icons/ +public/images/ public/manifest.json public/manifest.webmanifest public/sitemap.xml diff --git a/amplify.yml b/amplify.yml index 17a829a..9f16b61 100644 --- a/amplify.yml +++ b/amplify.yml @@ -16,3 +16,4 @@ frontend: cache: paths: - node_modules/**/* + - public/images/**/* diff --git a/next.config.js b/next.config.js index 12b94aa..fec9aef 100644 --- a/next.config.js +++ b/next.config.js @@ -1,13 +1,18 @@ -const imageOptimization = (process.env.IMAGE_OPTIMIZATION || '1') === '1'; - const next_config = { images: { domains: ['images.ctfassets.net'], - ...{ ...(imageOptimization ? {} : { loader: 'custom' }) }, + loader: 'custom', + imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], + deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840], }, env: { - imageOptimization, + nextImageExportOptimizer_imageFolderPath: 'public/images', + nextImageExportOptimizer_exportFolderPath: 'out', + nextImageExportOptimizer_quality: 50, + nextImageExportOptimizer_storePicturesInWEBP: true, + nextImageExportOptimizer_generateAndUseBlurImages: true, }, + productionBrowserSourceMaps: true, }; -module.exports = { ...next_config }; +module.exports = next_config; diff --git a/package.json b/package.json index e6d1b9c..c2c5f6b 100644 --- a/package.json +++ b/package.json @@ -3,14 +3,18 @@ "license": "MIT", "author": "Igor Starostenko ", "scripts": { + "analyze": "source-map-explorer .next/static/**/*.js", "dev": "next dev", "start": "next start", "format": "prettier --config ./.prettierrc --write src/**/*.js", "lint": "next lint", - "build:dir": "mkdirp ./public/icons/", + "build:analyze": "npm run build && npm run analyze", + "build:dir": "mkdirp ./public/icons/ && mkdirp ./public/images/", "build:favicons": "node scripts/favicons", + "build:images": "npm run contentful:assets && next-image-export-optimizer --exportFolderPath=out --nextConfigPath=next.config.js", "build:sitemap": "next-sitemap", - "build": "npm run build:dir && npm run build:favicons && next build && npm run build:sitemap && next export", + "build": "npm run build:dir && npm run build:favicons && next build && npm run build:sitemap && next export && npm run build:images", + "contentful:assets": "node scripts/contentful_assets.js", "contentful:backup": "node scripts/contentful_backup.js", "contentful:export": "contentful space export --space-id $CONTENTFUL_SPACE_ID", "test:lighthouse": "npx ava scripts/lighthouse.test.js" @@ -30,6 +34,7 @@ "dotenv": "^10.0.0", "framer-motion": "^5.2.1", "next": "^13.1.1", + "next-image-export-optimizer": "^1.1.2", "prop-types": "^15.6.2", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -56,6 +61,7 @@ "next-sitemap": "^3.1.43", "node-gyp": "^9.3.1", "prettier": "^2.4.1", + "source-map-explorer": "^2.5.3", "webpack": "^5.75.0" } } diff --git a/scripts/contentful_assets.js b/scripts/contentful_assets.js new file mode 100644 index 0000000..27f9c17 --- /dev/null +++ b/scripts/contentful_assets.js @@ -0,0 +1,53 @@ +const fs = require('fs'); +const fetch = require('node-fetch'); +const contentful = require('contentful'); +require('dotenv').config(); + +const imageDirectory = process.env.IMAGE_DIRECTORY || './public/images/'; +const replaceImages = parseInt(process.env.REPLACE_IMAGES || '0'); +const limit = parseInt(process.env.CONTENTFUL_LIMIT || '100'); + +const client = contentful.createClient({ + space: process.env.CONTENTFUL_SPACE_ID, + accessToken: process.env.CONTENTFUL_DELIVERY_TOKEN, +}); + +const saveFile = async (i, url, name) => { + const path = imageDirectory + name; + if (!replaceImages && fs.existsSync(path)) { + return console.log(`${i + 1}. ${path} already exists`); + } + + const response = await fetch(url); + const buffer = await response.buffer(); + fs.writeFile(path, buffer, () => + console.log(`${i + 1}. Saved ${url} into ${path}`) + ); +}; + +const getAllAssets = async (options) => { + let records = { items: [] }; + // Ensure we load all records, regardless of the API limit + while (records.total != 0 && records.items.length < (records.total || 1)) { + let response = await client.getAssets({ + ...options, // skip can't be overriden + skip: records.items.length, + }); + records = { ...response, items: [...records.items, ...response.items] }; + } + return records; +}; + +const saveAllAssets = async (items) => { + for (let i = 0; i < items.length; i += 1) { + const src = `https:${items[i].fields.file.url}`; + const fileName = `${items[i].sys.id}_${items[i].fields.file.fileName}`; + await saveFile(i, src, fileName); + } +}; + +(async () => { + const assets = await getAllAssets({ limit }); + console.log(`Total assets: ${assets.total}`); + await saveAllAssets(assets.items); +})(); diff --git a/src/components/article/index.js b/src/components/article/index.js index 7e0456e..6916a68 100644 --- a/src/components/article/index.js +++ b/src/components/article/index.js @@ -46,9 +46,11 @@ const Article = ({ }} > {title} @@ -75,15 +77,11 @@ Article.propTypes = { title: PropTypes.string.isRequired, description: PropTypes.string.isRequired, image: PropTypes.shape({ - file: PropTypes.shape({ - url: PropTypes.string.isRequired, - details: PropTypes.shape({ - image: PropTypes.shape({ - width: PropTypes.number.isRequired, - height: PropTypes.number.isRequired, - }).isRequired, - }).isRequired, - }).isRequired, + src: PropTypes.string.isRequired, + backupSrc: PropTypes.string, + alt: PropTypes.string.isRequired, + width: PropTypes.number.isRequired, + height: PropTypes.number.isRequired, }), date: PropTypes.string.isRequired, tags: PropTypes.arrayOf(PropTypes.string), diff --git a/src/components/filter/filter.css.js b/src/components/filter/filter.css.js index 230661e..ef1efba 100644 --- a/src/components/filter/filter.css.js +++ b/src/components/filter/filter.css.js @@ -24,7 +24,7 @@ export const Categories = styled.div` a { text-decoration: none; - color: ${colors.grey}; + color: ${colors.darkGrey}; &:hover { color: inherit; diff --git a/src/components/gallery/index.js b/src/components/gallery/index.js index 58937cc..12a203c 100644 --- a/src/components/gallery/index.js +++ b/src/components/gallery/index.js @@ -20,7 +20,8 @@ const GalleryImage = ({ index, onClick, photo, margin }) => ( onClick={(e) => onClick(e, { index, photo })} key={photo.id} src={photo.src} - alt={photo.title} + backupSrc={photo.backupSrc} + alt={photo.alt} width={photo.width} height={photo.height} /> @@ -34,6 +35,7 @@ GalleryImage.propTypes = { title: PropTypes.string.isRequired, width: PropTypes.number.isRequired, height: PropTypes.number.isRequired, + backupSrc: PropTypes.string, src: PropTypes.string.isRequired, }).isRequired, margin: PropTypes.number, diff --git a/src/components/image/image.css.js b/src/components/image/image.css.js index bc485dd..338f488 100644 --- a/src/components/image/image.css.js +++ b/src/components/image/image.css.js @@ -1,5 +1,5 @@ import styled from 'styled-components'; -import Image from 'next/image'; +import ExportedImage from 'next-image-export-optimizer'; export const ImageWrapper = styled.div` box-shadow: -1px 3px 6px 1px rgba(0, 0, 0, 0.3); @@ -19,7 +19,7 @@ export const ImageWrapper = styled.div` } `; -export const SImage = styled(Image)` +export const SImage = styled(ExportedImage)` max-width: 100%; height: auto; `; diff --git a/src/components/image/image.js b/src/components/image/image.js index 5d9c67b..1c6ee61 100644 --- a/src/components/image/image.js +++ b/src/components/image/image.js @@ -1,30 +1,27 @@ -import React from 'react'; +import React, { useState } from 'react'; import PropTypes from 'prop-types'; import { SImage } from './image.css'; -const noOptimization = ({ src }) => src; - /* For contentful query params see https://www.contentful.com/developers/docs/references/images-api/#/reference */ -const BaseImage = ({ alt, src, query = '?fm=webp', ...rest }) => ( - -); +const BaseImage = ({ alt, src, backupSrc, ...rest }) => { + const [isError, setIsError] = useState(false); + + if (isError) { + /* eslint-disable @next/next/no-img-element */ + return {alt}; + } + + return ( + setIsError(true)} {...rest} /> + ); +}; BaseImage.propTypes = { src: PropTypes.string.isRequired, alt: PropTypes.string.isRequired, - query: PropTypes.string, + backupSrc: PropTypes.string, }; export default BaseImage; diff --git a/src/components/recommendations/index.js b/src/components/recommendations/index.js index d7e6a67..a4c8b4e 100644 --- a/src/components/recommendations/index.js +++ b/src/components/recommendations/index.js @@ -16,7 +16,8 @@ const Recommendations = ({ category, posts }) => ( {post.thumbnail.description diff --git a/src/components/selfie/selfie.css.js b/src/components/selfie/selfie.css.js index e179806..4c43555 100644 --- a/src/components/selfie/selfie.css.js +++ b/src/components/selfie/selfie.css.js @@ -1,9 +1,8 @@ import styled from 'styled-components'; -import BaseImage from 'components/image/image'; import Box from 'components/box'; import MEDIA from 'helpers/mediaTemplates'; -export const Image = styled(BaseImage)` +export const Image = styled.img` cursor: initial; border-radius: 50%; border: 2px solid powderblue !important; diff --git a/src/contentClient.js b/src/contentClient.js index ca00d93..9265664 100644 --- a/src/contentClient.js +++ b/src/contentClient.js @@ -23,18 +23,26 @@ const parseFields = (item) => { }; }; -const parseImage = (file) => { +const parseImage = (id, title, file) => { const { width, height } = file.details.image; return { - src: `https:${file.url}`, + src: `/images/${id}_${file.fileName}`, + backupSrc: `https:${file.url}`, + alt: title, width, height, }; }; const parseItem = (data) => { - const { file, ...fields } = parseFields(data); - return { ...fields, ...parseImage(file) }; + const item = parseFields(data); + + if (!item) { + return null; + } + + const { id, title, file, ...fields } = item; + return { id, ...fields, ...parseImage(id, title, file) }; }; const getEntries = async (options) => { diff --git a/src/pages/[category].js b/src/pages/[category].js index 1be53c0..31647ac 100644 --- a/src/pages/[category].js +++ b/src/pages/[category].js @@ -3,7 +3,7 @@ import { getEntries, getAllEntries, getCategoriesPaths, - parseFields, + parseItem, } from 'contentClient'; import Category from 'components/category'; @@ -32,7 +32,7 @@ export const getStaticProps = async ({ params }) => { ...posts, /* eslint-disable no-unused-vars */ items: posts.items.map(({ thumbnail, images, ...fields }) => ({ - thumbnail: parseFields(thumbnail), + thumbnail: parseItem(thumbnail || {}), ...fields, })), }, diff --git a/src/pages/index.js b/src/pages/index.js index f332f4d..661eb15 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -1,5 +1,5 @@ import React from 'react'; -import { getEntries, getAllEntries, parseFields } from 'contentClient'; +import { getEntries, getAllEntries, parseItem } from 'contentClient'; import Category from 'components/category'; const Index = ({ page, posts }) => ; @@ -25,7 +25,7 @@ export const getStaticProps = async () => { ...posts, /* eslint-disable no-unused-vars */ items: posts.items.map(({ thumbnail, images, ...fields }) => ({ - thumbnail: parseFields(thumbnail), + thumbnail: parseItem(thumbnail || {}), ...fields, })), }, diff --git a/yarn.lock b/yarn.lock index 54c3541..10b2400 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1022,6 +1022,11 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +async@^3.2.3: + version "3.2.4" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" + integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1249,6 +1254,11 @@ browserslist@^4.14.5: node-releases "^2.0.6" update-browserslist-db "^1.0.5" +btoa@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" + integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== + buffer-equal-constant-time@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" @@ -1397,7 +1407,7 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: +chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1533,6 +1543,13 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" +cli-progress@^3.10.0: + version "3.11.2" + resolved "https://registry.yarnpkg.com/cli-progress/-/cli-progress-3.11.2.tgz#f8c89bd157e74f3f2c43bcfb3505670b4d48fc77" + integrity sha512-lCPoS6ncgX4+rJu5bS3F/iCz17kZ9MPZ6dpuTtI0KXKABkhyXIdYB3Inby1OpaGti3YlI3EeEkM9AuWpelJrVA== + dependencies: + string-width "^4.2.3" + cli-spinners@^2.5.0: version "2.7.0" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.7.0.tgz#f815fd30b5f9eaac02db604c7a231ed7cb2f797a" @@ -2307,6 +2324,11 @@ duplexer3@^0.1.4: resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== +duplexer@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== + ecdsa-sig-formatter@1.0.11: version "1.0.11" resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" @@ -2314,6 +2336,13 @@ ecdsa-sig-formatter@1.0.11: dependencies: safe-buffer "^5.0.1" +ejs@^3.1.5: + version "3.1.8" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.8.tgz#758d32910c78047585c7ef1f92f9ee041c1c190b" + integrity sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ== + dependencies: + jake "^10.8.5" + electron-to-chromium@^1.4.202: version "1.4.210" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.210.tgz#12611fe874b833a3bf3671438b5893aba7858980" @@ -2936,6 +2965,13 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" +filelist@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" + integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q== + dependencies: + minimatch "^5.0.1" + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -3188,7 +3224,7 @@ glob@7.1.7: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.3, glob@^7.1.4, glob@^7.2.0: +glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -3271,6 +3307,13 @@ graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6, resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== +gzip-size@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" + integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== + dependencies: + duplexer "^0.1.2" + has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -3944,7 +3987,7 @@ is-wsl@^1.1.0: resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== -is-wsl@^2.2.0: +is-wsl@^2.1.1, is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== @@ -3984,6 +4027,16 @@ iterate-object@^1.2.0: resolved "https://registry.yarnpkg.com/iterate-object/-/iterate-object-1.3.4.tgz#fa50b1d9e58e340a7dd6b4c98c8a5e182e790096" integrity sha512-4dG1D1x/7g8PwHS9aK6QV5V94+ZvyP4+d19qDv43EzImmrndysIl4prmJ1hWWIGCqrZHyaHBm6BSEWHOLnpoNw== +jake@^10.8.5: + version "10.8.5" + resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.5.tgz#f2183d2c59382cb274226034543b9c03b8164c46" + integrity sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw== + dependencies: + async "^3.2.3" + chalk "^4.0.2" + filelist "^1.0.1" + minimatch "^3.0.4" + jest-worker@^27.4.5: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" @@ -4725,6 +4778,13 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== +mkdirp@^0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" @@ -4789,6 +4849,15 @@ neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== +next-image-export-optimizer@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/next-image-export-optimizer/-/next-image-export-optimizer-1.1.2.tgz#8accb1ebcc5a570a15f934335d2e789243392c42" + integrity sha512-/9d2zE8I4l0JA3xvFBNrVxwkgFEA1n+ryY3DhugRMEKPzm28uFFxasFzMm3jgTwJSYE+U6fSaH6PA6soJlkZ7A== + dependencies: + cli-progress "^3.10.0" + sharp "^0.31.0" + typescript "^4.7.2" + next-sitemap@^3.1.43: version "3.1.43" resolved "https://registry.yarnpkg.com/next-sitemap/-/next-sitemap-3.1.43.tgz#f29ce7de7a7ea5cce95b36512cf06b8d30606abf" @@ -5012,6 +5081,14 @@ open@^6.4.0: dependencies: is-wsl "^1.1.0" +open@^7.3.1: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + open@^8.0.5: version "8.4.0" resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" @@ -5956,6 +6033,13 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +rimraf@~2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + robots-parser@^2.0.1: version "2.4.0" resolved "https://registry.yarnpkg.com/robots-parser/-/robots-parser-2.4.0.tgz#c0e45f66108ad5950adc86b6737349189b41f864" @@ -6093,7 +6177,7 @@ shallowequal@^1.1.0: resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== -sharp@^0.31.1: +sharp@^0.31.0, sharp@^0.31.1: version "0.31.3" resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.31.3.tgz#60227edc5c2be90e7378a210466c99aefcf32688" integrity sha512-XcR4+FCLBFKw1bdB+GEhnUNXNXvnt0tDo4WsBsraKymuo/IAuPuCBVAL2wIkUw2r/dwFW5Q5+g66Kwl2dgDFVg== @@ -6209,6 +6293,24 @@ socks@^2.6.2: ip "^2.0.0" smart-buffer "^4.2.0" +source-map-explorer@^2.5.3: + version "2.5.3" + resolved "https://registry.yarnpkg.com/source-map-explorer/-/source-map-explorer-2.5.3.tgz#33551b51e33b70f56d15e79083cdd4c43e583b69" + integrity sha512-qfUGs7UHsOBE5p/lGfQdaAj/5U/GWYBw2imEpD6UQNkqElYonkow8t+HBL1qqIl3CuGZx7n8/CQo4x1HwSHhsg== + dependencies: + btoa "^1.2.1" + chalk "^4.1.0" + convert-source-map "^1.7.0" + ejs "^3.1.5" + escape-html "^1.0.3" + glob "^7.1.6" + gzip-size "^6.0.0" + lodash "^4.17.20" + open "^7.3.1" + source-map "^0.7.4" + temp "^0.9.4" + yargs "^16.2.0" + 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" @@ -6227,6 +6329,11 @@ source-map@^0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +source-map@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + space-separated-tokens@^1.0.0: version "1.1.5" resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" @@ -6596,6 +6703,14 @@ temp-dir@^2.0.0: resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== +temp@^0.9.4: + version "0.9.4" + resolved "https://registry.yarnpkg.com/temp/-/temp-0.9.4.tgz#cd20a8580cb63635d0e4e9d4bd989d44286e7620" + integrity sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA== + dependencies: + mkdirp "^0.5.1" + rimraf "~2.6.2" + term-size@^2.1.0: version "2.2.1" resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" @@ -6808,6 +6923,11 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== +typescript@^4.7.2: + version "4.9.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78" + integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg== + ua-parser-js@^0.7.30: version "0.7.31" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6"