From 04fe54e00b6aca5daef524bab1202ef1658f30c5 Mon Sep 17 00:00:00 2001 From: Travis Fischer Date: Sun, 17 Jan 2021 18:54:52 -0500 Subject: [PATCH] feat: social features --- .env.example | 4 - .gitignore | 1 + components/NotionPage.tsx | 34 +++- components/temp | 34 ---- lib/config.ts | 42 ++++- lib/env.ts | 31 +--- lib/get-page-description.ts | 20 +++ lib/get-preview-images.ts | 2 +- lib/get-site-for-domain.ts | 7 +- lib/get-sites.ts | 4 +- package.json | 4 + pages/[pageId].tsx | 6 +- pages/_document.tsx | 4 +- pages/api/render-social-image/[pageId].ts | 115 ++++++++++++ pages/index.tsx | 6 +- vercel.json | 2 - yarn.lock | 208 +++++++++++++++++++++- 17 files changed, 423 insertions(+), 101 deletions(-) delete mode 100644 components/temp create mode 100644 lib/get-page-description.ts create mode 100644 pages/api/render-social-image/[pageId].ts diff --git a/.env.example b/.env.example index 53d3181..c1752c9 100644 --- a/.env.example +++ b/.env.example @@ -13,9 +13,5 @@ GCLOUD_PROJECT= FIREBASE_COLLECTION_IMAGES= -DOMAIN= - -NOTION_ROOT_PAGE_ID= - # Optional #FATHOM_ID= \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1437c53..74b7586 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ yarn-debug.log* yarn-error.log* # local env files +.env .env.local .env.development.local .env.test.local diff --git a/components/NotionPage.tsx b/components/NotionPage.tsx index 336430a..bb6dff6 100644 --- a/components/NotionPage.tsx +++ b/components/NotionPage.tsx @@ -14,8 +14,16 @@ import { NotionRenderer } from 'react-notion-x' import { getBlockTitle } from 'notion-utils' import * as types from 'lib/types' import { mapPageUrl, getCanonicalPageUrl } from 'lib/map-page-url' -import { mapNotionImageUrl } from 'lib/map-image-url' -import { isDev } from 'lib/config' +import { mapImageUrl, mapNotionImageUrl } from 'lib/map-image-url' +import { getPageDescription } from 'lib/get-page-description' +import { + isDev, + api, + siteDescription, + defaultPageCover, + defaultPageCoverPosition, + defaultPageIcon +} from 'lib/config' import { searchNotion } from 'lib/search-notion' // components @@ -89,10 +97,15 @@ export const NotionPage: React.FC = ({ const canonicalPageUrl = !isDev && getCanonicalPageUrl(site, recordMap)(pageId) + const isBlogPost = + block.type === 'page' && block.parent_table === 'collection' + const socialImage = mapImageUrl(api.renderSocialImage(pageId)) + const socialDescription = + getPageDescription(block, recordMap) ?? siteDescription let comments: React.ReactNode = null // only display comments on blog post pages - if (block.type === 'page' && block.parent_table === 'collection') { + if (isBlogPost) { comments = ( = ({ + {socialDescription && ( + <> + + + + )} + + {socialImage && } + {canonicalPageUrl && } {title} @@ -158,9 +180,9 @@ export const NotionPage: React.FC = ({ darkMode={isDarkMode} previewImages={site.previewImages !== false} showCollectionViewDropdown={false} - defaultPageIcon='https://ssfy.io/https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fs3-us-west-2.amazonaws.com%252Fsecure.notion-static.com%252F797768e4-f24a-4e65-bd4a-b622ae9671dc%252Fprofile-2020-280w-circle.png%3Ftable%3Dblock%26id%3D78fc5a4b-88d7-4b0e-824e-29407e9f1ec1%26cache%3Dv2' - defaultPageCover='https://ssfy.io/https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fs3-us-west-2.amazonaws.com%252Fsecure.notion-static.com%252F9fc5ecae-2b4b-4e73-b0d4-918c829ba69f%252FIMG_0259-opt.jpg%3Ftable%3Dblock%26id%3D78fc5a4b-88d7-4b0e-824e-29407e9f1ec1%26cache%3Dv2' - defaultPageCoverPosition={0.1862} + defaultPageIcon={defaultPageIcon} + defaultPageCover={defaultPageCover} + defaultPageCoverPosition={defaultPageCoverPosition} mapPageUrl={siteMapPageUrl} mapImageUrl={mapNotionImageUrl} searchNotion={searchNotion} diff --git a/components/temp b/components/temp deleted file mode 100644 index 0e7ab7f..0000000 --- a/components/temp +++ /dev/null @@ -1,34 +0,0 @@ -pageLink: ({ href = '', ...rest }) => { - const parts = href - .split('?')[0] - .split('/') - .filter((p: string) => !!p.trim()) - let pagesPath = - parts.length <= 1 ? '/[domain]' : '/[domain]/[pageId]' - let as = href - - if (isDemo) { - pagesPath = '/[domain]' - } else if (isDev) { - // localhost - } else { - // prod, non-demo - as = `/${site.domain}${href}` - } - - console.log({ href, parts, domain: site.domain, as }) - // const MyButton = React.forwardRef( - // ({ href: href2, ...rest }, ref) => { - // return ( - // - // Click Me - // - // ) - // } - // ) - return ( - - - - ) -} diff --git a/lib/config.ts b/lib/config.ts index b022422..54dc86b 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -1,14 +1,45 @@ /** - * All app config that should be available client-side. + * Site-wide app configuration. * - * @see env.ts for server-side version. + * @see env.ts for config relating to third-party dependencies. */ import { getEnv } from './get-env' +// this is the most important config value which specifies the site's root Notion page +export const rootNotionPageId = '78fc5a4b88d74b0e824e29407e9f1ec1' + +// general site config +export const siteName = 'Transitive Bullshit' +export const siteFavicon = '/favicon.png' +export const siteAuthor = 'Travis Fischer' +export const siteDomain = 'transitivebullsh.it' +export const siteDescription = + 'Personal site of Travis Fischer aka Transitive Bullshit' + +// default notion values for site-wide consistency (may be overridden on a per-page basis) +export const defaultPageIcon = + 'https://ssfy.io/https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fs3-us-west-2.amazonaws.com%252Fsecure.notion-static.com%252F797768e4-f24a-4e65-bd4a-b622ae9671dc%252Fprofile-2020-280w-circle.png%3Ftable%3Dblock%26id%3D78fc5a4b-88d7-4b0e-824e-29407e9f1ec1%26cache%3Dv2' +export const defaultPageCover = + 'https://ssfy.io/https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fs3-us-west-2.amazonaws.com%252Fsecure.notion-static.com%252F9fc5ecae-2b4b-4e73-b0d4-918c829ba69f%252FIMG_0259-opt.jpg%3Ftable%3Dblock%26id%3D78fc5a4b-88d7-4b0e-824e-29407e9f1ec1%26cache%3Dv2' +export const defaultPageCoverPosition = 0.1862 + +// ---------------------------------------------------------------------------- + export const isDev = process.env.NODE_ENV === 'development' || !process.env.NODE_ENV +export const port = getEnv('PORT', '3000') +export const host = isDev ? `http://localhost:${port}` : `https://${siteDomain}` + +export const apiBaseUrl = `${host}/api` + +export const api = { + createPreviewImage: `${apiBaseUrl}/create-preview-image`, + searchNotion: `${apiBaseUrl}/search-notion`, + renderSocialImage: (pageId) => `${apiBaseUrl}/render-social-image/${pageId}` +} + export const fathomId = isDev ? null : getEnv('FATHOM_ID', null) export const fathomConfig = fathomId @@ -16,10 +47,3 @@ export const fathomConfig = fathomId excludedDomains: ['localhost', 'localhost:3000'] } : undefined - -// TODO: fix duplication between server-side env and client-side config -export const apiBaseUrl = `/api` -export const api = { - createPreviewImage: `${apiBaseUrl}/create-preview-image`, - searchNotion: `${apiBaseUrl}/search-notion` -} diff --git a/lib/env.ts b/lib/env.ts index 38a42ab..f025f0b 100644 --- a/lib/env.ts +++ b/lib/env.ts @@ -1,23 +1,13 @@ /** - * All app config that needs to be available server-side. + * Config for third-party dependencies. * - * @see config.ts for client-side version. + * - Google Cloud (Firebase) - used very simple database functionality. + * - Fathom - simple analytics. + * + * @see config.ts for primary configuration. */ import { getEnv } from './get-env' -import { isDev } from './config' - -export * from './config' - -export const port = getEnv('PORT', '3000') -export const domain = getEnv('DOMAIN') -export const host = isDev ? `http://localhost:${port}` : `https://${domain}` - -export const apiBaseUrl = `${host}/api` -export const api = { - createPreviewImage: `${apiBaseUrl}/create-preview-image`, - searchNotion: `${apiBaseUrl}/search-notion` -} export const googleProjectId = getEnv('GCLOUD_PROJECT') @@ -40,14 +30,3 @@ try { } export const firebaseCollectionImages = getEnv('FIREBASE_COLLECTION_IMAGES') - -export const notionRootPageId = getEnv('NOTION_ROOT_PAGE_ID') - -export const siteName = getEnv('SITE_NAME', 'Transitive Bullshit') -export const siteDesc = getEnv( - 'SITE_DESC', - 'Personal site of Travis Fischer aka Transitive Bullshit.' -) -export const siteImage = getEnv('SITE_IMAGE', '/social.jpg') -export const siteFavicon = getEnv('SITE_FAVICON', '/favicon.png') -export const siteAuthor = getEnv('SITE_AUTHOR', 'Travis Fischer') diff --git a/lib/get-page-description.ts b/lib/get-page-description.ts new file mode 100644 index 0000000..1af7ca5 --- /dev/null +++ b/lib/get-page-description.ts @@ -0,0 +1,20 @@ +import * as types from 'lib/types' + +export function getPageDescription( + block: types.Block, + recordMap: types.RecordMap +): string | null { + const collection = recordMap.collection[block.parent_id]?.value + + if (collection) { + const descriptionKey = Object.keys(collection.schema).find( + (key) => collection.schema[key].name === 'Description' + ) + + if (descriptionKey) { + return block.properties[descriptionKey] + } + } + + return null +} diff --git a/lib/get-preview-images.ts b/lib/get-preview-images.ts index 0a81346..4c2b4c8 100644 --- a/lib/get-preview-images.ts +++ b/lib/get-preview-images.ts @@ -1,7 +1,7 @@ import crypto from 'crypto' import got from 'got' -import { api } from './env' +import { api } from './config' import * as types from './types' import * as db from './db' diff --git a/lib/get-site-for-domain.ts b/lib/get-site-for-domain.ts index 79f9d7c..c85dd93 100644 --- a/lib/get-site-for-domain.ts +++ b/lib/get-site-for-domain.ts @@ -1,4 +1,4 @@ -import * as config from './env' +import * as config from './config' import * as types from './types' export const getSiteForDomain = async ( @@ -7,8 +7,7 @@ export const getSiteForDomain = async ( return { domain, name: config.siteName, - rootNotionPageId: config.notionRootPageId, - description: config.siteDesc, - image: config.siteImage + rootNotionPageId: config.rootNotionPageId, + description: config.siteDescription } as types.Site } diff --git a/lib/get-sites.ts b/lib/get-sites.ts index 31bf3e0..ecde722 100644 --- a/lib/get-sites.ts +++ b/lib/get-sites.ts @@ -1,7 +1,7 @@ import { getSiteForDomain } from './get-site-for-domain' -import * as config from './env' +import * as config from './config' import * as types from './types' export async function getSites(): Promise { - return [await getSiteForDomain(config.domain)] + return [await getSiteForDomain(config.siteDomain)] } diff --git a/package.json b/package.json index 1ef5df7..08a4d68 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ }, "dependencies": { "@google-cloud/firestore": "^4.8.1", + "chrome-aws-lambda": "^5.5.0", "classnames": "^2.2.6", "dangerously-set-html-content": "^1.0.8", "fathom-client": "^3.0.0", @@ -38,6 +39,8 @@ "notion-utils": "^3.1.1", "p-map": "^4.0.0", "p-memoize": "^4.0.0", + "puppeteer-core": "^5.5.0", + "puppeteer-social-image-transitive-bs": "^0.8.1", "react": "17.0.1", "react-body-classname": "^1.3.1", "react-dom": "17.0.1", @@ -63,6 +66,7 @@ "eslint-plugin-react": "^7.18.0", "npm-run-all": "^4.1.5", "prettier": "^2.0.5", + "puppeteer": "^5.5.0", "typescript": "^4.0.2" } } diff --git a/pages/[pageId].tsx b/pages/[pageId].tsx index 1a95d93..57a48d6 100644 --- a/pages/[pageId].tsx +++ b/pages/[pageId].tsx @@ -1,5 +1,5 @@ import React from 'react' -import { isDev, domain } from 'lib/env' +import { isDev, siteDomain } from 'lib/config' import { getSiteMaps } from 'lib/get-site-maps' import { resolveNotionPage } from 'lib/resolve-notion-page' import { NotionPage } from 'components' @@ -8,11 +8,11 @@ export const getStaticProps = async (context) => { const rawPageId = context.params.pageId as string try { - const props = await resolveNotionPage(domain, rawPageId) + const props = await resolveNotionPage(siteDomain, rawPageId) return { props, revalidate: 10 } } catch (err) { - console.error('page error', domain, rawPageId, err) + console.error('page error', siteDomain, rawPageId, err) return { props: { diff --git a/pages/_document.tsx b/pages/_document.tsx index c320241..87593d1 100644 --- a/pages/_document.tsx +++ b/pages/_document.tsx @@ -1,13 +1,13 @@ import React from 'react' import Document, { Html, Head, Main, NextScript } from 'next/document' -import * as config from 'lib/env' +import { siteFavicon } from 'lib/config' export default class MyDocument extends Document { render() { return ( - + { + if (req.method !== 'GET') { + return res.status(405).send({ error: 'method not allowed' }) + } + + const pageId = req.query.pageId as string + + if (!pageId) { + return res.status(400).send({ error: 'missing required parameter pageId' }) + } + + let recordMap: types.ExtendedRecordMap + let block: types.PageBlock + + try { + recordMap = await getPage(pageId) + + const pageBlockId = Object.keys(recordMap.block)[0] + block = recordMap.block[pageBlockId]?.value as types.PageBlock + + if (!block) { + return res.status(404).send({ + error: `unable to resolve root block for notion page "${pageId}"` + }) + } + } catch (err) { + return res + .status(404) + .send({ error: `unable to load notion page "${pageId}"` }) + } + + // TODO: centralize these default config values + const image = await createSocialImage({ + imageUrl: block.format?.page_cover ?? defaultPageCover, + title: getBlockTitle(block, recordMap) ?? siteName, + logo: getBlockIcon(block, recordMap) ?? defaultPageIcon, + subtitle: getPageDescription(block, recordMap) ?? siteDescription, + watermark: siteDomain + }) + + res.setHeader( + 'Cache-Control', + 'public, immutable, s-maxage=31536000, max-age=31536000, stale-while-revalidate=60' + ) + res.setHeader('Content-Type', 'image/jpeg') + res.status(200).send(image) +} + +async function createSocialImage(params: SocialImageConfig) { + let browser + + try { + browser = await chromium.puppeteer.launch({ + args: chromium.args, + defaultViewport: chromium.defaultViewport, + executablePath: await chromium.executablePath, + headless: true, // chromium.headless, + ignoreHTTPSErrors: true + }) + + const res = await renderSocialImage({ + template: 'article', + templateParams: params, + templateStyles: `h1 { font-size: 96px; text-align: center; } h2 { font-size: 32px; }`, + size: params.size, + browser + }) + + return res + } finally { + if (browser) { + await browser.close() + } + } +} diff --git a/pages/index.tsx b/pages/index.tsx index 07c2b4a..393c1a0 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,15 +1,15 @@ import React from 'react' -import { domain } from 'lib/env' +import { siteDomain } from 'lib/config' import { resolveNotionPage } from 'lib/resolve-notion-page' import { NotionPage } from 'components' export const getStaticProps = async (context) => { try { - const props = await resolveNotionPage(domain) + const props = await resolveNotionPage(siteDomain) return { props, revalidate: 10 } } catch (err) { - console.error('page error', domain, err) + console.error('page error', siteDomain, err) return { props: { diff --git a/vercel.json b/vercel.json index 4199751..2aa949d 100644 --- a/vercel.json +++ b/vercel.json @@ -5,8 +5,6 @@ "GOOGLE_APPLICATION_CREDENTIALS": "@transitive-bullshit-google-application-credentials", "GCLOUD_PROJECT": "@transitive-bullshit-gcloud-project", "FIREBASE_COLLECTION_IMAGES": "@transitive-bullshit-firebase-collection-images", - "DOMAIN": "@transitive-bullshit-domain", - "NOTION_ROOT_PAGE_ID": "@transitive-bullshit-notion-root-page-id", "FATHOM_ID": "@transitive-bullshit-fathom-id" } } diff --git a/yarn.lock b/yarn.lock index 29461a9..69f275a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -111,6 +111,14 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79" integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg== +"@babel/polyfill@^7.4.4": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.12.1.tgz#1f2d6371d1261bbd961f3c5d5909150e12d0bd96" + integrity sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g== + dependencies: + core-js "^2.6.5" + regenerator-runtime "^0.13.4" + "@babel/runtime@7.12.5", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.2.0": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" @@ -430,6 +438,13 @@ dependencies: "@types/node" "*" +"@types/yauzl@^2.9.1": + version "2.9.1" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.1.tgz#d10f69f9f522eef3cf98e30afb684a1e1ec923af" + integrity sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA== + dependencies: + "@types/node" "*" + "@xobotyi/scrollbar-width@1.9.5": version "1.9.5" resolved "https://registry.yarnpkg.com/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz#80224a6919272f405b87913ca13b92929bdf3c4d" @@ -470,6 +485,11 @@ adjust-sourcemap-loader@3.0.0: loader-utils "^2.0.0" regex-parser "^2.2.11" +agent-base@5: + version "5.1.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c" + integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -807,6 +827,11 @@ browserslist@4.14.6: escalade "^3.1.1" node-releases "^1.1.65" +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= + 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" @@ -839,7 +864,7 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.5.0: +buffer@^5.2.1, buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -953,6 +978,13 @@ chownr@^2.0.0: resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== +chrome-aws-lambda@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/chrome-aws-lambda/-/chrome-aws-lambda-5.5.0.tgz#5b011d1596020b6ab4b92b010e427da1be6fc628" + integrity sha512-nYSDzTsVEVsvIFaUUAUN53ulXBLKSRXFS+eVYZOLZD5SA1If59rqBAiy4raMgorQwXWqjSsjK1SF4As+qzPLqA== + dependencies: + lambdafs "^2.0.0" + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -987,6 +1019,11 @@ clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" +clone@2.x: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -1103,6 +1140,11 @@ copy-to-clipboard@^3.2.0: dependencies: toggle-selection "^1.0.6" +core-js@^2.6.5: + version "2.6.12" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" + integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== + core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -1371,6 +1413,11 @@ detect-libc@^1.0.3: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= +devtools-protocol@0.0.818844: + version "0.0.818844" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.818844.tgz#d1947278ec85b53e4c8ca598f607a28fa785ba9e" + integrity sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -1895,6 +1942,17 @@ extend@^3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== +extract-zip@^2.0.0: + 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" @@ -1935,6 +1993,13 @@ fathom-client@^3.0.0: resolved "https://registry.yarnpkg.com/fathom-client/-/fathom-client-3.0.0.tgz#409c047cf1e2fea45b148e28d50fcd635e992893" integrity sha512-d0oH2SHWCMIVLbbegB7nBIjSvbqbHrZBZxIOWSVAxlJL/roL0Ah9NNb6rTIcKMlA4gov9AjWQGEcZRzlnGc3XQ== +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" + file-entry-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" @@ -2198,6 +2263,25 @@ gzip-size@^6.0.0: dependencies: duplexer "^0.1.2" +handlebars-jest@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/handlebars-jest/-/handlebars-jest-0.5.0.tgz#a0df11060aafb70d643d2535ceb1e6e1ead21efd" + integrity sha512-lf4LzgGqdHE7hPL+XPb89z8m2uRkcSW8DKPQqYAub8KF9r76emGFtnARn7rvBpbGmxGome+4Uw46VpJYUFisNg== + dependencies: + node-cache "^4.2.0" + +handlebars@^4.1.2: + version "4.7.6" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e" + integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.0" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -2315,6 +2399,14 @@ https-proxy-agent@5.0.0, https-proxy-agent@^5.0.0: agent-base "6" debug "4" +https-proxy-agent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz#702b71fb5520a132a66de1f67541d9e62154d82b" + integrity sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg== + dependencies: + agent-base "5" + debug "4" + hyphenate-style-name@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" @@ -2676,6 +2768,13 @@ keyv@^4.0.0: dependencies: json-buffer "3.0.1" +lambdafs@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/lambdafs/-/lambdafs-2.0.1.tgz#ddbee479e8e204dc17f1a43307ec3ae1df9ea485" + integrity sha512-RNb7Si2XPvU6pPiE6S0eDfH1W3n+OQaxpclSPJD0hnNFA5z+U1Ntr4sgUEE9xSxVu932ufh1iwtBcIxpEM9bOw== + dependencies: + tar-fs "^2.1.1" + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -2769,7 +2868,7 @@ lodash.throttle@^4.1.1: resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= -lodash@^4.17.13, lodash@^4.17.19, lodash@^4.17.20: +lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -3006,6 +3105,11 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= +neo-async@^2.6.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + next-tick@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" @@ -3076,6 +3180,14 @@ node-addon-api@^3.0.0, node-addon-api@^3.0.2: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.1.0.tgz#98b21931557466c6729e51cb77cd39c965f42239" integrity sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw== +node-cache@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-4.2.1.tgz#efd8474dee4edec4138cdded580f5516500f7334" + integrity sha512-BOb67bWg2dTyax5kdef5WfU3X8xu4wPg+zHzkvls0Q/QpYycIFRLEEIdAx9Wma43DxG6Qzn4illdZoYseKWa4A== + dependencies: + clone "2.x" + lodash "^4.17.15" + node-ensure@^0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/node-ensure/-/node-ensure-0.0.0.tgz#ecae764150de99861ec5c810fd5d096b183932a7" @@ -3500,6 +3612,11 @@ pdfjs-dist@2.1.266: node-ensure "^0.0.0" worker-loader "^2.0.0" +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: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" @@ -3527,7 +3644,7 @@ pkg-dir@^2.0.0: dependencies: find-up "^2.1.0" -pkg-dir@^4.1.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== @@ -3714,7 +3831,7 @@ process@0.11.10, process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= -progress@^2.0.0: +progress@^2.0.0, progress@^2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -3747,6 +3864,11 @@ protobufjs@^6.10.2, protobufjs@^6.8.6: "@types/node" "^13.7.0" long "^4.0.0" +proxy-from-env@^1.0.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== + public-encrypt@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" @@ -3782,6 +3904,51 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +puppeteer-core@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-5.5.0.tgz#dfb6266efe5a933cbf1a368d27025a6fd4f5a884" + integrity sha512-tlA+1n+ziW/Db03hVV+bAecDKse8ihFRXYiEypBe9IlLRvOCzYFG6qrCMBYK34HO/Q/Ecjc+tvkHRAfLVH+NgQ== + dependencies: + debug "^4.1.0" + devtools-protocol "0.0.818844" + extract-zip "^2.0.0" + https-proxy-agent "^4.0.0" + node-fetch "^2.6.1" + pkg-dir "^4.2.0" + progress "^2.0.1" + proxy-from-env "^1.0.0" + rimraf "^3.0.2" + tar-fs "^2.0.0" + unbzip2-stream "^1.3.3" + ws "^7.2.3" + +puppeteer-social-image-transitive-bs@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/puppeteer-social-image-transitive-bs/-/puppeteer-social-image-transitive-bs-0.8.1.tgz#388379fd555e9ce4798629099dd4e6c0bcf161be" + integrity sha512-jYasq40M/p8gmeBYGj5/vVTwRnY2eHG9HhMBLazVPl6x4Pu7pFF9MTVkB+NLHJvyIsaayeLht+TYrnIEGXBCHg== + dependencies: + "@babel/polyfill" "^7.4.4" + handlebars "^4.1.2" + handlebars-jest "^0.5.0" + +puppeteer@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-5.5.0.tgz#331a7edd212ca06b4a556156435f58cbae08af00" + integrity sha512-OM8ZvTXAhfgFA7wBIIGlPQzvyEETzDjeRa4mZRCRHxYL+GNH5WAuYUQdja3rpWZvkX/JKqmuVgbsxDNsDFjMEg== + dependencies: + debug "^4.1.0" + devtools-protocol "0.0.818844" + extract-zip "^2.0.0" + https-proxy-agent "^4.0.0" + node-fetch "^2.6.1" + pkg-dir "^4.2.0" + progress "^2.0.1" + proxy-from-env "^1.0.0" + rimraf "^3.0.2" + tar-fs "^2.0.0" + unbzip2-stream "^1.3.3" + ws "^7.2.3" + querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" @@ -4839,6 +5006,11 @@ throttle-debounce@^2.1.0: resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.3.0.tgz#fd31865e66502071e411817e241465b3e9c372e2" integrity sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ== +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= + timers-browserify@^2.0.4: version "2.0.12" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" @@ -4959,6 +5131,19 @@ typescript@^4.0.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== +uglify-js@^3.1.4: + version "3.12.4" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.12.4.tgz#93de48bb76bb3ec0fc36563f871ba46e2ee5c7ee" + integrity sha512-L5i5jg/SHkEqzN18gQMTWsZk3KelRsfD1wUVNqtq0kzqWQqcJjyL8yc1o8hJgRrWqrAl2mUFbhfznEIoi7zi2A== + +unbzip2-stream@^1.3.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" + integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== + dependencies: + buffer "^5.2.1" + through "^2.3.8" + unfetch@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be" @@ -5118,6 +5303,11 @@ word-wrap@^1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + worker-loader@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/worker-loader/-/worker-loader-2.0.0.tgz#45fda3ef76aca815771a89107399ee4119b430ac" @@ -5131,7 +5321,7 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -ws@^7.3.1: +ws@^7.2.3, ws@^7.3.1: version "7.4.2" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.2.tgz#782100048e54eb36fe9843363ab1c68672b261dd" integrity sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA== @@ -5146,6 +5336,14 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +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" + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"