diff --git a/app/api/package.json b/app/api/package.json index b56a4c1..354a796 100644 --- a/app/api/package.json +++ b/app/api/package.json @@ -5,11 +5,15 @@ "dependencies": { "@redwoodjs/api": "^0.34.1", "@sentry/node": "^6.5.1", + "chrome-aws-lambda": "^10.1.0", "cloudinary": "^1.23.0", "human-id": "^2.0.1", - "nodemailer": "^6.6.2" + "nodemailer": "^6.6.2", + "puppeteer-core": "^10.1.0" }, "devDependencies": { + "@netlify/functions": "^0.7.2", + "puppeteer": "^10.1.0", "@types/nodemailer": "^6.4.2" } } diff --git a/app/api/src/services/og-image-generator.ts b/app/api/src/services/og-image-generator.ts new file mode 100644 index 0000000..93adbdd --- /dev/null +++ b/app/api/src/services/og-image-generator.ts @@ -0,0 +1,71 @@ +// TODO this should be in the functions folder. +// Got the proof of concept working locally, but even though chrome-aws-lambda is supposed to fit into a AWS lambda it did not for me +// in the mean time this is causing builds to fail so moved it out here. +import { builder } from '@netlify/functions' +const { headless, executablePath, puppeteer } = require('chrome-aws-lambda') + +const captureWidth = 1200 +const captureHeight = 630 +const clipY = 0 + +async function unwrappedHandler(event, context) { + const path = event.path + .replace(/.+\/og-image-generator/, '') + .replace(/\/og-image-.+\.jpg/, '') + + const url = `${process.env.URL}/u${path}/social-card` + + const browser = await puppeteer.launch({ + executablePath: process.env.URL?.includes('localhost') + ? null + : await executablePath, + args: [ + '--no-sandbox', + '--disable-web-security', + '--disable-gpu', + '--hide-scrollbars', + '--disable-setuid-sandbox', + ], + // args: chromium.args, + defaultViewport: { + width: captureWidth, + height: captureHeight + clipY, + }, + headless: headless, + }) + const page = await browser.newPage() + + await page.goto(url, { waitUntil: 'networkidle0' }) + + const screenshot = await page.screenshot({ + type: 'jpeg', + // netlify functions can only return strings, so base64 it is + encoding: 'base64', + quality: 70, + clip: { + x: 0, + y: clipY, + width: captureWidth, + height: captureHeight, + }, + }) + + await browser.close() + + if (typeof screenshot !== 'string') { + return { + statusCode: 400, + } + } + + return { + statusCode: 200, + headers: { + 'Content-Type': 'image/jpg', + }, + body: screenshot, + isBase64Encoded: true, + } +} + +export const handler = builder(unwrappedHandler) diff --git a/app/web/src/Routes.js b/app/web/src/Routes.js index 665ad9d..4279d72 100644 --- a/app/web/src/Routes.js +++ b/app/web/src/Routes.js @@ -55,6 +55,7 @@ const Routes = () => { + diff --git a/app/web/src/components/Gravatar/Gravatar.tsx b/app/web/src/components/Gravatar/Gravatar.tsx index 58ea606..08603f5 100644 --- a/app/web/src/components/Gravatar/Gravatar.tsx +++ b/app/web/src/components/Gravatar/Gravatar.tsx @@ -4,9 +4,10 @@ import { Image as CloudinaryImage } from 'cloudinary-react' interface Props { image: string className?: string + size?: number } -const Gravatar = ({ image, className = '' }: Props) => { +const Gravatar = ({ image, size = 40, className = '' }: Props) => { return ( { diff --git a/app/web/src/components/IdeWrapper/useSaveCode.ts b/app/web/src/components/IdeWrapper/useSaveCode.ts index 8a26161..69dcd71 100644 --- a/app/web/src/components/IdeWrapper/useSaveCode.ts +++ b/app/web/src/components/IdeWrapper/useSaveCode.ts @@ -19,7 +19,7 @@ export const useSaveCode = () => { setNowError(!!error) } if (!currentUser || project?.user?.id !== currentUser?.sub) { - return () => console.log('not your project') + return () => {} } return (input: Prisma.ProjectUpdateInput) => { updateProject({ variables: { id: project.id, input } }) diff --git a/app/web/src/components/Seo/Seo.js b/app/web/src/components/Seo/Seo.tsx similarity index 70% rename from app/web/src/components/Seo/Seo.js rename to app/web/src/components/Seo/Seo.tsx index 69d97f0..7c8adc5 100644 --- a/app/web/src/components/Seo/Seo.js +++ b/app/web/src/components/Seo/Seo.tsx @@ -1,6 +1,16 @@ import { Helmet } from 'react-helmet' -const Seo = ({ title, description, lang }) => { +const Seo = ({ + title, + description, + lang, + socialImageUrl, +}: { + title: string + description: string + lang: string + socialImageUrl?: string +}) => { return ( <> { + Cadhub - {title} > diff --git a/app/web/src/components/SocialCardCell/SocialCardCell.tsx b/app/web/src/components/SocialCardCell/SocialCardCell.tsx new file mode 100644 index 0000000..ded726f --- /dev/null +++ b/app/web/src/components/SocialCardCell/SocialCardCell.tsx @@ -0,0 +1,147 @@ +import type { FindSocialCardQuery } from 'types/graphql' +import type { CellSuccessProps, CellFailureProps } from '@redwoodjs/web' +import Svg from 'src/components/Svg/Svg' +import { Image as CloudinaryImage } from 'cloudinary-react' +import Gravatar from 'src/components/Gravatar/Gravatar' +import CadPackage from 'src/components/CadPackage/CadPackage' + +export const QUERY = gql` + query FindSocialCardQuery($userName: String!, $projectTitle: String) { + userProject: userName(userName: $userName) { + userName + image + Project(projectTitle: $projectTitle) { + id + title + description + mainImage + createdAt + updatedAt + userId + cadPackage + Reaction { + emote + } + } + } + } +` + +export const Loading = () => Loading... + +export const Empty = () => Empty + +export const Failure = ({ error }: CellFailureProps) => ( + Error: {error.message} +) + +export const Success = ({ + userProject, +}: CellSuccessProps) => { + const image = userProject?.Project?.mainImage + const gravatar = userProject?.image + return ( + + + + + {/* */} + + + + + + {gravatar && ( + + )} + + {userProject?.userName} + + + + + + + {userProject?.Project?.title.replace(/-/g, ' ')} + + + + {(userProject?.Project?.description || '').slice(0, 150)} + + + + + + + + + + + + {[ + { + svg: 'reactions', + title: 'Reactions', + count: userProject?.Project?.Reaction?.length, + }, + { + svg: 'fork-new', + title: 'Forks', + count: 0, + }, + ].map(({ svg, title, count }, index) => ( + + + + {count} + {title} + + + ))} + + + + + {/* Because of how specific these styles are to this heading/logo and it doesn't need to be replicated else where as well as it's very precise with the placement of "pre-alpha" I think it's appropriate. */} + + CadHub + + + pre-alpha + + + + + + + ) +} diff --git a/app/web/src/components/Svg/Svg.tsx b/app/web/src/components/Svg/Svg.tsx index 2313dff..f21612d 100644 --- a/app/web/src/components/Svg/Svg.tsx +++ b/app/web/src/components/Svg/Svg.tsx @@ -13,6 +13,7 @@ type SvgNames = | 'flag' | 'floppy-disk' | 'fork' + | 'fork-new' | 'gear' | 'lightbulb' | 'logout' @@ -22,6 +23,7 @@ type SvgNames = | 'photograph' | 'plus' | 'plus-circle' + | 'reactions' | 'refresh' | 'save' | 'share' @@ -294,6 +296,39 @@ const Svg = ({ /> ), + 'fork-new': ( + + + + + + + ), gear: ( ), + reactions: ( + + + + + ), refresh: ( ( 404 Page Not Found + {location.href} 🤷 diff --git a/app/web/src/pages/ProjectPage/ProjectPage.tsx b/app/web/src/pages/ProjectPage/ProjectPage.tsx index 7e401ca..187db51 100644 --- a/app/web/src/pages/ProjectPage/ProjectPage.tsx +++ b/app/web/src/pages/ProjectPage/ProjectPage.tsx @@ -9,9 +9,20 @@ import { Toaster } from '@redwoodjs/web/toast' const ProjectPage = ({ userName, projectTitle }) => { const { currentUser } = useAuth() const [state, thunkDispatch] = useIdeState() + const cacheInvalidator = new Date() + .toISOString() + .split('-') + .slice(0, 2) + .join('-') + const socialImageUrl = `/.netlify/functions/og-image-generator/${userName}/${projectTitle}/og-image-${cacheInvalidator}.jpg` return ( <> - + { + return +} + +export default SocialCardPage diff --git a/app/web/tailwind.config.js b/app/web/tailwind.config.js index e492a68..e1dca04 100644 --- a/app/web/tailwind.config.js +++ b/app/web/tailwind.config.js @@ -22,6 +22,7 @@ module.exports = { 700: '#2A3038', 600: '#3B3E4B', 500: '#9F9FB4', + 400: '#A4A4B0', 300: '#CFCFD8', }, 'ch-purple': { @@ -31,6 +32,7 @@ module.exports = { }, 'ch-blue': { 600: '#79B2F8', + 500: '5098F1', 300: '#08466F' }, 'ch-pink': { diff --git a/app/yarn.lock b/app/yarn.lock index 4226568..92f6075 100644 --- a/app/yarn.lock +++ b/app/yarn.lock @@ -2214,6 +2214,13 @@ strict-event-emitter "^0.2.0" xmldom "^0.6.0" +"@netlify/functions@^0.7.2": + version "0.7.2" + resolved "https://registry.yarnpkg.com/@netlify/functions/-/functions-0.7.2.tgz#9d39553b94e7aaa86dddf515bdbaed3e89998122" + integrity sha512-xf45ZqQukMxmlkqNMC5BXdFMaVZ8VqF42MV5zA5nKVOh2V0mhYlcbTYlVbS/K2/rtvQ3W8lxxixYl4NT7kq6Bg== + dependencies: + is-promise "^4.0.0" + "@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents": version "2.1.8-no-fsevents" resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.tgz#da7c3996b8e6e19ebd14d82eaced2313e7769f9b" @@ -4282,6 +4289,13 @@ dependencies: "@types/yargs-parser" "*" +"@types/yauzl@^2.9.1": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.2.tgz#c48e5d56aff1444409e39fa164b0b4d4552a7b7a" + integrity sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA== + dependencies: + "@types/node" "*" + "@types/zen-observable@^0.8.0": version "0.8.2" resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.2.tgz#808c9fa7e4517274ed555fa158f2de4b4f468e71" @@ -6047,7 +6061,7 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" -buffer-crc32@^0.2.1, buffer-crc32@^0.2.13: +buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= @@ -6081,7 +6095,7 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.1.0, buffer@^5.5.0, buffer@^5.7.0: +buffer@^5.1.0, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -6469,6 +6483,13 @@ chownr@^2.0.0: resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== +chrome-aws-lambda@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/chrome-aws-lambda/-/chrome-aws-lambda-10.1.0.tgz#ac43b4cdfc1fbb2275c62effada560858099501e" + integrity sha512-NZQVf+J4kqG4sVhRm3WNmOfzY0OtTSm+S8rg77pwePa9RCYHzhnzRs8YvNI6L9tALIW6RpmefWiPURt3vURXcw== + dependencies: + lambdafs "^2.0.3" + chrome-trace-event@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" @@ -7557,7 +7578,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: dependencies: ms "2.0.0" -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.0, debug@^4.3.1: +debug@4, debug@4.3.1, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.0, debug@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== @@ -7830,6 +7851,11 @@ detective@^5.2.0: defined "^1.0.0" minimist "^1.1.1" +devtools-protocol@0.0.883894: + version "0.0.883894" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.883894.tgz#d403f2c75cd6d71c916aee8dde9258da988a4da9" + integrity sha512-33idhm54QJzf3Q7QofMgCvIVSd2o9H3kQPWaKT/fhoZh+digc+WSiMhbkeG3iN79WY4Hwr9G05NpbhEVrsOYAg== + dicer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872" @@ -8886,6 +8912,17 @@ extract-files@9.0.0, extract-files@^9.0.0: resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a" integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ== +extract-zip@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== + dependencies: + debug "^4.1.1" + get-stream "^5.1.0" + yauzl "^2.10.0" + optionalDependencies: + "@types/yauzl" "^2.9.1" + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -9003,6 +9040,13 @@ fbjs@^3.0.0: setimmediate "^1.0.5" ua-parser-js "^0.7.18" +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= + dependencies: + pend "~1.2.0" + figgy-pudding@^3.5.1: version "3.5.2" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" @@ -10252,7 +10296,7 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= -https-proxy-agent@^5.0.0: +https-proxy-agent@5.0.0, https-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== @@ -10948,7 +10992,7 @@ is-potential-custom-element-name@^1.0.1: resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== -is-promise@4.0.0: +is-promise@4.0.0, is-promise@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3" integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ== @@ -11925,6 +11969,13 @@ klona@^2.0.3: resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0" integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA== +lambdafs@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/lambdafs/-/lambdafs-2.0.3.tgz#f2acc53cf4862d29f1df654c327864b4faeb1d4a" + integrity sha512-5YWwZA/QKk09GdfcJ/ABVO+bpFoGlnTBa5jmyM8Kt9yIzl2lDDVBPLK+Aenq2UEcuDpqxXIYI5zLB7VZNepTrg== + dependencies: + tar-fs "^2.1.1" + language-subtag-registry@~0.3.2: version "0.3.21" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a" @@ -12781,6 +12832,11 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" +mkdirp-classic@^0.5.2: + version "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, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -13814,6 +13870,11 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: version "2.3.0" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" @@ -13889,6 +13950,13 @@ pirates@^4.0.0, pirates@^4.0.1: dependencies: node-modules-regexp "^1.0.0" +pkg-dir@4.2.0, pkg-dir@^4.1.0, pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + pkg-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" @@ -13903,13 +13971,6 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" -pkg-dir@^4.1.0, pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - pkg-up@2.0.0, pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" @@ -14442,6 +14503,11 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= +progress@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.1.tgz#c9242169342b1c29d275889c95734621b1952e31" + integrity sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg== + progress@^2.0.0, progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -14657,6 +14723,11 @@ proxy-addr@~2.0.5: forwarded "0.2.0" ipaddr.js "1.9.1" +proxy-from-env@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + proxyquire@2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/proxyquire/-/proxyquire-2.1.3.tgz#2049a7eefa10a9a953346a18e54aab2b4268df39" @@ -14733,6 +14804,42 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +puppeteer-core@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-10.1.0.tgz#ffd9fd780ad237b9ac23cc95cbb919be5e4523a5" + integrity sha512-x2yDSJI/PRiWhDqAt1jd4rhTotxwjwKzHLIIqD2MlJ+TmzGJfBY9snAGIVXJwkWfKJg+Ef5xupdK0EbHDqBpFw== + dependencies: + debug "4.3.1" + devtools-protocol "0.0.883894" + extract-zip "2.0.1" + https-proxy-agent "5.0.0" + node-fetch "2.6.1" + pkg-dir "4.2.0" + progress "2.0.1" + proxy-from-env "1.1.0" + rimraf "3.0.2" + tar-fs "2.0.0" + unbzip2-stream "1.3.3" + ws "7.4.6" + +puppeteer@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-10.1.0.tgz#6ee1d7e30401a967f4403bd42ace9e51e399504f" + integrity sha512-bsyDHbFBvbofZ63xqF7hMhuKBX1h4WsqFIAoh1GuHr/Y9cewh+EFNAOdqWSkQRHLiBU/MY6M+8PUnXXjAPtuSg== + dependencies: + debug "4.3.1" + devtools-protocol "0.0.883894" + extract-zip "2.0.1" + https-proxy-agent "5.0.0" + node-fetch "2.6.1" + pkg-dir "4.2.0" + progress "2.0.1" + proxy-from-env "1.1.0" + rimraf "3.0.2" + tar-fs "2.0.0" + unbzip2-stream "1.3.3" + ws "7.4.6" + purgecss@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-4.0.3.tgz#8147b429f9c09db719e05d64908ea8b672913742" @@ -16946,7 +17053,27 @@ tapable@^2.0.0, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.0.tgz#5c373d281d9c672848213d0e037d1c4165ab426b" integrity sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw== -tar-stream@^2.1.2: +tar-fs@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.0.tgz#677700fc0c8b337a78bee3623fdc235f21d7afad" + integrity sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA== + dependencies: + chownr "^1.1.1" + mkdirp "^0.5.1" + pump "^3.0.0" + tar-stream "^2.0.0" + +tar-fs@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-stream@^2.0.0, tar-stream@^2.1.2, tar-stream@^2.1.4: version "2.2.0" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== @@ -17133,7 +17260,7 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -through@^2.3.6: +through@^2.3.6, through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -17489,6 +17616,14 @@ unbox-primitive@^1.0.1: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" +unbzip2-stream@1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz#d156d205e670d8d8c393e1c02ebd506422873f6a" + integrity sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg== + dependencies: + buffer "^5.2.1" + through "^2.3.8" + unc-path-regex@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" @@ -18303,6 +18438,11 @@ ws@7.4.5: resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.5.tgz#a484dd851e9beb6fdb420027e3885e8ce48986c1" integrity sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g== +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + "ws@^5.2.0 || ^6.0.0 || ^7.0.0", ws@^7.4.5: version "7.5.0" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.0.tgz#0033bafea031fb9df041b2026fc72a571ca44691" @@ -18523,6 +18663,14 @@ yargs@^17.0.0, yargs@^17.0.1: y18n "^5.0.5" yargs-parser "^20.2.2" +yauzl@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" + yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
+ {(userProject?.Project?.description || '').slice(0, 150)} +
+ {userProject?.Project?.title.replace(/-/g, ' ')} +
+ ++ {(userProject?.Project?.description || '').slice(0, 150)} +
++ CadHub +
+