├── .editorconfig ├── .eslintrc.js ├── .github └── workflows │ └── qc.yml ├── .gitignore ├── README.md ├── api └── og │ └── [title].ts ├── docs ├── background.jpg ├── banner.jpeg ├── hero.png ├── image-left.png └── image-right.png ├── index.d.ts ├── package.json ├── pnpm-lock.yaml ├── prettier.config.js ├── src ├── constant │ └── api.ts ├── lib │ ├── compress.test.ts │ ├── compress.ts │ ├── constant │ │ └── font.ts │ ├── generator.test.ts │ ├── generator.ts │ ├── injector.test.ts │ ├── injector.ts │ ├── puppeteer.ts │ ├── sanitizer.test.ts │ ├── sanitizer.ts │ ├── template │ │ ├── blank.ts │ │ ├── hero.ts │ │ ├── image-left.ts │ │ ├── image-right.ts │ │ ├── template.test.ts │ │ └── template.ts │ ├── types.ts │ ├── utils.test.ts │ └── utils.ts └── mocks │ ├── img.ts │ └── server.ts ├── tsconfig.build.json ├── tsconfig.json ├── vercel.json └── vite.config.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | end_of_line = crlf 3 | indent_size = 2 4 | indent_style = space 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['@typescript-eslint', 'jsdoc', 'prettier'], 3 | parser: '@typescript-eslint/parser', 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:jsdoc/recommended', 8 | 'xo', 9 | 'prettier', 10 | ], 11 | parserOptions: { 12 | ecmaVersion: 6, 13 | sourceType: 'module', 14 | }, 15 | rules: { 16 | 'linebreak-style': ['error', 'windows'], 17 | 'object-curly-spacing': ['error', 'always'], 18 | 'indent': 'off', 19 | 'no-unused-vars': 'off', 20 | '@typescript-eslint/no-unused-vars': 'error', 21 | 'require-jsdoc': 'off', 22 | 'new-cap': 'off', 23 | 'prettier/prettier': ['error'], 24 | 'no-undef': 'off', 25 | 'jsdoc/no-undefined-types': 'off', 26 | // 'comma-dangle': ['error', 'always-multiline'], 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /.github/workflows/qc.yml: -------------------------------------------------------------------------------- 1 | name: Lint and test files on every pull and root branch push 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | test: 13 | name: Lint and test 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | node-version: [14] 18 | steps: 19 | - name: Checkout from repository 20 | uses: actions/checkout@v2.3.3 21 | - uses: pnpm/action-setup@v2.0.1 22 | with: 23 | version: 6.20.3 24 | - name: Use Node.js ${{ matrix.node-version }} 25 | uses: actions/setup-node@v2 26 | with: 27 | node-version: ${{ matrix.node-version }} 28 | cache: 'pnpm' 29 | - name: Install dependencies 30 | run: pnpm install 31 | - name: Lint code 32 | run: pnpm run lint 33 | - name: Test code 34 | run: pnpm run test 35 | - name: Build the code 36 | run: pnpm run build 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | 36 | # typescript 37 | *.tsbuildinfo 38 | dist 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Windgraph 3 |

4 | 5 | > This project is now deprecated. If you want similar solution, please use [@vercel/og](https://vercel.com/docs/concepts/functions/edge-functions/og-image-generation) library instead as it's faster and more mature. In the future, the service will be terminated indefinitely. 6 | 7 | Windgraph is a service that lets you generate a dynamic, Tailwind-powered Open Graph images that you can use either for SEO or just for social images. 8 | 9 | Inspired by [Vercel's original og-image](https://github.com/vercel/og-image). 10 | 11 | > Windgraph is still on active development. The API may change without prior notice. 12 | 13 | ## Features 14 | 15 | - Markdown syntax support 16 | - Batteries-included default styling 17 | - Latest Tailwind features, including [arbitrary values](https://tailwindcss.com/docs/adding-custom-styles#using-arbitrary-values) 18 | - Customizable fonts powered by [Google Fonts](https://fonts.google.com/) 19 | 20 | ## Open Graph Template 21 | 22 | Currently, there are 3 pre-made templates that can be used to generate Open Graph images. 23 | 24 | ### `hero` 25 | 26 | ![Hero Template](./docs/hero.png) 27 | 28 | ### `image-left` 29 | 30 | ![Image Left Template](./docs/image-left.png) 31 | 32 | ### `image-right` 33 | 34 | ![Image Right Template](./docs/image-right.png) 35 | 36 | You must specify the template you want to use in form of querystring. 37 | 38 | If `template` is omitted, `windgraph` won't be using any template at all and styling is left to the user. 39 | 40 | > Feel free to request a template by submitting an issue. 41 | 42 | ## API 43 | 44 | GET - `/api/og/?<query>` 45 | 46 | Generate an open graph image based on user's input and template. 47 | 48 | ### Parameters 49 | 50 | Name | Description 51 | ---- | ----------- 52 | `title` | Image title, supports Markdown syntax. **REQUIRED** 53 | 54 | ### Query 55 | 56 | Name | Description 57 | ---- | ----------- 58 | `subtitle` | Open Graph subtitle, supports Markdown syntax. 59 | `footer` | Open Graph footer, supports Markdown syntax. 60 | `image` | Image source, must be an accessible URL that responds with an image. 61 | `width` | Output image width in pixels. Defaults to `1200` 62 | `height` | Output image height in pixels. Defauls to `630` 63 | `container-class` | Tailwind CSS classes to be injected to main container. Defaults to `w-screen h-screen p-16 flex flex-col justify-center items-center` 64 | `title-class` | Tailwind CSS classes to be injected to `title`. Defaults to `text-center text-7xl leading-relaxed` 65 | `subtitle-class` | Tailwind CSS classes to be injected to `subtitle`. Defaults to `text-center text-2xl` 66 | `image-class` | Tailwind CSS classes to be injected to `image`. Defaults to `w-full h-auto max-w-[40vh]` 67 | `footer-class` | Tailwind CSS classes to be injected to `footer`. Defaults to `text-center text-sm` 68 | `font-sans` | Sans serif fonts to be used. Defaults to Tailwind's default 69 | `font-serif` | Serif fonts to be used. Defaults to Tailwind's default. Must be used with `font-serif` class. 70 | `font-mono` | Monospaced fonts to be used. Defaults to Tailwind's default. Automatically used on code blocks. 71 | `format` | Image format. Allowed values are `jpeg` and `png`. By default, `jpeg` is compressed to 80% quality. Defaults to `jpeg` 72 | `compress` | Boolean value that represents if the image should be compressed or not. This parameter allows for finer compression compared to the default `jpeg` compression. Default to `false` 73 | `template` | Template name. 74 | 75 | ## Showcase 76 | 77 | `https://windgraph.vercel.app/api/og/**Hello**%20I'm%20Windgraph?template=hero&title-class=text-white%20mb-4&subtitle=by%20Namchee&subtitle-class=text-white&font-sans=Inter&container-class=bg-gradient-to-b%20from-fuchsia-500%20via-red-600%20to-orange-400` 78 | 79 | <img src="https://windgraph.vercel.app/api/og/**Hello**%20I'm%20Windgraph?template=hero&title-class=text-white%20mb-4&subtitle=by%20Namchee&subtitle-class=text-white&font-sans=Inter&container-class=bg-gradient-to-b%20from-fuchsia-500%20via-red-600%20to-orange-400" title="Sample Windgraph request" /> 80 | 81 | ### With Background Image 82 | 83 | You can use images or inline SVG as a background by utilizing Tailwind's [arbitrary values](https://v2.tailwindcss.com/docs/just-in-time-mode#arbitrary-value-support). For example: 84 | 85 | `https://windgraph.vercel.app/api/og/**Hello**,%20I'm%20%60Windgraph%60?title-class=text-white%20mb-4&container-class=bg-cover%20bg-[url(%27https://raw.githubusercontent.com/Namchee/windgraph/master/docs/background.jpg%27)]&subtitle=by%20Namchee&subtitle-class=text-white&template=hero` 86 | 87 | <img src="https://windgraph.vercel.app/api/og/**Hello**,%20I'm%20%60Windgraph%60?title-class=text-white%20mb-4&container-class=bg-cover%20bg-[url(%27https://raw.githubusercontent.com/Namchee/windgraph/master/docs/background.jpg%27)]&subtitle=by%20Namchee&subtitle-class=text-white&template=hero" title="Sample Arbitrary Value" /> 88 | 89 | ### Using Other Templates 90 | 91 | `https://windgraph.vercel.app/api/og/useEffect%20vs%20useLayoutEffect?subtitle=Check%20Out%20This%20Article&image=https%3A%2F%2Fimages.unsplash.com%2Fphoto-1518050947974-4be8c7469f0c&template=image-right&subtitle-class=mb-4%20text-2xl%20text-gray-400&title-class=text-white%20text-6xl%20leading-tight%20font-medium&container-class=bg-gray-900&font-sans=Inter&footer=Made%20by%20Namchee.%20Inspired%20by%20Kent%20C.%20Dodds%20article&footer-class=text-xl%20text-gray-400&image-class=w-full%20h-full` 92 | 93 | <img src="https://windgraph.vercel.app/api/og/useEffect%20vs%20useLayoutEffect?subtitle=Check%20Out%20This%20Article&image=https%3A%2F%2Fimages.unsplash.com%2Fphoto-1518050947974-4be8c7469f0c&template=image-right&subtitle-class=mb-4%20text-2xl%20text-gray-400&title-class=text-white%20text-6xl%20leading-tight%20font-medium&container-class=bg-gray-900&font-sans=Inter&footer=Made%20by%20Namchee.%20Inspired%20by%20Kent%20C.%20Dodds%20article&footer-class=text-xl%20text-gray-400&image-class=w-full%20h-full" title="Image Right Template" /> 94 | 95 | ## FAQ 96 | 97 | ### Can I avoid the markdown feature? 98 | 99 | To avoid markdown processing, you can escape markdown characters by prepending it with `\` or `%5C`. For example: 100 | 101 | `https://windgraph.vercel.app/api/og/%5C*%5C*Hello%5C*%5C*,%20I'm%20%60Windgraph%60?title-class=mb-4%20text-white&container-class=bg-gradient-to-b%20from-rose-400%20via-fuchsia-500%20to-indigo-500&subtitle=by%20Namchee&subtitle-class=text-white&template=hero` 102 | 103 | <img src="https://windgraph.vercel.app/api/og/%5C*%5C*Hello%5C*%5C*,%20I'm%20%60Windgraph%60?title-class=mb-4%20text-white&container-class=bg-gradient-to-b%20from-rose-400%20via-fuchsia-500%20to-indigo-500&subtitle=by%20Namchee&subtitle-class=text-white&template=hero" /> 104 | 105 | ### I'm using `image-left` / `image-right` template but `space-x-{value}` is not working properly! 106 | 107 | As all provided templates is created using CSS grid, it is recommended to use [gap utilities](https://tailwindcss.com/docs/gap) instead to ensure 100% compatibility. 108 | 109 | ## Limitations 110 | 111 | Besides the limit of Tailwind itself, there are two main limitations of using Windgraph: 112 | 113 | ### Static Template 114 | 115 | Currently you cannot use any other form of template other than the provided one. This will be addressed in future release where you can craft template and use it for your personal use. 116 | 117 | ### URL Length Limitation 118 | 119 | While there are no actual limitations for URL length according to [RFC 2616](http://www.faqs.org/rfcs/rfc2616.html), it's recommended to keep the URL length to 2048 characters at maximum. Bearing that in mind, you shouldn't add too much Tailwind classes or using too much arbitrary values that contains long values. 120 | 121 | ## License 122 | 123 | This project is licensed under the [MIT License](./LICENSE) 124 | 125 | ## Credits 126 | 127 | - Background image in background image customization demonstration is taken by <a href="https://unsplash.com/@jrkorpa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Jr Korpa</a> on <a href="https://unsplash.com/s/photos/neon?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a> 128 | - Image in image right sample is taken by <a href="https://unsplash.com/@stephenfjohnson?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Stephen Johnson</a> on <a href="https://unsplash.com/s/photos/lights?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a> 129 | 130 | 131 | -------------------------------------------------------------------------------- /api/og/[title].ts: -------------------------------------------------------------------------------- 1 | import { generateContent } from '../../src/lib/generator'; 2 | import { captureScreen } from './../../src/lib/puppeteer'; 3 | import { generatePageOptions } from './../../src/lib/utils'; 4 | import { compressImage } from './../../src/lib/compress'; 5 | 6 | import { VercelRequest, VercelResponse } from '@vercel/node'; 7 | 8 | import type { OpenGraphRequest, PageOptions } from './../../src/lib/types'; 9 | 10 | /** 11 | * Sample route handler 12 | * 13 | * @param {VercelRequest} req request object 14 | * @param {VercelResponse} res response object 15 | * @returns {Promise<VercelResponse>} response object that contains generated 16 | * open graph image 17 | */ 18 | async function og( 19 | req: VercelRequest, 20 | res: VercelResponse 21 | ): Promise<VercelResponse> { 22 | const { query } = req; 23 | 24 | const ogRequest: OpenGraphRequest = { 25 | title: query.title as string, 26 | subtitle: query.subtitle as string, 27 | footer: query.footer as string, 28 | image: query.image as string, 29 | containerClass: query['container-class'] as string, 30 | titleClass: query['title-class'] as string, 31 | subtitleClass: query['subtitle-class'] as string, 32 | imageClass: query['image-class'] as string, 33 | footerClass: query['footer-class'] as string, 34 | fontSans: query['font-sans'] as string, 35 | fontSerif: query['font-serif'] as string, 36 | fontMono: query['font-mono'] as string, 37 | template: query.template as string, 38 | }; 39 | 40 | const html = await generateContent(ogRequest); 41 | const options: PageOptions = generatePageOptions( 42 | query as Record<string, string> 43 | ); 44 | 45 | let img = await captureScreen(html, options); 46 | if (options.compress && options.format === 'png') { 47 | img = await compressImage(img); 48 | } 49 | 50 | res.setHeader('Content-Length', img.byteLength); 51 | res.setHeader('Content-Type', `image/${options.format}`); 52 | 53 | return res.status(200).end(img); 54 | } 55 | 56 | export default og; 57 | -------------------------------------------------------------------------------- /docs/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Namchee/windgraph/ef1d12d59f3fde192712b6166baeddb83a56ae37/docs/background.jpg -------------------------------------------------------------------------------- /docs/banner.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Namchee/windgraph/ef1d12d59f3fde192712b6166baeddb83a56ae37/docs/banner.jpeg -------------------------------------------------------------------------------- /docs/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Namchee/windgraph/ef1d12d59f3fde192712b6166baeddb83a56ae37/docs/hero.png -------------------------------------------------------------------------------- /docs/image-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Namchee/windgraph/ef1d12d59f3fde192712b6166baeddb83a56ae37/docs/image-left.png -------------------------------------------------------------------------------- /docs/image-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Namchee/windgraph/ef1d12d59f3fde192712b6166baeddb83a56ae37/docs/image-right.png -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@squoosh/lib'; 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "windgraph", 3 | "private": true, 4 | "scripts": { 5 | "build": "tsc --project tsconfig.build.json", 6 | "lint": "eslint src/**", 7 | "test": "vitest" 8 | }, 9 | "dependencies": { 10 | "chrome-aws-lambda": "^10.1.0", 11 | "imagemin": "7.0.1", 12 | "imagemin-pngquant": "^9.0.2", 13 | "isomorphic-unfetch": "^3.1.0", 14 | "markdown-wasm": "^1.2.0", 15 | "puppeteer-core": "10.1.0" 16 | }, 17 | "devDependencies": { 18 | "@types/imagemin": "7.0.1", 19 | "@types/node": "^17.0.10", 20 | "@typescript-eslint/eslint-plugin": "^5.10.0", 21 | "@typescript-eslint/parser": "^5.10.0", 22 | "@vercel/node": "^1.13.0", 23 | "eslint": "8.7.0", 24 | "eslint-config-prettier": "^8.3.0", 25 | "eslint-config-xo": "^0.39.0", 26 | "eslint-plugin-jsdoc": "^37.6.3", 27 | "eslint-plugin-prettier": "^4.0.0", 28 | "msw": "^0.39.2", 29 | "prettier": "^2.5.1", 30 | "typescript": "^4.5.5", 31 | "vite": "^2.8.6", 32 | "vitest": "^0.7.4" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: 5.4 2 | 3 | specifiers: 4 | '@types/imagemin': 7.0.1 5 | '@types/node': ^17.0.10 6 | '@typescript-eslint/eslint-plugin': ^5.10.0 7 | '@typescript-eslint/parser': ^5.10.0 8 | '@vercel/node': ^1.13.0 9 | chrome-aws-lambda: ^10.1.0 10 | eslint: 8.7.0 11 | eslint-config-prettier: ^8.3.0 12 | eslint-config-xo: ^0.39.0 13 | eslint-plugin-jsdoc: ^37.6.3 14 | eslint-plugin-prettier: ^4.0.0 15 | imagemin: 7.0.1 16 | imagemin-pngquant: ^9.0.2 17 | isomorphic-unfetch: ^3.1.0 18 | markdown-wasm: ^1.2.0 19 | msw: ^0.39.2 20 | prettier: ^2.5.1 21 | puppeteer-core: 10.1.0 22 | typescript: ^4.5.5 23 | vite: ^2.8.6 24 | vitest: ^0.7.4 25 | 26 | dependencies: 27 | chrome-aws-lambda: 10.1.0_puppeteer-core@10.1.0 28 | imagemin: 7.0.1 29 | imagemin-pngquant: 9.0.2 30 | isomorphic-unfetch: 3.1.0 31 | markdown-wasm: 1.2.0 32 | puppeteer-core: 10.1.0 33 | 34 | devDependencies: 35 | '@types/imagemin': 7.0.1 36 | '@types/node': 17.0.10 37 | '@typescript-eslint/eslint-plugin': 5.10.0_obx3a7hhjmo3meprtibk2lhhqq 38 | '@typescript-eslint/parser': 5.10.0_j2dpqr3duszxwhwhg5puk5zm6e 39 | '@vercel/node': 1.13.0 40 | eslint: 8.7.0 41 | eslint-config-prettier: 8.3.0_eslint@8.7.0 42 | eslint-config-xo: 0.39.0_eslint@8.7.0 43 | eslint-plugin-jsdoc: 37.6.3_eslint@8.7.0 44 | eslint-plugin-prettier: 4.0.0_izqfdfjs4tb3bkpfxntcht7n6y 45 | msw: 0.39.2 46 | prettier: 2.5.1 47 | typescript: 4.5.5 48 | vite: 2.8.6 49 | vitest: 0.7.4 50 | 51 | packages: 52 | 53 | /@es-joy/jsdoccomment/0.17.0: 54 | resolution: {integrity: sha512-B8DIIWE194KyQFPojUs+THa2XX+1vulwTBjirw6GqcxjtNE60Rreex26svBnV9SNLTuz92ctZx5XQE1H7yOxgA==} 55 | engines: {node: ^12 || ^14 || ^16 || ^17} 56 | dependencies: 57 | comment-parser: 1.3.0 58 | esquery: 1.4.0 59 | jsdoc-type-pratt-parser: 2.2.2 60 | dev: true 61 | 62 | /@eslint/eslintrc/1.0.5: 63 | resolution: {integrity: sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==} 64 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 65 | dependencies: 66 | ajv: 6.12.6 67 | debug: 4.3.3 68 | espree: 9.3.0 69 | globals: 13.12.0 70 | ignore: 4.0.6 71 | import-fresh: 3.3.0 72 | js-yaml: 4.1.0 73 | minimatch: 3.0.4 74 | strip-json-comments: 3.1.1 75 | transitivePeerDependencies: 76 | - supports-color 77 | dev: true 78 | 79 | /@humanwhocodes/config-array/0.9.2: 80 | resolution: {integrity: sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA==} 81 | engines: {node: '>=10.10.0'} 82 | dependencies: 83 | '@humanwhocodes/object-schema': 1.2.1 84 | debug: 4.3.3 85 | minimatch: 3.0.4 86 | transitivePeerDependencies: 87 | - supports-color 88 | dev: true 89 | 90 | /@humanwhocodes/object-schema/1.2.1: 91 | resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} 92 | dev: true 93 | 94 | /@mswjs/cookies/0.2.0: 95 | resolution: {integrity: sha512-GTKYnIfXVP8GL8HRWrse+ujqDXCLKvu7+JoL6pvZFzS/d2i9pziByoWD69cOe35JNoSrx2DPNqrhUF+vgV3qUA==} 96 | engines: {node: '>=14'} 97 | dependencies: 98 | '@types/set-cookie-parser': 2.4.2 99 | set-cookie-parser: 2.4.8 100 | dev: true 101 | 102 | /@mswjs/interceptors/0.15.1: 103 | resolution: {integrity: sha512-D5B+ZJNlfvBm6ZctAfRBdNJdCHYAe2Ix4My5qfbHV5WH+3lkt3mmsjiWJzEh5ZwGDauzY487TldI275If7DJVw==} 104 | engines: {node: '>=14'} 105 | dependencies: 106 | '@open-draft/until': 1.0.3 107 | '@xmldom/xmldom': 0.7.5 108 | debug: 4.3.3 109 | headers-polyfill: 3.0.4 110 | outvariant: 1.2.1 111 | strict-event-emitter: 0.2.0 112 | transitivePeerDependencies: 113 | - supports-color 114 | dev: true 115 | 116 | /@nodelib/fs.scandir/2.1.5: 117 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 118 | engines: {node: '>= 8'} 119 | dependencies: 120 | '@nodelib/fs.stat': 2.0.5 121 | run-parallel: 1.2.0 122 | 123 | /@nodelib/fs.stat/2.0.5: 124 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 125 | engines: {node: '>= 8'} 126 | 127 | /@nodelib/fs.walk/1.2.8: 128 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 129 | engines: {node: '>= 8'} 130 | dependencies: 131 | '@nodelib/fs.scandir': 2.1.5 132 | fastq: 1.13.0 133 | 134 | /@open-draft/until/1.0.3: 135 | resolution: {integrity: sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==} 136 | dev: true 137 | 138 | /@sindresorhus/is/0.7.0: 139 | resolution: {integrity: sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==} 140 | engines: {node: '>=4'} 141 | dev: false 142 | 143 | /@types/chai-subset/1.3.3: 144 | resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} 145 | dependencies: 146 | '@types/chai': 4.3.0 147 | dev: true 148 | 149 | /@types/chai/4.3.0: 150 | resolution: {integrity: sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw==} 151 | dev: true 152 | 153 | /@types/cookie/0.4.1: 154 | resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} 155 | dev: true 156 | 157 | /@types/glob/7.2.0: 158 | resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} 159 | dependencies: 160 | '@types/minimatch': 3.0.5 161 | '@types/node': 17.0.10 162 | dev: false 163 | 164 | /@types/imagemin/7.0.1: 165 | resolution: {integrity: sha512-xEn5+M3lDBtI3JxLy6eU3ksoVurygnlG7OYhTqJfGGP4PcvYnfn+IABCmMve7ziM/SneHDm5xgJFKC8hCYPicw==} 166 | dependencies: 167 | '@types/node': 17.0.10 168 | dev: true 169 | 170 | /@types/js-levenshtein/1.1.1: 171 | resolution: {integrity: sha512-qC4bCqYGy1y/NP7dDVr7KJarn+PbX1nSpwA7JXdu0HxT3QYjO8MJ+cntENtHFVy2dRAyBV23OZ6MxsW1AM1L8g==} 172 | dev: true 173 | 174 | /@types/json-schema/7.0.9: 175 | resolution: {integrity: sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==} 176 | dev: true 177 | 178 | /@types/keyv/3.1.4: 179 | resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} 180 | dependencies: 181 | '@types/node': 17.0.10 182 | dev: false 183 | 184 | /@types/minimatch/3.0.5: 185 | resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} 186 | dev: false 187 | 188 | /@types/node/17.0.10: 189 | resolution: {integrity: sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog==} 190 | 191 | /@types/responselike/1.0.0: 192 | resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} 193 | dependencies: 194 | '@types/node': 17.0.10 195 | dev: false 196 | 197 | /@types/set-cookie-parser/2.4.2: 198 | resolution: {integrity: sha512-fBZgytwhYAUkj/jC/FAV4RQ5EerRup1YQsXQCh8rZfiHkc4UahC192oH0smGwsXol3cL3A5oETuAHeQHmhXM4w==} 199 | dependencies: 200 | '@types/node': 17.0.10 201 | dev: true 202 | 203 | /@types/yauzl/2.9.2: 204 | resolution: {integrity: sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==} 205 | requiresBuild: true 206 | dependencies: 207 | '@types/node': 17.0.10 208 | dev: false 209 | optional: true 210 | 211 | /@typescript-eslint/eslint-plugin/5.10.0_obx3a7hhjmo3meprtibk2lhhqq: 212 | resolution: {integrity: sha512-XXVKnMsq2fuu9K2KsIxPUGqb6xAImz8MEChClbXmE3VbveFtBUU5bzM6IPVWqzyADIgdkS2Ws/6Xo7W2TeZWjQ==} 213 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 214 | peerDependencies: 215 | '@typescript-eslint/parser': ^5.0.0 216 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 217 | typescript: '*' 218 | peerDependenciesMeta: 219 | typescript: 220 | optional: true 221 | dependencies: 222 | '@typescript-eslint/parser': 5.10.0_j2dpqr3duszxwhwhg5puk5zm6e 223 | '@typescript-eslint/scope-manager': 5.10.0 224 | '@typescript-eslint/type-utils': 5.10.0_j2dpqr3duszxwhwhg5puk5zm6e 225 | '@typescript-eslint/utils': 5.10.0_j2dpqr3duszxwhwhg5puk5zm6e 226 | debug: 4.3.3 227 | eslint: 8.7.0 228 | functional-red-black-tree: 1.0.1 229 | ignore: 5.2.0 230 | regexpp: 3.2.0 231 | semver: 7.3.5 232 | tsutils: 3.21.0_typescript@4.5.5 233 | typescript: 4.5.5 234 | transitivePeerDependencies: 235 | - supports-color 236 | dev: true 237 | 238 | /@typescript-eslint/parser/5.10.0_j2dpqr3duszxwhwhg5puk5zm6e: 239 | resolution: {integrity: sha512-pJB2CCeHWtwOAeIxv8CHVGJhI5FNyJAIpx5Pt72YkK3QfEzt6qAlXZuyaBmyfOdM62qU0rbxJzNToPTVeJGrQw==} 240 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 241 | peerDependencies: 242 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 243 | typescript: '*' 244 | peerDependenciesMeta: 245 | typescript: 246 | optional: true 247 | dependencies: 248 | '@typescript-eslint/scope-manager': 5.10.0 249 | '@typescript-eslint/types': 5.10.0 250 | '@typescript-eslint/typescript-estree': 5.10.0_typescript@4.5.5 251 | debug: 4.3.3 252 | eslint: 8.7.0 253 | typescript: 4.5.5 254 | transitivePeerDependencies: 255 | - supports-color 256 | dev: true 257 | 258 | /@typescript-eslint/scope-manager/5.10.0: 259 | resolution: {integrity: sha512-tgNgUgb4MhqK6DoKn3RBhyZ9aJga7EQrw+2/OiDk5hKf3pTVZWyqBi7ukP+Z0iEEDMF5FDa64LqODzlfE4O/Dg==} 260 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 261 | dependencies: 262 | '@typescript-eslint/types': 5.10.0 263 | '@typescript-eslint/visitor-keys': 5.10.0 264 | dev: true 265 | 266 | /@typescript-eslint/type-utils/5.10.0_j2dpqr3duszxwhwhg5puk5zm6e: 267 | resolution: {integrity: sha512-TzlyTmufJO5V886N+hTJBGIfnjQDQ32rJYxPaeiyWKdjsv2Ld5l8cbS7pxim4DeNs62fKzRSt8Q14Evs4JnZyQ==} 268 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 269 | peerDependencies: 270 | eslint: '*' 271 | typescript: '*' 272 | peerDependenciesMeta: 273 | typescript: 274 | optional: true 275 | dependencies: 276 | '@typescript-eslint/utils': 5.10.0_j2dpqr3duszxwhwhg5puk5zm6e 277 | debug: 4.3.3 278 | eslint: 8.7.0 279 | tsutils: 3.21.0_typescript@4.5.5 280 | typescript: 4.5.5 281 | transitivePeerDependencies: 282 | - supports-color 283 | dev: true 284 | 285 | /@typescript-eslint/types/5.10.0: 286 | resolution: {integrity: sha512-wUljCgkqHsMZbw60IbOqT/puLfyqqD5PquGiBo1u1IS3PLxdi3RDGlyf032IJyh+eQoGhz9kzhtZa+VC4eWTlQ==} 287 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 288 | dev: true 289 | 290 | /@typescript-eslint/typescript-estree/5.10.0_typescript@4.5.5: 291 | resolution: {integrity: sha512-x+7e5IqfwLwsxTdliHRtlIYkgdtYXzE0CkFeV6ytAqq431ZyxCFzNMNR5sr3WOlIG/ihVZr9K/y71VHTF/DUQA==} 292 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 293 | peerDependencies: 294 | typescript: '*' 295 | peerDependenciesMeta: 296 | typescript: 297 | optional: true 298 | dependencies: 299 | '@typescript-eslint/types': 5.10.0 300 | '@typescript-eslint/visitor-keys': 5.10.0 301 | debug: 4.3.3 302 | globby: 11.1.0 303 | is-glob: 4.0.3 304 | semver: 7.3.5 305 | tsutils: 3.21.0_typescript@4.5.5 306 | typescript: 4.5.5 307 | transitivePeerDependencies: 308 | - supports-color 309 | dev: true 310 | 311 | /@typescript-eslint/utils/5.10.0_j2dpqr3duszxwhwhg5puk5zm6e: 312 | resolution: {integrity: sha512-IGYwlt1CVcFoE2ueW4/ioEwybR60RAdGeiJX/iDAw0t5w0wK3S7QncDwpmsM70nKgGTuVchEWB8lwZwHqPAWRg==} 313 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 314 | peerDependencies: 315 | eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 316 | dependencies: 317 | '@types/json-schema': 7.0.9 318 | '@typescript-eslint/scope-manager': 5.10.0 319 | '@typescript-eslint/types': 5.10.0 320 | '@typescript-eslint/typescript-estree': 5.10.0_typescript@4.5.5 321 | eslint: 8.7.0 322 | eslint-scope: 5.1.1 323 | eslint-utils: 3.0.0_eslint@8.7.0 324 | transitivePeerDependencies: 325 | - supports-color 326 | - typescript 327 | dev: true 328 | 329 | /@typescript-eslint/visitor-keys/5.10.0: 330 | resolution: {integrity: sha512-GMxj0K1uyrFLPKASLmZzCuSddmjZVbVj3Ouy5QVuIGKZopxvOr24JsS7gruz6C3GExE01mublZ3mIBOaon9zuQ==} 331 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 332 | dependencies: 333 | '@typescript-eslint/types': 5.10.0 334 | eslint-visitor-keys: 3.2.0 335 | dev: true 336 | 337 | /@vercel/node/1.13.0: 338 | resolution: {integrity: sha512-AqdUuJC0+r3q1lcL+Knjb+dHsSDSCRfwFPJ7odRkHO7sfoAkhJI4RussIDFTF7Yvt0e+GmWuYGFAgwSiv4FWEg==} 339 | dependencies: 340 | '@types/node': 17.0.10 341 | ts-node: 8.9.1_typescript@4.3.4 342 | typescript: 4.3.4 343 | dev: true 344 | 345 | /@xmldom/xmldom/0.7.5: 346 | resolution: {integrity: sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==} 347 | engines: {node: '>=10.0.0'} 348 | dev: true 349 | 350 | /acorn-jsx/5.3.2_acorn@8.7.0: 351 | resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} 352 | peerDependencies: 353 | acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 354 | dependencies: 355 | acorn: 8.7.0 356 | dev: true 357 | 358 | /acorn/8.7.0: 359 | resolution: {integrity: sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==} 360 | engines: {node: '>=0.4.0'} 361 | hasBin: true 362 | dev: true 363 | 364 | /agent-base/6.0.2: 365 | resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} 366 | engines: {node: '>= 6.0.0'} 367 | dependencies: 368 | debug: 4.3.3 369 | transitivePeerDependencies: 370 | - supports-color 371 | dev: false 372 | 373 | /ajv/6.12.6: 374 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 375 | dependencies: 376 | fast-deep-equal: 3.1.3 377 | fast-json-stable-stringify: 2.1.0 378 | json-schema-traverse: 0.4.1 379 | uri-js: 4.4.1 380 | dev: true 381 | 382 | /ansi-escapes/4.3.2: 383 | resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} 384 | engines: {node: '>=8'} 385 | dependencies: 386 | type-fest: 0.21.3 387 | dev: true 388 | 389 | /ansi-regex/5.0.1: 390 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 391 | engines: {node: '>=8'} 392 | dev: true 393 | 394 | /ansi-styles/4.3.0: 395 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 396 | engines: {node: '>=8'} 397 | dependencies: 398 | color-convert: 2.0.1 399 | dev: true 400 | 401 | /anymatch/3.1.2: 402 | resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} 403 | engines: {node: '>= 8'} 404 | dependencies: 405 | normalize-path: 3.0.0 406 | picomatch: 2.3.1 407 | dev: true 408 | 409 | /arch/2.2.0: 410 | resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} 411 | dev: false 412 | 413 | /archive-type/4.0.0: 414 | resolution: {integrity: sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA=} 415 | engines: {node: '>=4'} 416 | dependencies: 417 | file-type: 4.4.0 418 | dev: false 419 | 420 | /arg/4.1.3: 421 | resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} 422 | dev: true 423 | 424 | /argparse/2.0.1: 425 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 426 | dev: true 427 | 428 | /array-union/2.1.0: 429 | resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} 430 | engines: {node: '>=8'} 431 | 432 | /assertion-error/1.1.0: 433 | resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} 434 | dev: true 435 | 436 | /balanced-match/1.0.2: 437 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 438 | 439 | /base64-js/1.5.1: 440 | resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} 441 | 442 | /bin-build/3.0.0: 443 | resolution: {integrity: sha512-jcUOof71/TNAI2uM5uoUaDq2ePcVBQ3R/qhxAz1rX7UfvduAL/RXD3jXzvn8cVcDJdGVkiR1shal3OH0ImpuhA==} 444 | engines: {node: '>=4'} 445 | dependencies: 446 | decompress: 4.2.1 447 | download: 6.2.5 448 | execa: 0.7.0 449 | p-map-series: 1.0.0 450 | tempfile: 2.0.0 451 | dev: false 452 | 453 | /bin-check/4.1.0: 454 | resolution: {integrity: sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA==} 455 | engines: {node: '>=4'} 456 | dependencies: 457 | execa: 0.7.0 458 | executable: 4.1.1 459 | dev: false 460 | 461 | /bin-version-check/4.0.0: 462 | resolution: {integrity: sha512-sR631OrhC+1f8Cvs8WyVWOA33Y8tgwjETNPyyD/myRBXLkfS/vl74FmH/lFcRl9KY3zwGh7jFhvyk9vV3/3ilQ==} 463 | engines: {node: '>=6'} 464 | dependencies: 465 | bin-version: 3.1.0 466 | semver: 5.7.1 467 | semver-truncate: 1.1.2 468 | dev: false 469 | 470 | /bin-version/3.1.0: 471 | resolution: {integrity: sha512-Mkfm4iE1VFt4xd4vH+gx+0/71esbfus2LsnCGe8Pi4mndSPyT+NGES/Eg99jx8/lUGWfu3z2yuB/bt5UB+iVbQ==} 472 | engines: {node: '>=6'} 473 | dependencies: 474 | execa: 1.0.0 475 | find-versions: 3.2.0 476 | dev: false 477 | 478 | /bin-wrapper/4.1.0: 479 | resolution: {integrity: sha512-hfRmo7hWIXPkbpi0ZltboCMVrU+0ClXR/JgbCKKjlDjQf6igXa7OwdqNcFWQZPZTgiY7ZpzE3+LjjkLiTN2T7Q==} 480 | engines: {node: '>=6'} 481 | dependencies: 482 | bin-check: 4.1.0 483 | bin-version-check: 4.0.0 484 | download: 7.1.0 485 | import-lazy: 3.1.0 486 | os-filter-obj: 2.0.0 487 | pify: 4.0.1 488 | dev: false 489 | 490 | /binary-extensions/2.2.0: 491 | resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} 492 | engines: {node: '>=8'} 493 | dev: true 494 | 495 | /bl/1.2.3: 496 | resolution: {integrity: sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==} 497 | dependencies: 498 | readable-stream: 2.3.7 499 | safe-buffer: 5.2.1 500 | dev: false 501 | 502 | /bl/4.1.0: 503 | resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} 504 | dependencies: 505 | buffer: 5.7.1 506 | inherits: 2.0.4 507 | readable-stream: 3.6.0 508 | 509 | /brace-expansion/1.1.11: 510 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 511 | dependencies: 512 | balanced-match: 1.0.2 513 | concat-map: 0.0.1 514 | 515 | /braces/3.0.2: 516 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} 517 | engines: {node: '>=8'} 518 | dependencies: 519 | fill-range: 7.0.1 520 | 521 | /buffer-alloc-unsafe/1.1.0: 522 | resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==} 523 | dev: false 524 | 525 | /buffer-alloc/1.2.0: 526 | resolution: {integrity: sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==} 527 | dependencies: 528 | buffer-alloc-unsafe: 1.1.0 529 | buffer-fill: 1.0.0 530 | dev: false 531 | 532 | /buffer-crc32/0.2.13: 533 | resolution: {integrity: sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=} 534 | dev: false 535 | 536 | /buffer-fill/1.0.0: 537 | resolution: {integrity: sha1-+PeLdniYiO858gXNY39o5wISKyw=} 538 | dev: false 539 | 540 | /buffer-from/1.1.2: 541 | resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} 542 | dev: true 543 | 544 | /buffer/5.7.1: 545 | resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} 546 | dependencies: 547 | base64-js: 1.5.1 548 | ieee754: 1.2.1 549 | 550 | /cacheable-request/2.1.4: 551 | resolution: {integrity: sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=} 552 | dependencies: 553 | clone-response: 1.0.2 554 | get-stream: 3.0.0 555 | http-cache-semantics: 3.8.1 556 | keyv: 3.0.0 557 | lowercase-keys: 1.0.0 558 | normalize-url: 2.0.1 559 | responselike: 1.0.2 560 | dev: false 561 | 562 | /callsites/3.1.0: 563 | resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 564 | engines: {node: '>=6'} 565 | dev: true 566 | 567 | /caw/2.0.1: 568 | resolution: {integrity: sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==} 569 | engines: {node: '>=4'} 570 | dependencies: 571 | get-proxy: 2.1.0 572 | isurl: 1.0.0 573 | tunnel-agent: 0.6.0 574 | url-to-options: 1.0.1 575 | dev: false 576 | 577 | /chai/4.3.6: 578 | resolution: {integrity: sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==} 579 | engines: {node: '>=4'} 580 | dependencies: 581 | assertion-error: 1.1.0 582 | check-error: 1.0.2 583 | deep-eql: 3.0.1 584 | get-func-name: 2.0.0 585 | loupe: 2.3.4 586 | pathval: 1.1.1 587 | type-detect: 4.0.8 588 | dev: true 589 | 590 | /chalk/4.1.1: 591 | resolution: {integrity: sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==} 592 | engines: {node: '>=10'} 593 | dependencies: 594 | ansi-styles: 4.3.0 595 | supports-color: 7.2.0 596 | dev: true 597 | 598 | /chalk/4.1.2: 599 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 600 | engines: {node: '>=10'} 601 | dependencies: 602 | ansi-styles: 4.3.0 603 | supports-color: 7.2.0 604 | dev: true 605 | 606 | /chardet/0.7.0: 607 | resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} 608 | dev: true 609 | 610 | /check-error/1.0.2: 611 | resolution: {integrity: sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=} 612 | dev: true 613 | 614 | /chokidar/3.5.3: 615 | resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} 616 | engines: {node: '>= 8.10.0'} 617 | dependencies: 618 | anymatch: 3.1.2 619 | braces: 3.0.2 620 | glob-parent: 5.1.2 621 | is-binary-path: 2.1.0 622 | is-glob: 4.0.3 623 | normalize-path: 3.0.0 624 | readdirp: 3.6.0 625 | optionalDependencies: 626 | fsevents: 2.3.2 627 | dev: true 628 | 629 | /chownr/1.1.4: 630 | resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} 631 | dev: false 632 | 633 | /chrome-aws-lambda/10.1.0_puppeteer-core@10.1.0: 634 | resolution: {integrity: sha512-NZQVf+J4kqG4sVhRm3WNmOfzY0OtTSm+S8rg77pwePa9RCYHzhnzRs8YvNI6L9tALIW6RpmefWiPURt3vURXcw==} 635 | engines: {node: '>= 10.16'} 636 | peerDependencies: 637 | puppeteer-core: ^10.1.0 638 | dependencies: 639 | lambdafs: 2.1.1 640 | puppeteer-core: 10.1.0 641 | dev: false 642 | 643 | /cli-cursor/3.1.0: 644 | resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} 645 | engines: {node: '>=8'} 646 | dependencies: 647 | restore-cursor: 3.1.0 648 | dev: true 649 | 650 | /cli-spinners/2.6.1: 651 | resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==} 652 | engines: {node: '>=6'} 653 | dev: true 654 | 655 | /cli-width/3.0.0: 656 | resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} 657 | engines: {node: '>= 10'} 658 | dev: true 659 | 660 | /cliui/7.0.4: 661 | resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} 662 | dependencies: 663 | string-width: 4.2.3 664 | strip-ansi: 6.0.1 665 | wrap-ansi: 7.0.0 666 | dev: true 667 | 668 | /clone-response/1.0.2: 669 | resolution: {integrity: sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=} 670 | dependencies: 671 | mimic-response: 1.0.1 672 | dev: false 673 | 674 | /clone/1.0.4: 675 | resolution: {integrity: sha1-2jCcwmPfFZlMaIypAheco8fNfH4=} 676 | engines: {node: '>=0.8'} 677 | dev: true 678 | 679 | /color-convert/2.0.1: 680 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 681 | engines: {node: '>=7.0.0'} 682 | dependencies: 683 | color-name: 1.1.4 684 | dev: true 685 | 686 | /color-name/1.1.4: 687 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 688 | dev: true 689 | 690 | /commander/2.20.3: 691 | resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} 692 | dev: false 693 | 694 | /comment-parser/1.3.0: 695 | resolution: {integrity: sha512-hRpmWIKgzd81vn0ydoWoyPoALEOnF4wt8yKD35Ib1D6XC2siLiYaiqfGkYrunuKdsXGwpBpHU3+9r+RVw2NZfA==} 696 | engines: {node: '>= 12.0.0'} 697 | dev: true 698 | 699 | /concat-map/0.0.1: 700 | resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} 701 | 702 | /config-chain/1.1.13: 703 | resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} 704 | dependencies: 705 | ini: 1.3.8 706 | proto-list: 1.2.4 707 | dev: false 708 | 709 | /confusing-browser-globals/1.0.10: 710 | resolution: {integrity: sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==} 711 | dev: true 712 | 713 | /content-disposition/0.5.4: 714 | resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} 715 | engines: {node: '>= 0.6'} 716 | dependencies: 717 | safe-buffer: 5.2.1 718 | dev: false 719 | 720 | /cookie/0.4.2: 721 | resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} 722 | engines: {node: '>= 0.6'} 723 | dev: true 724 | 725 | /core-util-is/1.0.3: 726 | resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} 727 | dev: false 728 | 729 | /cross-spawn/5.1.0: 730 | resolution: {integrity: sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=} 731 | dependencies: 732 | lru-cache: 4.1.5 733 | shebang-command: 1.2.0 734 | which: 1.3.1 735 | dev: false 736 | 737 | /cross-spawn/6.0.5: 738 | resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==} 739 | engines: {node: '>=4.8'} 740 | dependencies: 741 | nice-try: 1.0.5 742 | path-key: 2.0.1 743 | semver: 5.7.1 744 | shebang-command: 1.2.0 745 | which: 1.3.1 746 | dev: false 747 | 748 | /cross-spawn/7.0.3: 749 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 750 | engines: {node: '>= 8'} 751 | dependencies: 752 | path-key: 3.1.1 753 | shebang-command: 2.0.0 754 | which: 2.0.2 755 | 756 | /debug/4.3.1: 757 | resolution: {integrity: sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==} 758 | engines: {node: '>=6.0'} 759 | peerDependencies: 760 | supports-color: '*' 761 | peerDependenciesMeta: 762 | supports-color: 763 | optional: true 764 | dependencies: 765 | ms: 2.1.2 766 | dev: false 767 | 768 | /debug/4.3.3: 769 | resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} 770 | engines: {node: '>=6.0'} 771 | peerDependencies: 772 | supports-color: '*' 773 | peerDependenciesMeta: 774 | supports-color: 775 | optional: true 776 | dependencies: 777 | ms: 2.1.2 778 | 779 | /decode-uri-component/0.2.0: 780 | resolution: {integrity: sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=} 781 | engines: {node: '>=0.10'} 782 | dev: false 783 | 784 | /decompress-response/3.3.0: 785 | resolution: {integrity: sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=} 786 | engines: {node: '>=4'} 787 | dependencies: 788 | mimic-response: 1.0.1 789 | dev: false 790 | 791 | /decompress-tar/4.1.1: 792 | resolution: {integrity: sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==} 793 | engines: {node: '>=4'} 794 | dependencies: 795 | file-type: 5.2.0 796 | is-stream: 1.1.0 797 | tar-stream: 1.6.2 798 | dev: false 799 | 800 | /decompress-tarbz2/4.1.1: 801 | resolution: {integrity: sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==} 802 | engines: {node: '>=4'} 803 | dependencies: 804 | decompress-tar: 4.1.1 805 | file-type: 6.2.0 806 | is-stream: 1.1.0 807 | seek-bzip: 1.0.6 808 | unbzip2-stream: 1.3.3 809 | dev: false 810 | 811 | /decompress-targz/4.1.1: 812 | resolution: {integrity: sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==} 813 | engines: {node: '>=4'} 814 | dependencies: 815 | decompress-tar: 4.1.1 816 | file-type: 5.2.0 817 | is-stream: 1.1.0 818 | dev: false 819 | 820 | /decompress-unzip/4.0.1: 821 | resolution: {integrity: sha1-3qrM39FK6vhVePczroIQ+bSEj2k=} 822 | engines: {node: '>=4'} 823 | dependencies: 824 | file-type: 3.9.0 825 | get-stream: 2.3.1 826 | pify: 2.3.0 827 | yauzl: 2.10.0 828 | dev: false 829 | 830 | /decompress/4.2.1: 831 | resolution: {integrity: sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==} 832 | engines: {node: '>=4'} 833 | dependencies: 834 | decompress-tar: 4.1.1 835 | decompress-tarbz2: 4.1.1 836 | decompress-targz: 4.1.1 837 | decompress-unzip: 4.0.1 838 | graceful-fs: 4.2.9 839 | make-dir: 1.3.0 840 | pify: 2.3.0 841 | strip-dirs: 2.1.0 842 | dev: false 843 | 844 | /deep-eql/3.0.1: 845 | resolution: {integrity: sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==} 846 | engines: {node: '>=0.12'} 847 | dependencies: 848 | type-detect: 4.0.8 849 | dev: true 850 | 851 | /deep-is/0.1.4: 852 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 853 | dev: true 854 | 855 | /defaults/1.0.3: 856 | resolution: {integrity: sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=} 857 | dependencies: 858 | clone: 1.0.4 859 | dev: true 860 | 861 | /devtools-protocol/0.0.883894: 862 | resolution: {integrity: sha512-33idhm54QJzf3Q7QofMgCvIVSd2o9H3kQPWaKT/fhoZh+digc+WSiMhbkeG3iN79WY4Hwr9G05NpbhEVrsOYAg==} 863 | dev: false 864 | 865 | /diff/4.0.2: 866 | resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} 867 | engines: {node: '>=0.3.1'} 868 | dev: true 869 | 870 | /dir-glob/3.0.1: 871 | resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} 872 | engines: {node: '>=8'} 873 | dependencies: 874 | path-type: 4.0.0 875 | 876 | /doctrine/3.0.0: 877 | resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} 878 | engines: {node: '>=6.0.0'} 879 | dependencies: 880 | esutils: 2.0.3 881 | dev: true 882 | 883 | /download/6.2.5: 884 | resolution: {integrity: sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA==} 885 | engines: {node: '>=4'} 886 | dependencies: 887 | caw: 2.0.1 888 | content-disposition: 0.5.4 889 | decompress: 4.2.1 890 | ext-name: 5.0.0 891 | file-type: 5.2.0 892 | filenamify: 2.1.0 893 | get-stream: 3.0.0 894 | got: 7.1.0 895 | make-dir: 1.3.0 896 | p-event: 1.3.0 897 | pify: 3.0.0 898 | dev: false 899 | 900 | /download/7.1.0: 901 | resolution: {integrity: sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ==} 902 | engines: {node: '>=6'} 903 | dependencies: 904 | archive-type: 4.0.0 905 | caw: 2.0.1 906 | content-disposition: 0.5.4 907 | decompress: 4.2.1 908 | ext-name: 5.0.0 909 | file-type: 8.1.0 910 | filenamify: 2.1.0 911 | get-stream: 3.0.0 912 | got: 8.3.2 913 | make-dir: 1.3.0 914 | p-event: 2.3.1 915 | pify: 3.0.0 916 | dev: false 917 | 918 | /duplexer3/0.1.4: 919 | resolution: {integrity: sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=} 920 | dev: false 921 | 922 | /emoji-regex/8.0.0: 923 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 924 | dev: true 925 | 926 | /end-of-stream/1.4.4: 927 | resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} 928 | dependencies: 929 | once: 1.4.0 930 | dev: false 931 | 932 | /esbuild-android-64/0.14.27: 933 | resolution: {integrity: sha512-LuEd4uPuj/16Y8j6kqy3Z2E9vNY9logfq8Tq+oTE2PZVuNs3M1kj5Qd4O95ee66yDGb3isaOCV7sOLDwtMfGaQ==} 934 | engines: {node: '>=12'} 935 | cpu: [x64] 936 | os: [android] 937 | requiresBuild: true 938 | dev: true 939 | optional: true 940 | 941 | /esbuild-android-arm64/0.14.27: 942 | resolution: {integrity: sha512-E8Ktwwa6vX8q7QeJmg8yepBYXaee50OdQS3BFtEHKrzbV45H4foMOeEE7uqdjGQZFBap5VAqo7pvjlyA92wznQ==} 943 | engines: {node: '>=12'} 944 | cpu: [arm64] 945 | os: [android] 946 | requiresBuild: true 947 | dev: true 948 | optional: true 949 | 950 | /esbuild-darwin-64/0.14.27: 951 | resolution: {integrity: sha512-czw/kXl/1ZdenPWfw9jDc5iuIYxqUxgQ/Q+hRd4/3udyGGVI31r29LCViN2bAJgGvQkqyLGVcG03PJPEXQ5i2g==} 952 | engines: {node: '>=12'} 953 | cpu: [x64] 954 | os: [darwin] 955 | requiresBuild: true 956 | dev: true 957 | optional: true 958 | 959 | /esbuild-darwin-arm64/0.14.27: 960 | resolution: {integrity: sha512-BEsv2U2U4o672oV8+xpXNxN9bgqRCtddQC6WBh4YhXKDcSZcdNh7+6nS+DM2vu7qWIWNA4JbRG24LUUYXysimQ==} 961 | engines: {node: '>=12'} 962 | cpu: [arm64] 963 | os: [darwin] 964 | requiresBuild: true 965 | dev: true 966 | optional: true 967 | 968 | /esbuild-freebsd-64/0.14.27: 969 | resolution: {integrity: sha512-7FeiFPGBo+ga+kOkDxtPmdPZdayrSzsV9pmfHxcyLKxu+3oTcajeZlOO1y9HW+t5aFZPiv7czOHM4KNd0tNwCA==} 970 | engines: {node: '>=12'} 971 | cpu: [x64] 972 | os: [freebsd] 973 | requiresBuild: true 974 | dev: true 975 | optional: true 976 | 977 | /esbuild-freebsd-arm64/0.14.27: 978 | resolution: {integrity: sha512-8CK3++foRZJluOWXpllG5zwAVlxtv36NpHfsbWS7TYlD8S+QruXltKlXToc/5ZNzBK++l6rvRKELu/puCLc7jA==} 979 | engines: {node: '>=12'} 980 | cpu: [arm64] 981 | os: [freebsd] 982 | requiresBuild: true 983 | dev: true 984 | optional: true 985 | 986 | /esbuild-linux-32/0.14.27: 987 | resolution: {integrity: sha512-qhNYIcT+EsYSBClZ5QhLzFzV5iVsP1YsITqblSaztr3+ZJUI+GoK8aXHyzKd7/CKKuK93cxEMJPpfi1dfsOfdw==} 988 | engines: {node: '>=12'} 989 | cpu: [ia32] 990 | os: [linux] 991 | requiresBuild: true 992 | dev: true 993 | optional: true 994 | 995 | /esbuild-linux-64/0.14.27: 996 | resolution: {integrity: sha512-ESjck9+EsHoTaKWlFKJpPZRN26uiav5gkI16RuI8WBxUdLrrAlYuYSndxxKgEn1csd968BX/8yQZATYf/9+/qg==} 997 | engines: {node: '>=12'} 998 | cpu: [x64] 999 | os: [linux] 1000 | requiresBuild: true 1001 | dev: true 1002 | optional: true 1003 | 1004 | /esbuild-linux-arm/0.14.27: 1005 | resolution: {integrity: sha512-JnnmgUBdqLQO9hoNZQqNHFWlNpSX82vzB3rYuCJMhtkuaWQEmQz6Lec1UIxJdC38ifEghNTBsF9bbe8dFilnCw==} 1006 | engines: {node: '>=12'} 1007 | cpu: [arm] 1008 | os: [linux] 1009 | requiresBuild: true 1010 | dev: true 1011 | optional: true 1012 | 1013 | /esbuild-linux-arm64/0.14.27: 1014 | resolution: {integrity: sha512-no6Mi17eV2tHlJnqBHRLekpZ2/VYx+NfGxKcBE/2xOMYwctsanCaXxw4zapvNrGE9X38vefVXLz6YCF8b1EHiQ==} 1015 | engines: {node: '>=12'} 1016 | cpu: [arm64] 1017 | os: [linux] 1018 | requiresBuild: true 1019 | dev: true 1020 | optional: true 1021 | 1022 | /esbuild-linux-mips64le/0.14.27: 1023 | resolution: {integrity: sha512-NolWP2uOvIJpbwpsDbwfeExZOY1bZNlWE/kVfkzLMsSgqeVcl5YMen/cedRe9mKnpfLli+i0uSp7N+fkKNU27A==} 1024 | engines: {node: '>=12'} 1025 | cpu: [mips64el] 1026 | os: [linux] 1027 | requiresBuild: true 1028 | dev: true 1029 | optional: true 1030 | 1031 | /esbuild-linux-ppc64le/0.14.27: 1032 | resolution: {integrity: sha512-/7dTjDvXMdRKmsSxKXeWyonuGgblnYDn0MI1xDC7J1VQXny8k1qgNp6VmrlsawwnsymSUUiThhkJsI+rx0taNA==} 1033 | engines: {node: '>=12'} 1034 | cpu: [ppc64] 1035 | os: [linux] 1036 | requiresBuild: true 1037 | dev: true 1038 | optional: true 1039 | 1040 | /esbuild-linux-riscv64/0.14.27: 1041 | resolution: {integrity: sha512-D+aFiUzOJG13RhrSmZgrcFaF4UUHpqj7XSKrIiCXIj1dkIkFqdrmqMSOtSs78dOtObWiOrFCDDzB24UyeEiNGg==} 1042 | engines: {node: '>=12'} 1043 | cpu: [riscv64] 1044 | os: [linux] 1045 | requiresBuild: true 1046 | dev: true 1047 | optional: true 1048 | 1049 | /esbuild-linux-s390x/0.14.27: 1050 | resolution: {integrity: sha512-CD/D4tj0U4UQjELkdNlZhQ8nDHU5rBn6NGp47Hiz0Y7/akAY5i0oGadhEIg0WCY/HYVXFb3CsSPPwaKcTOW3bg==} 1051 | engines: {node: '>=12'} 1052 | cpu: [s390x] 1053 | os: [linux] 1054 | requiresBuild: true 1055 | dev: true 1056 | optional: true 1057 | 1058 | /esbuild-netbsd-64/0.14.27: 1059 | resolution: {integrity: sha512-h3mAld69SrO1VoaMpYl3a5FNdGRE/Nqc+E8VtHOag4tyBwhCQXxtvDDOAKOUQexBGca0IuR6UayQ4ntSX5ij1Q==} 1060 | engines: {node: '>=12'} 1061 | cpu: [x64] 1062 | os: [netbsd] 1063 | requiresBuild: true 1064 | dev: true 1065 | optional: true 1066 | 1067 | /esbuild-openbsd-64/0.14.27: 1068 | resolution: {integrity: sha512-xwSje6qIZaDHXWoPpIgvL+7fC6WeubHHv18tusLYMwL+Z6bEa4Pbfs5IWDtQdHkArtfxEkIZz77944z8MgDxGw==} 1069 | engines: {node: '>=12'} 1070 | cpu: [x64] 1071 | os: [openbsd] 1072 | requiresBuild: true 1073 | dev: true 1074 | optional: true 1075 | 1076 | /esbuild-sunos-64/0.14.27: 1077 | resolution: {integrity: sha512-/nBVpWIDjYiyMhuqIqbXXsxBc58cBVH9uztAOIfWShStxq9BNBik92oPQPJ57nzWXRNKQUEFWr4Q98utDWz7jg==} 1078 | engines: {node: '>=12'} 1079 | cpu: [x64] 1080 | os: [sunos] 1081 | requiresBuild: true 1082 | dev: true 1083 | optional: true 1084 | 1085 | /esbuild-windows-32/0.14.27: 1086 | resolution: {integrity: sha512-Q9/zEjhZJ4trtWhFWIZvS/7RUzzi8rvkoaS9oiizkHTTKd8UxFwn/Mm2OywsAfYymgUYm8+y2b+BKTNEFxUekw==} 1087 | engines: {node: '>=12'} 1088 | cpu: [ia32] 1089 | os: [win32] 1090 | requiresBuild: true 1091 | dev: true 1092 | optional: true 1093 | 1094 | /esbuild-windows-64/0.14.27: 1095 | resolution: {integrity: sha512-b3y3vTSl5aEhWHK66ngtiS/c6byLf6y/ZBvODH1YkBM+MGtVL6jN38FdHUsZasCz9gFwYs/lJMVY9u7GL6wfYg==} 1096 | engines: {node: '>=12'} 1097 | cpu: [x64] 1098 | os: [win32] 1099 | requiresBuild: true 1100 | dev: true 1101 | optional: true 1102 | 1103 | /esbuild-windows-arm64/0.14.27: 1104 | resolution: {integrity: sha512-I/reTxr6TFMcR5qbIkwRGvldMIaiBu2+MP0LlD7sOlNXrfqIl9uNjsuxFPGEG4IRomjfQ5q8WT+xlF/ySVkqKg==} 1105 | engines: {node: '>=12'} 1106 | cpu: [arm64] 1107 | os: [win32] 1108 | requiresBuild: true 1109 | dev: true 1110 | optional: true 1111 | 1112 | /esbuild/0.14.27: 1113 | resolution: {integrity: sha512-MZQt5SywZS3hA9fXnMhR22dv0oPGh6QtjJRIYbgL1AeqAoQZE+Qn5ppGYQAoHv/vq827flj4tIJ79Mrdiwk46Q==} 1114 | engines: {node: '>=12'} 1115 | hasBin: true 1116 | requiresBuild: true 1117 | optionalDependencies: 1118 | esbuild-android-64: 0.14.27 1119 | esbuild-android-arm64: 0.14.27 1120 | esbuild-darwin-64: 0.14.27 1121 | esbuild-darwin-arm64: 0.14.27 1122 | esbuild-freebsd-64: 0.14.27 1123 | esbuild-freebsd-arm64: 0.14.27 1124 | esbuild-linux-32: 0.14.27 1125 | esbuild-linux-64: 0.14.27 1126 | esbuild-linux-arm: 0.14.27 1127 | esbuild-linux-arm64: 0.14.27 1128 | esbuild-linux-mips64le: 0.14.27 1129 | esbuild-linux-ppc64le: 0.14.27 1130 | esbuild-linux-riscv64: 0.14.27 1131 | esbuild-linux-s390x: 0.14.27 1132 | esbuild-netbsd-64: 0.14.27 1133 | esbuild-openbsd-64: 0.14.27 1134 | esbuild-sunos-64: 0.14.27 1135 | esbuild-windows-32: 0.14.27 1136 | esbuild-windows-64: 0.14.27 1137 | esbuild-windows-arm64: 0.14.27 1138 | dev: true 1139 | 1140 | /escalade/3.1.1: 1141 | resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} 1142 | engines: {node: '>=6'} 1143 | dev: true 1144 | 1145 | /escape-string-regexp/1.0.5: 1146 | resolution: {integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=} 1147 | engines: {node: '>=0.8.0'} 1148 | 1149 | /escape-string-regexp/4.0.0: 1150 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 1151 | engines: {node: '>=10'} 1152 | dev: true 1153 | 1154 | /eslint-config-prettier/8.3.0_eslint@8.7.0: 1155 | resolution: {integrity: sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==} 1156 | hasBin: true 1157 | peerDependencies: 1158 | eslint: '>=7.0.0' 1159 | dependencies: 1160 | eslint: 8.7.0 1161 | dev: true 1162 | 1163 | /eslint-config-xo/0.39.0_eslint@8.7.0: 1164 | resolution: {integrity: sha512-QX+ZnQgzy/UtgF8dksIiIBzpYoEKmiL0CmZ8O0Gnby7rGXg8Cny1CXirmHp1zKYIpO7BuTmtWj8eUYOsGr0IGQ==} 1165 | engines: {node: '>=10'} 1166 | peerDependencies: 1167 | eslint: '>=7.20.0' 1168 | dependencies: 1169 | confusing-browser-globals: 1.0.10 1170 | eslint: 8.7.0 1171 | dev: true 1172 | 1173 | /eslint-plugin-jsdoc/37.6.3_eslint@8.7.0: 1174 | resolution: {integrity: sha512-Ysd1ZK4kL7DjjRJtWzb6Z7YANu7ndalu5PQBhOn07SlpKQ/+8JXvdtQ6yyADOO8w9xW5ZEEzuGY3KWhtk4CRYA==} 1175 | engines: {node: ^12 || ^14 || ^16 || ^17} 1176 | peerDependencies: 1177 | eslint: ^7.0.0 || ^8.0.0 1178 | dependencies: 1179 | '@es-joy/jsdoccomment': 0.17.0 1180 | comment-parser: 1.3.0 1181 | debug: 4.3.3 1182 | escape-string-regexp: 4.0.0 1183 | eslint: 8.7.0 1184 | esquery: 1.4.0 1185 | regextras: 0.8.0 1186 | semver: 7.3.5 1187 | spdx-expression-parse: 3.0.1 1188 | transitivePeerDependencies: 1189 | - supports-color 1190 | dev: true 1191 | 1192 | /eslint-plugin-prettier/4.0.0_izqfdfjs4tb3bkpfxntcht7n6y: 1193 | resolution: {integrity: sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==} 1194 | engines: {node: '>=6.0.0'} 1195 | peerDependencies: 1196 | eslint: '>=7.28.0' 1197 | eslint-config-prettier: '*' 1198 | prettier: '>=2.0.0' 1199 | peerDependenciesMeta: 1200 | eslint-config-prettier: 1201 | optional: true 1202 | dependencies: 1203 | eslint: 8.7.0 1204 | eslint-config-prettier: 8.3.0_eslint@8.7.0 1205 | prettier: 2.5.1 1206 | prettier-linter-helpers: 1.0.0 1207 | dev: true 1208 | 1209 | /eslint-scope/5.1.1: 1210 | resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} 1211 | engines: {node: '>=8.0.0'} 1212 | dependencies: 1213 | esrecurse: 4.3.0 1214 | estraverse: 4.3.0 1215 | dev: true 1216 | 1217 | /eslint-scope/7.1.0: 1218 | resolution: {integrity: sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==} 1219 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1220 | dependencies: 1221 | esrecurse: 4.3.0 1222 | estraverse: 5.3.0 1223 | dev: true 1224 | 1225 | /eslint-utils/3.0.0_eslint@8.7.0: 1226 | resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} 1227 | engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} 1228 | peerDependencies: 1229 | eslint: '>=5' 1230 | dependencies: 1231 | eslint: 8.7.0 1232 | eslint-visitor-keys: 2.1.0 1233 | dev: true 1234 | 1235 | /eslint-visitor-keys/2.1.0: 1236 | resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} 1237 | engines: {node: '>=10'} 1238 | dev: true 1239 | 1240 | /eslint-visitor-keys/3.2.0: 1241 | resolution: {integrity: sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==} 1242 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1243 | dev: true 1244 | 1245 | /eslint/8.7.0: 1246 | resolution: {integrity: sha512-ifHYzkBGrzS2iDU7KjhCAVMGCvF6M3Xfs8X8b37cgrUlDt6bWRTpRh6T/gtSXv1HJ/BUGgmjvNvOEGu85Iif7w==} 1247 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1248 | hasBin: true 1249 | dependencies: 1250 | '@eslint/eslintrc': 1.0.5 1251 | '@humanwhocodes/config-array': 0.9.2 1252 | ajv: 6.12.6 1253 | chalk: 4.1.2 1254 | cross-spawn: 7.0.3 1255 | debug: 4.3.3 1256 | doctrine: 3.0.0 1257 | escape-string-regexp: 4.0.0 1258 | eslint-scope: 7.1.0 1259 | eslint-utils: 3.0.0_eslint@8.7.0 1260 | eslint-visitor-keys: 3.2.0 1261 | espree: 9.3.0 1262 | esquery: 1.4.0 1263 | esutils: 2.0.3 1264 | fast-deep-equal: 3.1.3 1265 | file-entry-cache: 6.0.1 1266 | functional-red-black-tree: 1.0.1 1267 | glob-parent: 6.0.2 1268 | globals: 13.12.0 1269 | ignore: 5.2.0 1270 | import-fresh: 3.3.0 1271 | imurmurhash: 0.1.4 1272 | is-glob: 4.0.3 1273 | js-yaml: 4.1.0 1274 | json-stable-stringify-without-jsonify: 1.0.1 1275 | levn: 0.4.1 1276 | lodash.merge: 4.6.2 1277 | minimatch: 3.0.4 1278 | natural-compare: 1.4.0 1279 | optionator: 0.9.1 1280 | regexpp: 3.2.0 1281 | strip-ansi: 6.0.1 1282 | strip-json-comments: 3.1.1 1283 | text-table: 0.2.0 1284 | v8-compile-cache: 2.3.0 1285 | transitivePeerDependencies: 1286 | - supports-color 1287 | dev: true 1288 | 1289 | /espree/9.3.0: 1290 | resolution: {integrity: sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==} 1291 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1292 | dependencies: 1293 | acorn: 8.7.0 1294 | acorn-jsx: 5.3.2_acorn@8.7.0 1295 | eslint-visitor-keys: 3.2.0 1296 | dev: true 1297 | 1298 | /esquery/1.4.0: 1299 | resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} 1300 | engines: {node: '>=0.10'} 1301 | dependencies: 1302 | estraverse: 5.3.0 1303 | dev: true 1304 | 1305 | /esrecurse/4.3.0: 1306 | resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} 1307 | engines: {node: '>=4.0'} 1308 | dependencies: 1309 | estraverse: 5.3.0 1310 | dev: true 1311 | 1312 | /estraverse/4.3.0: 1313 | resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} 1314 | engines: {node: '>=4.0'} 1315 | dev: true 1316 | 1317 | /estraverse/5.3.0: 1318 | resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} 1319 | engines: {node: '>=4.0'} 1320 | dev: true 1321 | 1322 | /esutils/2.0.3: 1323 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 1324 | engines: {node: '>=0.10.0'} 1325 | dev: true 1326 | 1327 | /events/3.3.0: 1328 | resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} 1329 | engines: {node: '>=0.8.x'} 1330 | dev: true 1331 | 1332 | /execa/0.7.0: 1333 | resolution: {integrity: sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=} 1334 | engines: {node: '>=4'} 1335 | dependencies: 1336 | cross-spawn: 5.1.0 1337 | get-stream: 3.0.0 1338 | is-stream: 1.1.0 1339 | npm-run-path: 2.0.2 1340 | p-finally: 1.0.0 1341 | signal-exit: 3.0.7 1342 | strip-eof: 1.0.0 1343 | dev: false 1344 | 1345 | /execa/1.0.0: 1346 | resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} 1347 | engines: {node: '>=6'} 1348 | dependencies: 1349 | cross-spawn: 6.0.5 1350 | get-stream: 4.1.0 1351 | is-stream: 1.1.0 1352 | npm-run-path: 2.0.2 1353 | p-finally: 1.0.0 1354 | signal-exit: 3.0.7 1355 | strip-eof: 1.0.0 1356 | dev: false 1357 | 1358 | /execa/4.1.0: 1359 | resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} 1360 | engines: {node: '>=10'} 1361 | dependencies: 1362 | cross-spawn: 7.0.3 1363 | get-stream: 5.2.0 1364 | human-signals: 1.1.1 1365 | is-stream: 2.0.1 1366 | merge-stream: 2.0.0 1367 | npm-run-path: 4.0.1 1368 | onetime: 5.1.2 1369 | signal-exit: 3.0.7 1370 | strip-final-newline: 2.0.0 1371 | dev: false 1372 | 1373 | /executable/4.1.1: 1374 | resolution: {integrity: sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==} 1375 | engines: {node: '>=4'} 1376 | dependencies: 1377 | pify: 2.3.0 1378 | dev: false 1379 | 1380 | /ext-list/2.2.2: 1381 | resolution: {integrity: sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==} 1382 | engines: {node: '>=0.10.0'} 1383 | dependencies: 1384 | mime-db: 1.52.0 1385 | dev: false 1386 | 1387 | /ext-name/5.0.0: 1388 | resolution: {integrity: sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==} 1389 | engines: {node: '>=4'} 1390 | dependencies: 1391 | ext-list: 2.2.2 1392 | sort-keys-length: 1.0.1 1393 | dev: false 1394 | 1395 | /external-editor/3.1.0: 1396 | resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} 1397 | engines: {node: '>=4'} 1398 | dependencies: 1399 | chardet: 0.7.0 1400 | iconv-lite: 0.4.24 1401 | tmp: 0.0.33 1402 | dev: true 1403 | 1404 | /extract-zip/2.0.1: 1405 | resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} 1406 | engines: {node: '>= 10.17.0'} 1407 | hasBin: true 1408 | dependencies: 1409 | debug: 4.3.3 1410 | get-stream: 5.2.0 1411 | yauzl: 2.10.0 1412 | optionalDependencies: 1413 | '@types/yauzl': 2.9.2 1414 | transitivePeerDependencies: 1415 | - supports-color 1416 | dev: false 1417 | 1418 | /fast-deep-equal/3.1.3: 1419 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 1420 | dev: true 1421 | 1422 | /fast-diff/1.2.0: 1423 | resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} 1424 | dev: true 1425 | 1426 | /fast-glob/3.2.11: 1427 | resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==} 1428 | engines: {node: '>=8.6.0'} 1429 | dependencies: 1430 | '@nodelib/fs.stat': 2.0.5 1431 | '@nodelib/fs.walk': 1.2.8 1432 | glob-parent: 5.1.2 1433 | merge2: 1.4.1 1434 | micromatch: 4.0.4 1435 | 1436 | /fast-json-stable-stringify/2.1.0: 1437 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 1438 | dev: true 1439 | 1440 | /fast-levenshtein/2.0.6: 1441 | resolution: {integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=} 1442 | dev: true 1443 | 1444 | /fastq/1.13.0: 1445 | resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} 1446 | dependencies: 1447 | reusify: 1.0.4 1448 | 1449 | /fd-slicer/1.1.0: 1450 | resolution: {integrity: sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=} 1451 | dependencies: 1452 | pend: 1.2.0 1453 | dev: false 1454 | 1455 | /figures/3.2.0: 1456 | resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} 1457 | engines: {node: '>=8'} 1458 | dependencies: 1459 | escape-string-regexp: 1.0.5 1460 | dev: true 1461 | 1462 | /file-entry-cache/6.0.1: 1463 | resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} 1464 | engines: {node: ^10.12.0 || >=12.0.0} 1465 | dependencies: 1466 | flat-cache: 3.0.4 1467 | dev: true 1468 | 1469 | /file-type/12.4.2: 1470 | resolution: {integrity: sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg==} 1471 | engines: {node: '>=8'} 1472 | dev: false 1473 | 1474 | /file-type/3.9.0: 1475 | resolution: {integrity: sha1-JXoHg4TR24CHvESdEH1SpSZyuek=} 1476 | engines: {node: '>=0.10.0'} 1477 | dev: false 1478 | 1479 | /file-type/4.4.0: 1480 | resolution: {integrity: sha1-G2AOX8ofvcboDApwxxyNul95BsU=} 1481 | engines: {node: '>=4'} 1482 | dev: false 1483 | 1484 | /file-type/5.2.0: 1485 | resolution: {integrity: sha1-LdvqfHP/42No365J3DOMBYwritY=} 1486 | engines: {node: '>=4'} 1487 | dev: false 1488 | 1489 | /file-type/6.2.0: 1490 | resolution: {integrity: sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==} 1491 | engines: {node: '>=4'} 1492 | dev: false 1493 | 1494 | /file-type/8.1.0: 1495 | resolution: {integrity: sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==} 1496 | engines: {node: '>=6'} 1497 | dev: false 1498 | 1499 | /filename-reserved-regex/2.0.0: 1500 | resolution: {integrity: sha1-q/c9+rc10EVECr/qLZHzieu/oik=} 1501 | engines: {node: '>=4'} 1502 | dev: false 1503 | 1504 | /filenamify/2.1.0: 1505 | resolution: {integrity: sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==} 1506 | engines: {node: '>=4'} 1507 | dependencies: 1508 | filename-reserved-regex: 2.0.0 1509 | strip-outer: 1.0.1 1510 | trim-repeated: 1.0.0 1511 | dev: false 1512 | 1513 | /fill-range/7.0.1: 1514 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} 1515 | engines: {node: '>=8'} 1516 | dependencies: 1517 | to-regex-range: 5.0.1 1518 | 1519 | /find-up/4.1.0: 1520 | resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} 1521 | engines: {node: '>=8'} 1522 | dependencies: 1523 | locate-path: 5.0.0 1524 | path-exists: 4.0.0 1525 | dev: false 1526 | 1527 | /find-versions/3.2.0: 1528 | resolution: {integrity: sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==} 1529 | engines: {node: '>=6'} 1530 | dependencies: 1531 | semver-regex: 2.0.0 1532 | dev: false 1533 | 1534 | /flat-cache/3.0.4: 1535 | resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} 1536 | engines: {node: ^10.12.0 || >=12.0.0} 1537 | dependencies: 1538 | flatted: 3.2.4 1539 | rimraf: 3.0.2 1540 | dev: true 1541 | 1542 | /flatted/3.2.4: 1543 | resolution: {integrity: sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==} 1544 | dev: true 1545 | 1546 | /from2/2.3.0: 1547 | resolution: {integrity: sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=} 1548 | dependencies: 1549 | inherits: 2.0.4 1550 | readable-stream: 2.3.7 1551 | dev: false 1552 | 1553 | /fs-constants/1.0.0: 1554 | resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} 1555 | dev: false 1556 | 1557 | /fs.realpath/1.0.0: 1558 | resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=} 1559 | 1560 | /fsevents/2.3.2: 1561 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} 1562 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 1563 | os: [darwin] 1564 | requiresBuild: true 1565 | dev: true 1566 | optional: true 1567 | 1568 | /function-bind/1.1.1: 1569 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} 1570 | dev: true 1571 | 1572 | /functional-red-black-tree/1.0.1: 1573 | resolution: {integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=} 1574 | dev: true 1575 | 1576 | /get-caller-file/2.0.5: 1577 | resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} 1578 | engines: {node: 6.* || 8.* || >= 10.*} 1579 | dev: true 1580 | 1581 | /get-func-name/2.0.0: 1582 | resolution: {integrity: sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=} 1583 | dev: true 1584 | 1585 | /get-proxy/2.1.0: 1586 | resolution: {integrity: sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==} 1587 | engines: {node: '>=4'} 1588 | dependencies: 1589 | npm-conf: 1.1.3 1590 | dev: false 1591 | 1592 | /get-stream/2.3.1: 1593 | resolution: {integrity: sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=} 1594 | engines: {node: '>=0.10.0'} 1595 | dependencies: 1596 | object-assign: 4.1.1 1597 | pinkie-promise: 2.0.1 1598 | dev: false 1599 | 1600 | /get-stream/3.0.0: 1601 | resolution: {integrity: sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=} 1602 | engines: {node: '>=4'} 1603 | dev: false 1604 | 1605 | /get-stream/4.1.0: 1606 | resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} 1607 | engines: {node: '>=6'} 1608 | dependencies: 1609 | pump: 3.0.0 1610 | dev: false 1611 | 1612 | /get-stream/5.2.0: 1613 | resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} 1614 | engines: {node: '>=8'} 1615 | dependencies: 1616 | pump: 3.0.0 1617 | dev: false 1618 | 1619 | /glob-parent/5.1.2: 1620 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 1621 | engines: {node: '>= 6'} 1622 | dependencies: 1623 | is-glob: 4.0.3 1624 | 1625 | /glob-parent/6.0.2: 1626 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 1627 | engines: {node: '>=10.13.0'} 1628 | dependencies: 1629 | is-glob: 4.0.3 1630 | dev: true 1631 | 1632 | /glob/7.2.0: 1633 | resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} 1634 | dependencies: 1635 | fs.realpath: 1.0.0 1636 | inflight: 1.0.6 1637 | inherits: 2.0.4 1638 | minimatch: 3.0.4 1639 | once: 1.4.0 1640 | path-is-absolute: 1.0.1 1641 | 1642 | /globals/13.12.0: 1643 | resolution: {integrity: sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==} 1644 | engines: {node: '>=8'} 1645 | dependencies: 1646 | type-fest: 0.20.2 1647 | dev: true 1648 | 1649 | /globby/10.0.2: 1650 | resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} 1651 | engines: {node: '>=8'} 1652 | dependencies: 1653 | '@types/glob': 7.2.0 1654 | array-union: 2.1.0 1655 | dir-glob: 3.0.1 1656 | fast-glob: 3.2.11 1657 | glob: 7.2.0 1658 | ignore: 5.2.0 1659 | merge2: 1.4.1 1660 | slash: 3.0.0 1661 | dev: false 1662 | 1663 | /globby/11.1.0: 1664 | resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} 1665 | engines: {node: '>=10'} 1666 | dependencies: 1667 | array-union: 2.1.0 1668 | dir-glob: 3.0.1 1669 | fast-glob: 3.2.11 1670 | ignore: 5.2.0 1671 | merge2: 1.4.1 1672 | slash: 3.0.0 1673 | dev: true 1674 | 1675 | /got/7.1.0: 1676 | resolution: {integrity: sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==} 1677 | engines: {node: '>=4'} 1678 | dependencies: 1679 | '@types/keyv': 3.1.4 1680 | '@types/responselike': 1.0.0 1681 | decompress-response: 3.3.0 1682 | duplexer3: 0.1.4 1683 | get-stream: 3.0.0 1684 | is-plain-obj: 1.1.0 1685 | is-retry-allowed: 1.2.0 1686 | is-stream: 1.1.0 1687 | isurl: 1.0.0 1688 | lowercase-keys: 1.0.1 1689 | p-cancelable: 0.3.0 1690 | p-timeout: 1.2.1 1691 | safe-buffer: 5.2.1 1692 | timed-out: 4.0.1 1693 | url-parse-lax: 1.0.0 1694 | url-to-options: 1.0.1 1695 | dev: false 1696 | 1697 | /got/8.3.2: 1698 | resolution: {integrity: sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==} 1699 | engines: {node: '>=4'} 1700 | dependencies: 1701 | '@sindresorhus/is': 0.7.0 1702 | '@types/keyv': 3.1.4 1703 | '@types/responselike': 1.0.0 1704 | cacheable-request: 2.1.4 1705 | decompress-response: 3.3.0 1706 | duplexer3: 0.1.4 1707 | get-stream: 3.0.0 1708 | into-stream: 3.1.0 1709 | is-retry-allowed: 1.2.0 1710 | isurl: 1.0.0 1711 | lowercase-keys: 1.0.1 1712 | mimic-response: 1.0.1 1713 | p-cancelable: 0.4.1 1714 | p-timeout: 2.0.1 1715 | pify: 3.0.0 1716 | safe-buffer: 5.2.1 1717 | timed-out: 4.0.1 1718 | url-parse-lax: 3.0.0 1719 | url-to-options: 1.0.1 1720 | dev: false 1721 | 1722 | /graceful-fs/4.2.9: 1723 | resolution: {integrity: sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==} 1724 | dev: false 1725 | 1726 | /graphql/16.3.0: 1727 | resolution: {integrity: sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A==} 1728 | engines: {node: ^12.22.0 || ^14.16.0 || >=16.0.0} 1729 | dev: true 1730 | 1731 | /has-flag/4.0.0: 1732 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 1733 | engines: {node: '>=8'} 1734 | dev: true 1735 | 1736 | /has-symbol-support-x/1.4.2: 1737 | resolution: {integrity: sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==} 1738 | dev: false 1739 | 1740 | /has-to-string-tag-x/1.4.1: 1741 | resolution: {integrity: sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==} 1742 | dependencies: 1743 | has-symbol-support-x: 1.4.2 1744 | dev: false 1745 | 1746 | /has/1.0.3: 1747 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} 1748 | engines: {node: '>= 0.4.0'} 1749 | dependencies: 1750 | function-bind: 1.1.1 1751 | dev: true 1752 | 1753 | /headers-polyfill/3.0.4: 1754 | resolution: {integrity: sha512-I1DOM1EdWYntdrnCvqQtcKwSSuiTzoqOExy4v1mdcFixFZABlWP4IPHdmoLtPda0abMHqDOY4H9svhQ10DFR4w==} 1755 | dev: true 1756 | 1757 | /http-cache-semantics/3.8.1: 1758 | resolution: {integrity: sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==} 1759 | dev: false 1760 | 1761 | /https-proxy-agent/5.0.0: 1762 | resolution: {integrity: sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==} 1763 | engines: {node: '>= 6'} 1764 | dependencies: 1765 | agent-base: 6.0.2 1766 | debug: 4.3.3 1767 | transitivePeerDependencies: 1768 | - supports-color 1769 | dev: false 1770 | 1771 | /human-signals/1.1.1: 1772 | resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} 1773 | engines: {node: '>=8.12.0'} 1774 | dev: false 1775 | 1776 | /iconv-lite/0.4.24: 1777 | resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} 1778 | engines: {node: '>=0.10.0'} 1779 | dependencies: 1780 | safer-buffer: 2.1.2 1781 | dev: true 1782 | 1783 | /ieee754/1.2.1: 1784 | resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} 1785 | 1786 | /ignore/4.0.6: 1787 | resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} 1788 | engines: {node: '>= 4'} 1789 | dev: true 1790 | 1791 | /ignore/5.2.0: 1792 | resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} 1793 | engines: {node: '>= 4'} 1794 | 1795 | /imagemin-pngquant/9.0.2: 1796 | resolution: {integrity: sha512-cj//bKo8+Frd/DM8l6Pg9pws1pnDUjgb7ae++sUX1kUVdv2nrngPykhiUOgFeE0LGY/LmUbCf4egCHC4YUcZSg==} 1797 | engines: {node: '>=10'} 1798 | dependencies: 1799 | execa: 4.1.0 1800 | is-png: 2.0.0 1801 | is-stream: 2.0.1 1802 | ow: 0.17.0 1803 | pngquant-bin: 6.0.1 1804 | dev: false 1805 | 1806 | /imagemin/7.0.1: 1807 | resolution: {integrity: sha512-33AmZ+xjZhg2JMCe+vDf6a9mzWukE7l+wAtesjE7KyteqqKjzxv7aVQeWnul1Ve26mWvEQqyPwl0OctNBfSR9w==} 1808 | engines: {node: '>=8'} 1809 | dependencies: 1810 | file-type: 12.4.2 1811 | globby: 10.0.2 1812 | graceful-fs: 4.2.9 1813 | junk: 3.1.0 1814 | make-dir: 3.1.0 1815 | p-pipe: 3.1.0 1816 | replace-ext: 1.0.1 1817 | dev: false 1818 | 1819 | /import-fresh/3.3.0: 1820 | resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} 1821 | engines: {node: '>=6'} 1822 | dependencies: 1823 | parent-module: 1.0.1 1824 | resolve-from: 4.0.0 1825 | dev: true 1826 | 1827 | /import-lazy/3.1.0: 1828 | resolution: {integrity: sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ==} 1829 | engines: {node: '>=6'} 1830 | dev: false 1831 | 1832 | /imurmurhash/0.1.4: 1833 | resolution: {integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o=} 1834 | engines: {node: '>=0.8.19'} 1835 | dev: true 1836 | 1837 | /inflight/1.0.6: 1838 | resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=} 1839 | dependencies: 1840 | once: 1.4.0 1841 | wrappy: 1.0.2 1842 | 1843 | /inherits/2.0.4: 1844 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 1845 | 1846 | /ini/1.3.8: 1847 | resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} 1848 | dev: false 1849 | 1850 | /inquirer/8.2.1: 1851 | resolution: {integrity: sha512-pxhBaw9cyTFMjwKtkjePWDhvwzvrNGAw7En4hottzlPvz80GZaMZthdDU35aA6/f5FRZf3uhE057q8w1DE3V2g==} 1852 | engines: {node: '>=12.0.0'} 1853 | dependencies: 1854 | ansi-escapes: 4.3.2 1855 | chalk: 4.1.2 1856 | cli-cursor: 3.1.0 1857 | cli-width: 3.0.0 1858 | external-editor: 3.1.0 1859 | figures: 3.2.0 1860 | lodash: 4.17.21 1861 | mute-stream: 0.0.8 1862 | ora: 5.4.1 1863 | run-async: 2.4.1 1864 | rxjs: 7.5.5 1865 | string-width: 4.2.3 1866 | strip-ansi: 6.0.1 1867 | through: 2.3.8 1868 | dev: true 1869 | 1870 | /into-stream/3.1.0: 1871 | resolution: {integrity: sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=} 1872 | engines: {node: '>=4'} 1873 | dependencies: 1874 | from2: 2.3.0 1875 | p-is-promise: 1.1.0 1876 | dev: false 1877 | 1878 | /is-binary-path/2.1.0: 1879 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 1880 | engines: {node: '>=8'} 1881 | dependencies: 1882 | binary-extensions: 2.2.0 1883 | dev: true 1884 | 1885 | /is-core-module/2.8.1: 1886 | resolution: {integrity: sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==} 1887 | dependencies: 1888 | has: 1.0.3 1889 | dev: true 1890 | 1891 | /is-extglob/2.1.1: 1892 | resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=} 1893 | engines: {node: '>=0.10.0'} 1894 | 1895 | /is-fullwidth-code-point/3.0.0: 1896 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 1897 | engines: {node: '>=8'} 1898 | dev: true 1899 | 1900 | /is-glob/4.0.3: 1901 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 1902 | engines: {node: '>=0.10.0'} 1903 | dependencies: 1904 | is-extglob: 2.1.1 1905 | 1906 | /is-interactive/1.0.0: 1907 | resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} 1908 | engines: {node: '>=8'} 1909 | dev: true 1910 | 1911 | /is-natural-number/4.0.1: 1912 | resolution: {integrity: sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=} 1913 | dev: false 1914 | 1915 | /is-node-process/1.0.1: 1916 | resolution: {integrity: sha512-5IcdXuf++TTNt3oGl9EBdkvndXA8gmc4bz/Y+mdEpWh3Mcn/+kOw6hI7LD5CocqJWMzeb0I0ClndRVNdEPuJXQ==} 1917 | dev: true 1918 | 1919 | /is-number/7.0.0: 1920 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 1921 | engines: {node: '>=0.12.0'} 1922 | 1923 | /is-object/1.0.2: 1924 | resolution: {integrity: sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==} 1925 | dev: false 1926 | 1927 | /is-plain-obj/1.1.0: 1928 | resolution: {integrity: sha1-caUMhCnfync8kqOQpKA7OfzVHT4=} 1929 | engines: {node: '>=0.10.0'} 1930 | dev: false 1931 | 1932 | /is-png/2.0.0: 1933 | resolution: {integrity: sha512-4KPGizaVGj2LK7xwJIz8o5B2ubu1D/vcQsgOGFEDlpcvgZHto4gBnyd0ig7Ws+67ixmwKoNmu0hYnpo6AaKb5g==} 1934 | engines: {node: '>=8'} 1935 | dev: false 1936 | 1937 | /is-retry-allowed/1.2.0: 1938 | resolution: {integrity: sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==} 1939 | engines: {node: '>=0.10.0'} 1940 | dev: false 1941 | 1942 | /is-stream/1.1.0: 1943 | resolution: {integrity: sha1-EtSj3U5o4Lec6428hBc66A2RykQ=} 1944 | engines: {node: '>=0.10.0'} 1945 | dev: false 1946 | 1947 | /is-stream/2.0.1: 1948 | resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} 1949 | engines: {node: '>=8'} 1950 | dev: false 1951 | 1952 | /is-unicode-supported/0.1.0: 1953 | resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} 1954 | engines: {node: '>=10'} 1955 | dev: true 1956 | 1957 | /isarray/1.0.0: 1958 | resolution: {integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=} 1959 | dev: false 1960 | 1961 | /isexe/2.0.0: 1962 | resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} 1963 | 1964 | /isomorphic-unfetch/3.1.0: 1965 | resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==} 1966 | dependencies: 1967 | node-fetch: 2.6.1 1968 | unfetch: 4.2.0 1969 | dev: false 1970 | 1971 | /isurl/1.0.0: 1972 | resolution: {integrity: sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==} 1973 | engines: {node: '>= 4'} 1974 | dependencies: 1975 | has-to-string-tag-x: 1.4.1 1976 | is-object: 1.0.2 1977 | dev: false 1978 | 1979 | /js-levenshtein/1.1.6: 1980 | resolution: {integrity: sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==} 1981 | engines: {node: '>=0.10.0'} 1982 | dev: true 1983 | 1984 | /js-yaml/4.1.0: 1985 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 1986 | hasBin: true 1987 | dependencies: 1988 | argparse: 2.0.1 1989 | dev: true 1990 | 1991 | /jsdoc-type-pratt-parser/2.2.2: 1992 | resolution: {integrity: sha512-zRokSWcPLSWkoNzsWn9pq7YYSwDhKyEe+cJYT2qaPqLOOJb5sFSi46BPj81vP+e8chvCNdQL9RG86Bi9EI6MDw==} 1993 | engines: {node: '>=12.0.0'} 1994 | dev: true 1995 | 1996 | /json-buffer/3.0.0: 1997 | resolution: {integrity: sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=} 1998 | dev: false 1999 | 2000 | /json-schema-traverse/0.4.1: 2001 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 2002 | dev: true 2003 | 2004 | /json-stable-stringify-without-jsonify/1.0.1: 2005 | resolution: {integrity: sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=} 2006 | dev: true 2007 | 2008 | /junk/3.1.0: 2009 | resolution: {integrity: sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==} 2010 | engines: {node: '>=8'} 2011 | dev: false 2012 | 2013 | /keyv/3.0.0: 2014 | resolution: {integrity: sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==} 2015 | dependencies: 2016 | json-buffer: 3.0.0 2017 | dev: false 2018 | 2019 | /lambdafs/2.1.1: 2020 | resolution: {integrity: sha512-x5k8JcoJWkWLvCVBzrl4pzvkEHSgSBqFjg3Dpsc4AcTMq7oUMym4cL/gRTZ6VM4mUMY+M0dIbQ+V1c1tsqqanQ==} 2021 | engines: {node: '>= 10.16'} 2022 | hasBin: true 2023 | dev: false 2024 | bundledDependencies: 2025 | - tar-fs 2026 | 2027 | /levn/0.4.1: 2028 | resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 2029 | engines: {node: '>= 0.8.0'} 2030 | dependencies: 2031 | prelude-ls: 1.2.1 2032 | type-check: 0.4.0 2033 | dev: true 2034 | 2035 | /local-pkg/0.4.1: 2036 | resolution: {integrity: sha512-lL87ytIGP2FU5PWwNDo0w3WhIo2gopIAxPg9RxDYF7m4rr5ahuZxP22xnJHIvaLTe4Z9P6uKKY2UHiwyB4pcrw==} 2037 | engines: {node: '>=14'} 2038 | dev: true 2039 | 2040 | /locate-path/5.0.0: 2041 | resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} 2042 | engines: {node: '>=8'} 2043 | dependencies: 2044 | p-locate: 4.1.0 2045 | dev: false 2046 | 2047 | /lodash.merge/4.6.2: 2048 | resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} 2049 | dev: true 2050 | 2051 | /lodash/4.17.21: 2052 | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} 2053 | dev: true 2054 | 2055 | /log-symbols/4.1.0: 2056 | resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} 2057 | engines: {node: '>=10'} 2058 | dependencies: 2059 | chalk: 4.1.2 2060 | is-unicode-supported: 0.1.0 2061 | dev: true 2062 | 2063 | /loupe/2.3.4: 2064 | resolution: {integrity: sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==} 2065 | dependencies: 2066 | get-func-name: 2.0.0 2067 | dev: true 2068 | 2069 | /lowercase-keys/1.0.0: 2070 | resolution: {integrity: sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=} 2071 | engines: {node: '>=0.10.0'} 2072 | dev: false 2073 | 2074 | /lowercase-keys/1.0.1: 2075 | resolution: {integrity: sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==} 2076 | engines: {node: '>=0.10.0'} 2077 | dev: false 2078 | 2079 | /lru-cache/4.1.5: 2080 | resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} 2081 | dependencies: 2082 | pseudomap: 1.0.2 2083 | yallist: 2.1.2 2084 | dev: false 2085 | 2086 | /lru-cache/6.0.0: 2087 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 2088 | engines: {node: '>=10'} 2089 | dependencies: 2090 | yallist: 4.0.0 2091 | dev: true 2092 | 2093 | /make-dir/1.3.0: 2094 | resolution: {integrity: sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==} 2095 | engines: {node: '>=4'} 2096 | dependencies: 2097 | pify: 3.0.0 2098 | dev: false 2099 | 2100 | /make-dir/3.1.0: 2101 | resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} 2102 | engines: {node: '>=8'} 2103 | dependencies: 2104 | semver: 6.3.0 2105 | dev: false 2106 | 2107 | /make-error/1.3.6: 2108 | resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} 2109 | dev: true 2110 | 2111 | /markdown-wasm/1.2.0: 2112 | resolution: {integrity: sha512-S12OTkyXCkOgI1n1rZY9cg4bK/PGu80Emjpvwp8BEjwCxhPV3yddF0U6+QhCitdBsI1tzWcoeahmW7k0Pq81OA==} 2113 | dev: false 2114 | 2115 | /merge-stream/2.0.0: 2116 | resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} 2117 | dev: false 2118 | 2119 | /merge2/1.4.1: 2120 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 2121 | engines: {node: '>= 8'} 2122 | 2123 | /micromatch/4.0.4: 2124 | resolution: {integrity: sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==} 2125 | engines: {node: '>=8.6'} 2126 | dependencies: 2127 | braces: 3.0.2 2128 | picomatch: 2.3.1 2129 | 2130 | /mime-db/1.52.0: 2131 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} 2132 | engines: {node: '>= 0.6'} 2133 | dev: false 2134 | 2135 | /mimic-fn/2.1.0: 2136 | resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} 2137 | engines: {node: '>=6'} 2138 | 2139 | /mimic-response/1.0.1: 2140 | resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} 2141 | engines: {node: '>=4'} 2142 | dev: false 2143 | 2144 | /minimatch/3.0.4: 2145 | resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==} 2146 | dependencies: 2147 | brace-expansion: 1.1.11 2148 | 2149 | /minimist/1.2.5: 2150 | resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==} 2151 | dev: false 2152 | 2153 | /mkdirp/0.5.5: 2154 | resolution: {integrity: sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==} 2155 | hasBin: true 2156 | dependencies: 2157 | minimist: 1.2.5 2158 | dev: false 2159 | 2160 | /ms/2.1.2: 2161 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 2162 | 2163 | /msw/0.39.2: 2164 | resolution: {integrity: sha512-ju/HpqQpE4/qCxZ23t5Gaau0KREn4QuFzdG28nP1EpidMrymMJuIvNd32+2uGTGG031PMwrC41YW7vCxHOwyHA==} 2165 | engines: {node: '>=14'} 2166 | hasBin: true 2167 | requiresBuild: true 2168 | dependencies: 2169 | '@mswjs/cookies': 0.2.0 2170 | '@mswjs/interceptors': 0.15.1 2171 | '@open-draft/until': 1.0.3 2172 | '@types/cookie': 0.4.1 2173 | '@types/js-levenshtein': 1.1.1 2174 | chalk: 4.1.1 2175 | chokidar: 3.5.3 2176 | cookie: 0.4.2 2177 | graphql: 16.3.0 2178 | headers-polyfill: 3.0.4 2179 | inquirer: 8.2.1 2180 | is-node-process: 1.0.1 2181 | js-levenshtein: 1.1.6 2182 | node-fetch: 2.6.7 2183 | path-to-regexp: 6.2.0 2184 | statuses: 2.0.1 2185 | strict-event-emitter: 0.2.0 2186 | type-fest: 1.4.0 2187 | yargs: 17.3.1 2188 | transitivePeerDependencies: 2189 | - encoding 2190 | - supports-color 2191 | dev: true 2192 | 2193 | /mute-stream/0.0.8: 2194 | resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} 2195 | dev: true 2196 | 2197 | /nanoid/3.3.1: 2198 | resolution: {integrity: sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==} 2199 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 2200 | hasBin: true 2201 | dev: true 2202 | 2203 | /natural-compare/1.4.0: 2204 | resolution: {integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=} 2205 | dev: true 2206 | 2207 | /nice-try/1.0.5: 2208 | resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} 2209 | dev: false 2210 | 2211 | /node-fetch/2.6.1: 2212 | resolution: {integrity: sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==} 2213 | engines: {node: 4.x || >=6.0.0} 2214 | dev: false 2215 | 2216 | /node-fetch/2.6.7: 2217 | resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} 2218 | engines: {node: 4.x || >=6.0.0} 2219 | peerDependencies: 2220 | encoding: ^0.1.0 2221 | peerDependenciesMeta: 2222 | encoding: 2223 | optional: true 2224 | dependencies: 2225 | whatwg-url: 5.0.0 2226 | dev: true 2227 | 2228 | /normalize-path/3.0.0: 2229 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 2230 | engines: {node: '>=0.10.0'} 2231 | dev: true 2232 | 2233 | /normalize-url/2.0.1: 2234 | resolution: {integrity: sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==} 2235 | engines: {node: '>=4'} 2236 | dependencies: 2237 | prepend-http: 2.0.0 2238 | query-string: 5.1.1 2239 | sort-keys: 2.0.0 2240 | dev: false 2241 | 2242 | /npm-conf/1.1.3: 2243 | resolution: {integrity: sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==} 2244 | engines: {node: '>=4'} 2245 | dependencies: 2246 | config-chain: 1.1.13 2247 | pify: 3.0.0 2248 | dev: false 2249 | 2250 | /npm-run-path/2.0.2: 2251 | resolution: {integrity: sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=} 2252 | engines: {node: '>=4'} 2253 | dependencies: 2254 | path-key: 2.0.1 2255 | dev: false 2256 | 2257 | /npm-run-path/4.0.1: 2258 | resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} 2259 | engines: {node: '>=8'} 2260 | dependencies: 2261 | path-key: 3.1.1 2262 | dev: false 2263 | 2264 | /object-assign/4.1.1: 2265 | resolution: {integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=} 2266 | engines: {node: '>=0.10.0'} 2267 | dev: false 2268 | 2269 | /once/1.4.0: 2270 | resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} 2271 | dependencies: 2272 | wrappy: 1.0.2 2273 | 2274 | /onetime/5.1.2: 2275 | resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} 2276 | engines: {node: '>=6'} 2277 | dependencies: 2278 | mimic-fn: 2.1.0 2279 | 2280 | /optionator/0.9.1: 2281 | resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} 2282 | engines: {node: '>= 0.8.0'} 2283 | dependencies: 2284 | deep-is: 0.1.4 2285 | fast-levenshtein: 2.0.6 2286 | levn: 0.4.1 2287 | prelude-ls: 1.2.1 2288 | type-check: 0.4.0 2289 | word-wrap: 1.2.3 2290 | dev: true 2291 | 2292 | /ora/5.4.1: 2293 | resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} 2294 | engines: {node: '>=10'} 2295 | dependencies: 2296 | bl: 4.1.0 2297 | chalk: 4.1.2 2298 | cli-cursor: 3.1.0 2299 | cli-spinners: 2.6.1 2300 | is-interactive: 1.0.0 2301 | is-unicode-supported: 0.1.0 2302 | log-symbols: 4.1.0 2303 | strip-ansi: 6.0.1 2304 | wcwidth: 1.0.1 2305 | dev: true 2306 | 2307 | /os-filter-obj/2.0.0: 2308 | resolution: {integrity: sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg==} 2309 | engines: {node: '>=4'} 2310 | dependencies: 2311 | arch: 2.2.0 2312 | dev: false 2313 | 2314 | /os-tmpdir/1.0.2: 2315 | resolution: {integrity: sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=} 2316 | engines: {node: '>=0.10.0'} 2317 | dev: true 2318 | 2319 | /outvariant/1.2.1: 2320 | resolution: {integrity: sha512-bcILvFkvpMXh66+Ubax/inxbKRyWTUiiFIW2DWkiS79wakrLGn3Ydy+GvukadiyfZjaL6C7YhIem4EZSM282wA==} 2321 | dev: true 2322 | 2323 | /ow/0.17.0: 2324 | resolution: {integrity: sha512-i3keDzDQP5lWIe4oODyDFey1qVrq2hXKTuTH2VpqwpYtzPiKZt2ziRI4NBQmgW40AnV5Euz17OyWweCb+bNEQA==} 2325 | engines: {node: '>=10'} 2326 | dependencies: 2327 | type-fest: 0.11.0 2328 | dev: false 2329 | 2330 | /p-cancelable/0.3.0: 2331 | resolution: {integrity: sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==} 2332 | engines: {node: '>=4'} 2333 | dev: false 2334 | 2335 | /p-cancelable/0.4.1: 2336 | resolution: {integrity: sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==} 2337 | engines: {node: '>=4'} 2338 | dev: false 2339 | 2340 | /p-event/1.3.0: 2341 | resolution: {integrity: sha1-jmtPT2XHK8W2/ii3XtqHT5akoIU=} 2342 | engines: {node: '>=4'} 2343 | dependencies: 2344 | p-timeout: 1.2.1 2345 | dev: false 2346 | 2347 | /p-event/2.3.1: 2348 | resolution: {integrity: sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==} 2349 | engines: {node: '>=6'} 2350 | dependencies: 2351 | p-timeout: 2.0.1 2352 | dev: false 2353 | 2354 | /p-finally/1.0.0: 2355 | resolution: {integrity: sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=} 2356 | engines: {node: '>=4'} 2357 | dev: false 2358 | 2359 | /p-is-promise/1.1.0: 2360 | resolution: {integrity: sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=} 2361 | engines: {node: '>=4'} 2362 | dev: false 2363 | 2364 | /p-limit/2.3.0: 2365 | resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} 2366 | engines: {node: '>=6'} 2367 | dependencies: 2368 | p-try: 2.2.0 2369 | dev: false 2370 | 2371 | /p-locate/4.1.0: 2372 | resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} 2373 | engines: {node: '>=8'} 2374 | dependencies: 2375 | p-limit: 2.3.0 2376 | dev: false 2377 | 2378 | /p-map-series/1.0.0: 2379 | resolution: {integrity: sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco=} 2380 | engines: {node: '>=4'} 2381 | dependencies: 2382 | p-reduce: 1.0.0 2383 | dev: false 2384 | 2385 | /p-pipe/3.1.0: 2386 | resolution: {integrity: sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==} 2387 | engines: {node: '>=8'} 2388 | dev: false 2389 | 2390 | /p-reduce/1.0.0: 2391 | resolution: {integrity: sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=} 2392 | engines: {node: '>=4'} 2393 | dev: false 2394 | 2395 | /p-timeout/1.2.1: 2396 | resolution: {integrity: sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=} 2397 | engines: {node: '>=4'} 2398 | dependencies: 2399 | p-finally: 1.0.0 2400 | dev: false 2401 | 2402 | /p-timeout/2.0.1: 2403 | resolution: {integrity: sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==} 2404 | engines: {node: '>=4'} 2405 | dependencies: 2406 | p-finally: 1.0.0 2407 | dev: false 2408 | 2409 | /p-try/2.2.0: 2410 | resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} 2411 | engines: {node: '>=6'} 2412 | dev: false 2413 | 2414 | /parent-module/1.0.1: 2415 | resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 2416 | engines: {node: '>=6'} 2417 | dependencies: 2418 | callsites: 3.1.0 2419 | dev: true 2420 | 2421 | /path-exists/4.0.0: 2422 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 2423 | engines: {node: '>=8'} 2424 | dev: false 2425 | 2426 | /path-is-absolute/1.0.1: 2427 | resolution: {integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=} 2428 | engines: {node: '>=0.10.0'} 2429 | 2430 | /path-key/2.0.1: 2431 | resolution: {integrity: sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=} 2432 | engines: {node: '>=4'} 2433 | dev: false 2434 | 2435 | /path-key/3.1.1: 2436 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 2437 | engines: {node: '>=8'} 2438 | 2439 | /path-parse/1.0.7: 2440 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 2441 | dev: true 2442 | 2443 | /path-to-regexp/6.2.0: 2444 | resolution: {integrity: sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg==} 2445 | dev: true 2446 | 2447 | /path-type/4.0.0: 2448 | resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} 2449 | engines: {node: '>=8'} 2450 | 2451 | /pathval/1.1.1: 2452 | resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} 2453 | dev: true 2454 | 2455 | /pend/1.2.0: 2456 | resolution: {integrity: sha1-elfrVQpng/kRUzH89GY9XI4AelA=} 2457 | dev: false 2458 | 2459 | /picocolors/1.0.0: 2460 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 2461 | dev: true 2462 | 2463 | /picomatch/2.3.1: 2464 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 2465 | engines: {node: '>=8.6'} 2466 | 2467 | /pify/2.3.0: 2468 | resolution: {integrity: sha1-7RQaasBDqEnqWISY59yosVMw6Qw=} 2469 | engines: {node: '>=0.10.0'} 2470 | dev: false 2471 | 2472 | /pify/3.0.0: 2473 | resolution: {integrity: sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=} 2474 | engines: {node: '>=4'} 2475 | dev: false 2476 | 2477 | /pify/4.0.1: 2478 | resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} 2479 | engines: {node: '>=6'} 2480 | dev: false 2481 | 2482 | /pinkie-promise/2.0.1: 2483 | resolution: {integrity: sha1-ITXW36ejWMBprJsXh3YogihFD/o=} 2484 | engines: {node: '>=0.10.0'} 2485 | dependencies: 2486 | pinkie: 2.0.4 2487 | dev: false 2488 | 2489 | /pinkie/2.0.4: 2490 | resolution: {integrity: sha1-clVrgM+g1IqXToDnckjoDtT3+HA=} 2491 | engines: {node: '>=0.10.0'} 2492 | dev: false 2493 | 2494 | /pkg-dir/4.2.0: 2495 | resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} 2496 | engines: {node: '>=8'} 2497 | dependencies: 2498 | find-up: 4.1.0 2499 | dev: false 2500 | 2501 | /pngquant-bin/6.0.1: 2502 | resolution: {integrity: sha512-Q3PUyolfktf+hYio6wsg3SanQzEU/v8aICg/WpzxXcuCMRb7H2Q81okfpcEztbMvw25ILjd3a87doj2N9kvbpQ==} 2503 | engines: {node: '>=10'} 2504 | hasBin: true 2505 | requiresBuild: true 2506 | dependencies: 2507 | bin-build: 3.0.0 2508 | bin-wrapper: 4.1.0 2509 | execa: 4.1.0 2510 | dev: false 2511 | 2512 | /postcss/8.4.7: 2513 | resolution: {integrity: sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A==} 2514 | engines: {node: ^10 || ^12 || >=14} 2515 | dependencies: 2516 | nanoid: 3.3.1 2517 | picocolors: 1.0.0 2518 | source-map-js: 1.0.2 2519 | dev: true 2520 | 2521 | /prelude-ls/1.2.1: 2522 | resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 2523 | engines: {node: '>= 0.8.0'} 2524 | dev: true 2525 | 2526 | /prepend-http/1.0.4: 2527 | resolution: {integrity: sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=} 2528 | engines: {node: '>=0.10.0'} 2529 | dev: false 2530 | 2531 | /prepend-http/2.0.0: 2532 | resolution: {integrity: sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=} 2533 | engines: {node: '>=4'} 2534 | dev: false 2535 | 2536 | /prettier-linter-helpers/1.0.0: 2537 | resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} 2538 | engines: {node: '>=6.0.0'} 2539 | dependencies: 2540 | fast-diff: 1.2.0 2541 | dev: true 2542 | 2543 | /prettier/2.5.1: 2544 | resolution: {integrity: sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==} 2545 | engines: {node: '>=10.13.0'} 2546 | hasBin: true 2547 | dev: true 2548 | 2549 | /process-nextick-args/2.0.1: 2550 | resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} 2551 | dev: false 2552 | 2553 | /progress/2.0.1: 2554 | resolution: {integrity: sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==} 2555 | engines: {node: '>=0.4.0'} 2556 | dev: false 2557 | 2558 | /proto-list/1.2.4: 2559 | resolution: {integrity: sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=} 2560 | dev: false 2561 | 2562 | /proxy-from-env/1.1.0: 2563 | resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} 2564 | dev: false 2565 | 2566 | /pseudomap/1.0.2: 2567 | resolution: {integrity: sha1-8FKijacOYYkX7wqKw0wa5aaChrM=} 2568 | dev: false 2569 | 2570 | /pump/3.0.0: 2571 | resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} 2572 | dependencies: 2573 | end-of-stream: 1.4.4 2574 | once: 1.4.0 2575 | dev: false 2576 | 2577 | /punycode/2.1.1: 2578 | resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} 2579 | engines: {node: '>=6'} 2580 | dev: true 2581 | 2582 | /puppeteer-core/10.1.0: 2583 | resolution: {integrity: sha512-x2yDSJI/PRiWhDqAt1jd4rhTotxwjwKzHLIIqD2MlJ+TmzGJfBY9snAGIVXJwkWfKJg+Ef5xupdK0EbHDqBpFw==} 2584 | engines: {node: '>=10.18.1'} 2585 | dependencies: 2586 | debug: 4.3.1 2587 | devtools-protocol: 0.0.883894 2588 | extract-zip: 2.0.1 2589 | https-proxy-agent: 5.0.0 2590 | node-fetch: 2.6.1 2591 | pkg-dir: 4.2.0 2592 | progress: 2.0.1 2593 | proxy-from-env: 1.1.0 2594 | rimraf: 3.0.2 2595 | tar-fs: 2.0.0 2596 | unbzip2-stream: 1.3.3 2597 | ws: 7.4.6 2598 | transitivePeerDependencies: 2599 | - bufferutil 2600 | - supports-color 2601 | - utf-8-validate 2602 | dev: false 2603 | 2604 | /query-string/5.1.1: 2605 | resolution: {integrity: sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==} 2606 | engines: {node: '>=0.10.0'} 2607 | dependencies: 2608 | decode-uri-component: 0.2.0 2609 | object-assign: 4.1.1 2610 | strict-uri-encode: 1.1.0 2611 | dev: false 2612 | 2613 | /queue-microtask/1.2.3: 2614 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 2615 | 2616 | /readable-stream/2.3.7: 2617 | resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} 2618 | dependencies: 2619 | core-util-is: 1.0.3 2620 | inherits: 2.0.4 2621 | isarray: 1.0.0 2622 | process-nextick-args: 2.0.1 2623 | safe-buffer: 5.1.2 2624 | string_decoder: 1.1.1 2625 | util-deprecate: 1.0.2 2626 | dev: false 2627 | 2628 | /readable-stream/3.6.0: 2629 | resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} 2630 | engines: {node: '>= 6'} 2631 | dependencies: 2632 | inherits: 2.0.4 2633 | string_decoder: 1.3.0 2634 | util-deprecate: 1.0.2 2635 | 2636 | /readdirp/3.6.0: 2637 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 2638 | engines: {node: '>=8.10.0'} 2639 | dependencies: 2640 | picomatch: 2.3.1 2641 | dev: true 2642 | 2643 | /regexpp/3.2.0: 2644 | resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} 2645 | engines: {node: '>=8'} 2646 | dev: true 2647 | 2648 | /regextras/0.8.0: 2649 | resolution: {integrity: sha512-k519uI04Z3SaY0fLX843MRXnDeG2+vHOFsyhiPZvNLe7r8rD2YNRjq4BQLZZ0oAr2NrtvZlICsXysGNFPGa3CQ==} 2650 | engines: {node: '>=0.1.14'} 2651 | dev: true 2652 | 2653 | /replace-ext/1.0.1: 2654 | resolution: {integrity: sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==} 2655 | engines: {node: '>= 0.10'} 2656 | dev: false 2657 | 2658 | /require-directory/2.1.1: 2659 | resolution: {integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I=} 2660 | engines: {node: '>=0.10.0'} 2661 | dev: true 2662 | 2663 | /resolve-from/4.0.0: 2664 | resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 2665 | engines: {node: '>=4'} 2666 | dev: true 2667 | 2668 | /resolve/1.22.0: 2669 | resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==} 2670 | hasBin: true 2671 | dependencies: 2672 | is-core-module: 2.8.1 2673 | path-parse: 1.0.7 2674 | supports-preserve-symlinks-flag: 1.0.0 2675 | dev: true 2676 | 2677 | /responselike/1.0.2: 2678 | resolution: {integrity: sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=} 2679 | dependencies: 2680 | lowercase-keys: 1.0.1 2681 | dev: false 2682 | 2683 | /restore-cursor/3.1.0: 2684 | resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} 2685 | engines: {node: '>=8'} 2686 | dependencies: 2687 | onetime: 5.1.2 2688 | signal-exit: 3.0.7 2689 | dev: true 2690 | 2691 | /reusify/1.0.4: 2692 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 2693 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 2694 | 2695 | /rimraf/3.0.2: 2696 | resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} 2697 | hasBin: true 2698 | dependencies: 2699 | glob: 7.2.0 2700 | 2701 | /rollup/2.66.0: 2702 | resolution: {integrity: sha512-L6mKOkdyP8HK5kKJXaiWG7KZDumPJjuo1P+cfyHOJPNNTK3Moe7zCH5+fy7v8pVmHXtlxorzaBjvkBMB23s98g==} 2703 | engines: {node: '>=10.0.0'} 2704 | hasBin: true 2705 | optionalDependencies: 2706 | fsevents: 2.3.2 2707 | dev: true 2708 | 2709 | /run-async/2.4.1: 2710 | resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} 2711 | engines: {node: '>=0.12.0'} 2712 | dev: true 2713 | 2714 | /run-parallel/1.2.0: 2715 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 2716 | dependencies: 2717 | queue-microtask: 1.2.3 2718 | 2719 | /rxjs/7.5.5: 2720 | resolution: {integrity: sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==} 2721 | dependencies: 2722 | tslib: 2.3.1 2723 | dev: true 2724 | 2725 | /safe-buffer/5.1.2: 2726 | resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} 2727 | dev: false 2728 | 2729 | /safe-buffer/5.2.1: 2730 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 2731 | 2732 | /safer-buffer/2.1.2: 2733 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} 2734 | dev: true 2735 | 2736 | /seek-bzip/1.0.6: 2737 | resolution: {integrity: sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==} 2738 | hasBin: true 2739 | dependencies: 2740 | commander: 2.20.3 2741 | dev: false 2742 | 2743 | /semver-regex/2.0.0: 2744 | resolution: {integrity: sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==} 2745 | engines: {node: '>=6'} 2746 | dev: false 2747 | 2748 | /semver-truncate/1.1.2: 2749 | resolution: {integrity: sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g=} 2750 | engines: {node: '>=0.10.0'} 2751 | dependencies: 2752 | semver: 5.7.1 2753 | dev: false 2754 | 2755 | /semver/5.7.1: 2756 | resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} 2757 | hasBin: true 2758 | dev: false 2759 | 2760 | /semver/6.3.0: 2761 | resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} 2762 | hasBin: true 2763 | dev: false 2764 | 2765 | /semver/7.3.5: 2766 | resolution: {integrity: sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==} 2767 | engines: {node: '>=10'} 2768 | hasBin: true 2769 | dependencies: 2770 | lru-cache: 6.0.0 2771 | dev: true 2772 | 2773 | /set-cookie-parser/2.4.8: 2774 | resolution: {integrity: sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg==} 2775 | dev: true 2776 | 2777 | /shebang-command/1.2.0: 2778 | resolution: {integrity: sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=} 2779 | engines: {node: '>=0.10.0'} 2780 | dependencies: 2781 | shebang-regex: 1.0.0 2782 | dev: false 2783 | 2784 | /shebang-command/2.0.0: 2785 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 2786 | engines: {node: '>=8'} 2787 | dependencies: 2788 | shebang-regex: 3.0.0 2789 | 2790 | /shebang-regex/1.0.0: 2791 | resolution: {integrity: sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=} 2792 | engines: {node: '>=0.10.0'} 2793 | dev: false 2794 | 2795 | /shebang-regex/3.0.0: 2796 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 2797 | engines: {node: '>=8'} 2798 | 2799 | /signal-exit/3.0.7: 2800 | resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} 2801 | 2802 | /slash/3.0.0: 2803 | resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} 2804 | engines: {node: '>=8'} 2805 | 2806 | /sort-keys-length/1.0.1: 2807 | resolution: {integrity: sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=} 2808 | engines: {node: '>=0.10.0'} 2809 | dependencies: 2810 | sort-keys: 1.1.2 2811 | dev: false 2812 | 2813 | /sort-keys/1.1.2: 2814 | resolution: {integrity: sha1-RBttTTRnmPG05J6JIK37oOVD+a0=} 2815 | engines: {node: '>=0.10.0'} 2816 | dependencies: 2817 | is-plain-obj: 1.1.0 2818 | dev: false 2819 | 2820 | /sort-keys/2.0.0: 2821 | resolution: {integrity: sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=} 2822 | engines: {node: '>=4'} 2823 | dependencies: 2824 | is-plain-obj: 1.1.0 2825 | dev: false 2826 | 2827 | /source-map-js/1.0.2: 2828 | resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} 2829 | engines: {node: '>=0.10.0'} 2830 | dev: true 2831 | 2832 | /source-map-support/0.5.21: 2833 | resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} 2834 | dependencies: 2835 | buffer-from: 1.1.2 2836 | source-map: 0.6.1 2837 | dev: true 2838 | 2839 | /source-map/0.6.1: 2840 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} 2841 | engines: {node: '>=0.10.0'} 2842 | dev: true 2843 | 2844 | /spdx-exceptions/2.3.0: 2845 | resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} 2846 | dev: true 2847 | 2848 | /spdx-expression-parse/3.0.1: 2849 | resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} 2850 | dependencies: 2851 | spdx-exceptions: 2.3.0 2852 | spdx-license-ids: 3.0.11 2853 | dev: true 2854 | 2855 | /spdx-license-ids/3.0.11: 2856 | resolution: {integrity: sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==} 2857 | dev: true 2858 | 2859 | /statuses/2.0.1: 2860 | resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} 2861 | engines: {node: '>= 0.8'} 2862 | dev: true 2863 | 2864 | /strict-event-emitter/0.2.0: 2865 | resolution: {integrity: sha512-zv7K2egoKwkQkZGEaH8m+i2D0XiKzx5jNsiSul6ja2IYFvil10A59Z9Y7PPAAe5OW53dQUf9CfsHKzjZzKkm1w==} 2866 | dependencies: 2867 | events: 3.3.0 2868 | dev: true 2869 | 2870 | /strict-uri-encode/1.1.0: 2871 | resolution: {integrity: sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=} 2872 | engines: {node: '>=0.10.0'} 2873 | dev: false 2874 | 2875 | /string-width/4.2.3: 2876 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 2877 | engines: {node: '>=8'} 2878 | dependencies: 2879 | emoji-regex: 8.0.0 2880 | is-fullwidth-code-point: 3.0.0 2881 | strip-ansi: 6.0.1 2882 | dev: true 2883 | 2884 | /string_decoder/1.1.1: 2885 | resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} 2886 | dependencies: 2887 | safe-buffer: 5.1.2 2888 | dev: false 2889 | 2890 | /string_decoder/1.3.0: 2891 | resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} 2892 | dependencies: 2893 | safe-buffer: 5.2.1 2894 | 2895 | /strip-ansi/6.0.1: 2896 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 2897 | engines: {node: '>=8'} 2898 | dependencies: 2899 | ansi-regex: 5.0.1 2900 | dev: true 2901 | 2902 | /strip-dirs/2.1.0: 2903 | resolution: {integrity: sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==} 2904 | dependencies: 2905 | is-natural-number: 4.0.1 2906 | dev: false 2907 | 2908 | /strip-eof/1.0.0: 2909 | resolution: {integrity: sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=} 2910 | engines: {node: '>=0.10.0'} 2911 | dev: false 2912 | 2913 | /strip-final-newline/2.0.0: 2914 | resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} 2915 | engines: {node: '>=6'} 2916 | dev: false 2917 | 2918 | /strip-json-comments/3.1.1: 2919 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 2920 | engines: {node: '>=8'} 2921 | dev: true 2922 | 2923 | /strip-outer/1.0.1: 2924 | resolution: {integrity: sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==} 2925 | engines: {node: '>=0.10.0'} 2926 | dependencies: 2927 | escape-string-regexp: 1.0.5 2928 | dev: false 2929 | 2930 | /supports-color/7.2.0: 2931 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 2932 | engines: {node: '>=8'} 2933 | dependencies: 2934 | has-flag: 4.0.0 2935 | dev: true 2936 | 2937 | /supports-preserve-symlinks-flag/1.0.0: 2938 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 2939 | engines: {node: '>= 0.4'} 2940 | dev: true 2941 | 2942 | /tar-fs/2.0.0: 2943 | resolution: {integrity: sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA==} 2944 | dependencies: 2945 | chownr: 1.1.4 2946 | mkdirp: 0.5.5 2947 | pump: 3.0.0 2948 | tar-stream: 2.2.0 2949 | dev: false 2950 | 2951 | /tar-stream/1.6.2: 2952 | resolution: {integrity: sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==} 2953 | engines: {node: '>= 0.8.0'} 2954 | dependencies: 2955 | bl: 1.2.3 2956 | buffer-alloc: 1.2.0 2957 | end-of-stream: 1.4.4 2958 | fs-constants: 1.0.0 2959 | readable-stream: 2.3.7 2960 | to-buffer: 1.1.1 2961 | xtend: 4.0.2 2962 | dev: false 2963 | 2964 | /tar-stream/2.2.0: 2965 | resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} 2966 | engines: {node: '>=6'} 2967 | dependencies: 2968 | bl: 4.1.0 2969 | end-of-stream: 1.4.4 2970 | fs-constants: 1.0.0 2971 | inherits: 2.0.4 2972 | readable-stream: 3.6.0 2973 | dev: false 2974 | 2975 | /temp-dir/1.0.0: 2976 | resolution: {integrity: sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=} 2977 | engines: {node: '>=4'} 2978 | dev: false 2979 | 2980 | /tempfile/2.0.0: 2981 | resolution: {integrity: sha1-awRGhWqbERTRhW/8vlCczLCXcmU=} 2982 | engines: {node: '>=4'} 2983 | dependencies: 2984 | temp-dir: 1.0.0 2985 | uuid: 3.4.0 2986 | dev: false 2987 | 2988 | /text-table/0.2.0: 2989 | resolution: {integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=} 2990 | dev: true 2991 | 2992 | /through/2.3.8: 2993 | resolution: {integrity: sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=} 2994 | 2995 | /timed-out/4.0.1: 2996 | resolution: {integrity: sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=} 2997 | engines: {node: '>=0.10.0'} 2998 | dev: false 2999 | 3000 | /tinypool/0.1.2: 3001 | resolution: {integrity: sha512-fvtYGXoui2RpeMILfkvGIgOVkzJEGediv8UJt7TxdAOY8pnvUkFg/fkvqTfXG9Acc9S17Cnn1S4osDc2164guA==} 3002 | engines: {node: '>=14.0.0'} 3003 | dev: true 3004 | 3005 | /tinyspy/0.3.0: 3006 | resolution: {integrity: sha512-c5uFHqtUp74R2DJE3/Efg0mH5xicmgziaQXMm/LvuuZn3RdpADH32aEGDRyCzObXT1DNfwDMqRQ/Drh1MlO12g==} 3007 | engines: {node: '>=14.0.0'} 3008 | dev: true 3009 | 3010 | /tmp/0.0.33: 3011 | resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} 3012 | engines: {node: '>=0.6.0'} 3013 | dependencies: 3014 | os-tmpdir: 1.0.2 3015 | dev: true 3016 | 3017 | /to-buffer/1.1.1: 3018 | resolution: {integrity: sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==} 3019 | dev: false 3020 | 3021 | /to-regex-range/5.0.1: 3022 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 3023 | engines: {node: '>=8.0'} 3024 | dependencies: 3025 | is-number: 7.0.0 3026 | 3027 | /tr46/0.0.3: 3028 | resolution: {integrity: sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=} 3029 | dev: true 3030 | 3031 | /trim-repeated/1.0.0: 3032 | resolution: {integrity: sha1-42RqLqTokTEr9+rObPsFOAvAHCE=} 3033 | engines: {node: '>=0.10.0'} 3034 | dependencies: 3035 | escape-string-regexp: 1.0.5 3036 | dev: false 3037 | 3038 | /ts-node/8.9.1_typescript@4.3.4: 3039 | resolution: {integrity: sha512-yrq6ODsxEFTLz0R3BX2myf0WBCSQh9A+py8PBo1dCzWIOcvisbyH6akNKqDHMgXePF2kir5mm5JXJTH3OUJYOQ==} 3040 | engines: {node: '>=6.0.0'} 3041 | hasBin: true 3042 | peerDependencies: 3043 | typescript: '>=2.7' 3044 | dependencies: 3045 | arg: 4.1.3 3046 | diff: 4.0.2 3047 | make-error: 1.3.6 3048 | source-map-support: 0.5.21 3049 | typescript: 4.3.4 3050 | yn: 3.1.1 3051 | dev: true 3052 | 3053 | /tslib/1.14.1: 3054 | resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} 3055 | dev: true 3056 | 3057 | /tslib/2.3.1: 3058 | resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==} 3059 | dev: true 3060 | 3061 | /tsutils/3.21.0_typescript@4.5.5: 3062 | resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} 3063 | engines: {node: '>= 6'} 3064 | peerDependencies: 3065 | typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' 3066 | dependencies: 3067 | tslib: 1.14.1 3068 | typescript: 4.5.5 3069 | dev: true 3070 | 3071 | /tunnel-agent/0.6.0: 3072 | resolution: {integrity: sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=} 3073 | dependencies: 3074 | safe-buffer: 5.2.1 3075 | dev: false 3076 | 3077 | /type-check/0.4.0: 3078 | resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 3079 | engines: {node: '>= 0.8.0'} 3080 | dependencies: 3081 | prelude-ls: 1.2.1 3082 | dev: true 3083 | 3084 | /type-detect/4.0.8: 3085 | resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} 3086 | engines: {node: '>=4'} 3087 | dev: true 3088 | 3089 | /type-fest/0.11.0: 3090 | resolution: {integrity: sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==} 3091 | engines: {node: '>=8'} 3092 | dev: false 3093 | 3094 | /type-fest/0.20.2: 3095 | resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} 3096 | engines: {node: '>=10'} 3097 | dev: true 3098 | 3099 | /type-fest/0.21.3: 3100 | resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} 3101 | engines: {node: '>=10'} 3102 | dev: true 3103 | 3104 | /type-fest/1.4.0: 3105 | resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} 3106 | engines: {node: '>=10'} 3107 | dev: true 3108 | 3109 | /typescript/4.3.4: 3110 | resolution: {integrity: sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew==} 3111 | engines: {node: '>=4.2.0'} 3112 | hasBin: true 3113 | dev: true 3114 | 3115 | /typescript/4.5.5: 3116 | resolution: {integrity: sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==} 3117 | engines: {node: '>=4.2.0'} 3118 | hasBin: true 3119 | dev: true 3120 | 3121 | /unbzip2-stream/1.3.3: 3122 | resolution: {integrity: sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==} 3123 | dependencies: 3124 | buffer: 5.7.1 3125 | through: 2.3.8 3126 | dev: false 3127 | 3128 | /unfetch/4.2.0: 3129 | resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==} 3130 | dev: false 3131 | 3132 | /uri-js/4.4.1: 3133 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 3134 | dependencies: 3135 | punycode: 2.1.1 3136 | dev: true 3137 | 3138 | /url-parse-lax/1.0.0: 3139 | resolution: {integrity: sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=} 3140 | engines: {node: '>=0.10.0'} 3141 | dependencies: 3142 | prepend-http: 1.0.4 3143 | dev: false 3144 | 3145 | /url-parse-lax/3.0.0: 3146 | resolution: {integrity: sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=} 3147 | engines: {node: '>=4'} 3148 | dependencies: 3149 | prepend-http: 2.0.0 3150 | dev: false 3151 | 3152 | /url-to-options/1.0.1: 3153 | resolution: {integrity: sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=} 3154 | engines: {node: '>= 4'} 3155 | dev: false 3156 | 3157 | /util-deprecate/1.0.2: 3158 | resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=} 3159 | 3160 | /uuid/3.4.0: 3161 | resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} 3162 | deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. 3163 | hasBin: true 3164 | dev: false 3165 | 3166 | /v8-compile-cache/2.3.0: 3167 | resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} 3168 | dev: true 3169 | 3170 | /vite/2.8.6: 3171 | resolution: {integrity: sha512-e4H0QpludOVKkmOsRyqQ7LTcMUDF3mcgyNU4lmi0B5JUbe0ZxeBBl8VoZ8Y6Rfn9eFKYtdXNPcYK97ZwH+K2ug==} 3172 | engines: {node: '>=12.2.0'} 3173 | hasBin: true 3174 | peerDependencies: 3175 | less: '*' 3176 | sass: '*' 3177 | stylus: '*' 3178 | peerDependenciesMeta: 3179 | less: 3180 | optional: true 3181 | sass: 3182 | optional: true 3183 | stylus: 3184 | optional: true 3185 | dependencies: 3186 | esbuild: 0.14.27 3187 | postcss: 8.4.7 3188 | resolve: 1.22.0 3189 | rollup: 2.66.0 3190 | optionalDependencies: 3191 | fsevents: 2.3.2 3192 | dev: true 3193 | 3194 | /vitest/0.7.4: 3195 | resolution: {integrity: sha512-6kyJ/YZJFVj/zEVVHFyvLvAZlbg05yAyJrk7oP+FOCFanGRYK7bBEz4qsIpNHxX+dlf5vRkbBDjpdXzGL7udeA==} 3196 | engines: {node: '>=14.14.0'} 3197 | hasBin: true 3198 | peerDependencies: 3199 | '@vitest/ui': '*' 3200 | c8: '*' 3201 | happy-dom: '*' 3202 | jsdom: '*' 3203 | peerDependenciesMeta: 3204 | '@vitest/ui': 3205 | optional: true 3206 | c8: 3207 | optional: true 3208 | happy-dom: 3209 | optional: true 3210 | jsdom: 3211 | optional: true 3212 | dependencies: 3213 | '@types/chai': 4.3.0 3214 | '@types/chai-subset': 1.3.3 3215 | chai: 4.3.6 3216 | local-pkg: 0.4.1 3217 | tinypool: 0.1.2 3218 | tinyspy: 0.3.0 3219 | vite: 2.8.6 3220 | transitivePeerDependencies: 3221 | - less 3222 | - sass 3223 | - stylus 3224 | dev: true 3225 | 3226 | /wcwidth/1.0.1: 3227 | resolution: {integrity: sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=} 3228 | dependencies: 3229 | defaults: 1.0.3 3230 | dev: true 3231 | 3232 | /webidl-conversions/3.0.1: 3233 | resolution: {integrity: sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=} 3234 | dev: true 3235 | 3236 | /whatwg-url/5.0.0: 3237 | resolution: {integrity: sha1-lmRU6HZUYuN2RNNib2dCzotwll0=} 3238 | dependencies: 3239 | tr46: 0.0.3 3240 | webidl-conversions: 3.0.1 3241 | dev: true 3242 | 3243 | /which/1.3.1: 3244 | resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} 3245 | hasBin: true 3246 | dependencies: 3247 | isexe: 2.0.0 3248 | dev: false 3249 | 3250 | /which/2.0.2: 3251 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 3252 | engines: {node: '>= 8'} 3253 | hasBin: true 3254 | dependencies: 3255 | isexe: 2.0.0 3256 | 3257 | /word-wrap/1.2.3: 3258 | resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} 3259 | engines: {node: '>=0.10.0'} 3260 | dev: true 3261 | 3262 | /wrap-ansi/7.0.0: 3263 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 3264 | engines: {node: '>=10'} 3265 | dependencies: 3266 | ansi-styles: 4.3.0 3267 | string-width: 4.2.3 3268 | strip-ansi: 6.0.1 3269 | dev: true 3270 | 3271 | /wrappy/1.0.2: 3272 | resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} 3273 | 3274 | /ws/7.4.6: 3275 | resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} 3276 | engines: {node: '>=8.3.0'} 3277 | peerDependencies: 3278 | bufferutil: ^4.0.1 3279 | utf-8-validate: ^5.0.2 3280 | peerDependenciesMeta: 3281 | bufferutil: 3282 | optional: true 3283 | utf-8-validate: 3284 | optional: true 3285 | dev: false 3286 | 3287 | /xtend/4.0.2: 3288 | resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} 3289 | engines: {node: '>=0.4'} 3290 | dev: false 3291 | 3292 | /y18n/5.0.8: 3293 | resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} 3294 | engines: {node: '>=10'} 3295 | dev: true 3296 | 3297 | /yallist/2.1.2: 3298 | resolution: {integrity: sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=} 3299 | dev: false 3300 | 3301 | /yallist/4.0.0: 3302 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 3303 | dev: true 3304 | 3305 | /yargs-parser/21.0.1: 3306 | resolution: {integrity: sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==} 3307 | engines: {node: '>=12'} 3308 | dev: true 3309 | 3310 | /yargs/17.3.1: 3311 | resolution: {integrity: sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==} 3312 | engines: {node: '>=12'} 3313 | dependencies: 3314 | cliui: 7.0.4 3315 | escalade: 3.1.1 3316 | get-caller-file: 2.0.5 3317 | require-directory: 2.1.1 3318 | string-width: 4.2.3 3319 | y18n: 5.0.8 3320 | yargs-parser: 21.0.1 3321 | dev: true 3322 | 3323 | /yauzl/2.10.0: 3324 | resolution: {integrity: sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=} 3325 | dependencies: 3326 | buffer-crc32: 0.2.13 3327 | fd-slicer: 1.1.0 3328 | dev: false 3329 | 3330 | /yn/3.1.1: 3331 | resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} 3332 | engines: {node: '>=6'} 3333 | dev: true 3334 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | singleQuote: true, 3 | quoteProps: 'consistent', 4 | trailingCommas: 'all', 5 | arrowParens: 'avoid', 6 | parser: 'typescript', 7 | endOfLine: 'auto', 8 | }; 9 | -------------------------------------------------------------------------------- /src/constant/api.ts: -------------------------------------------------------------------------------- 1 | // Default OpenGraph specification 2 | export const WIDTH = 1200; 3 | export const HEIGHT = 630; 4 | -------------------------------------------------------------------------------- /src/lib/compress.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, vi, it, expect, afterEach } from 'vitest'; 2 | 3 | import { compressImage } from '@/lib/compress'; 4 | 5 | const bufferFn = vi.fn(); 6 | 7 | vi.mock('imagemin', () => ({ 8 | default: { 9 | buffer: () => bufferFn(), 10 | }, 11 | })); 12 | 13 | vi.mock('imagemin-pngquant', () => ({ 14 | default: vi.fn(), 15 | })); 16 | 17 | describe('compressImage', () => { 18 | afterEach(() => { 19 | vi.restoreAllMocks(); 20 | }); 21 | 22 | it('should compress the image in png format', async () => { 23 | const img = Buffer.from('', 'ascii'); 24 | 25 | await compressImage(img); 26 | 27 | expect(bufferFn).toHaveBeenCalledTimes(1); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /src/lib/compress.ts: -------------------------------------------------------------------------------- 1 | import imagemin from 'imagemin'; 2 | import imageminPngquant from 'imagemin-pngquant'; 3 | 4 | /** 5 | * Perform image compression to PNG image end result 6 | * 7 | * @param {Buffer} img result image in `Buffer` format 8 | * @returns {Promise<Buffer>} compressed image 9 | */ 10 | export async function compressImage(img: Buffer): Promise<Buffer> { 11 | return imagemin.buffer(img, { 12 | plugins: [ 13 | imageminPngquant({ 14 | quality: [0.7, 0.75], 15 | }), 16 | ], 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /src/lib/constant/font.ts: -------------------------------------------------------------------------------- 1 | // Enables emoji support 2 | export const EMOJI = 3 | 'https://raw.githack.com/googlei18n/noto-emoji/master/fonts/NotoColorEmoji.ttf'; 4 | -------------------------------------------------------------------------------- /src/lib/generator.test.ts: -------------------------------------------------------------------------------- 1 | import { afterAll, afterEach, beforeAll, describe, expect, it } from 'vitest'; 2 | import { generateContent } from '@/lib/generator'; 3 | 4 | import type { OpenGraphRequest } from '@/lib/types'; 5 | import { imgMockServer } from '@/mocks/server'; 6 | 7 | // Class injection are tested separately 8 | describe('generateContent', () => { 9 | beforeAll(() => { 10 | global.fetch = fetch; 11 | imgMockServer.listen(); 12 | }); 13 | 14 | afterEach(() => { 15 | imgMockServer.resetHandlers(); 16 | }); 17 | 18 | afterAll(() => { 19 | imgMockServer.close(); 20 | }); 21 | 22 | it.concurrent('should generate normal template', async () => { 23 | const content: OpenGraphRequest = { 24 | title: 'Foo bar', 25 | }; 26 | const template = await generateContent(content); 27 | 28 | expect(template).toMatch(/h1/); 29 | expect(template).not.toMatch(/h3/); 30 | expect(template).not.toMatch(/img/); 31 | }); 32 | 33 | it.concurrent('should generate template with subtitles', async () => { 34 | const content: OpenGraphRequest = { 35 | title: 'Foo bar', 36 | subtitle: 'bar baz', 37 | }; 38 | const template = await generateContent(content); 39 | 40 | expect(template).toMatch(/h1/); 41 | expect(template).toMatch(/h3/); 42 | expect(template).not.toMatch(/img/); 43 | }); 44 | 45 | it.concurrent( 46 | 'should generate template with subtitles and images', 47 | async () => { 48 | const content: OpenGraphRequest = { 49 | title: 'Foo bar', 50 | subtitle: 'bar baz', 51 | image: 'https://foo.bar/test.png', 52 | }; 53 | const template = await generateContent(content); 54 | 55 | expect(template).toMatch(/h1/); 56 | expect(template).toMatch(/h3/); 57 | expect(template).toMatch(/img/); 58 | } 59 | ); 60 | 61 | it.concurrent('should recognize custom fonts request', async () => { 62 | const content: OpenGraphRequest = { 63 | title: 'foo', 64 | fontSans: 'Open Sans', 65 | fontMono: 'Hack', 66 | }; 67 | const template = await generateContent(content); 68 | 69 | expect(template).toMatch( 70 | '<link href="https://fonts.googleapis.com/css2?family=Open Sans:wght@100;200;300;400;500;600;700;800;900&display=swap" rel="stylesheet">' 71 | ); 72 | expect(template).toMatch( 73 | '<link href="https://fonts.googleapis.com/css2?family=Hack:wght@100;200;300;400;500;600;700;800;900&display=swap" rel="stylesheet">' 74 | ); 75 | }); 76 | }); 77 | -------------------------------------------------------------------------------- /src/lib/generator.ts: -------------------------------------------------------------------------------- 1 | import { parse } from 'markdown-wasm'; 2 | 3 | import { 4 | buildTemplate, 5 | injectClassToElement, 6 | injectDefaultClasses, 7 | injectFonts, 8 | injectScripts, 9 | } from './injector'; 10 | import { sanitize } from './sanitizer'; 11 | import { isValidImage } from './utils'; 12 | 13 | import type { OpenGraphRequest, TemplateMap } from './types'; 14 | 15 | import { getTemplate } from './template/template'; 16 | 17 | /** 18 | * Generate content based on provided user input 19 | * 20 | * @param {OpenGraphRequest} content user-provided open graph input 21 | * @returns {string} HTML string 22 | */ 23 | export async function generateContent( 24 | content: OpenGraphRequest 25 | ): Promise<string> { 26 | const template: string = getTemplate(content.template || 'blank'); 27 | const templateMap: Partial<TemplateMap> = { 28 | fonts: injectFonts(content), 29 | scripts: injectScripts(content), 30 | }; 31 | 32 | const containerClass = injectDefaultClasses( 33 | content.containerClass || '', 34 | 'container' 35 | ); 36 | const titleClass = injectDefaultClasses(content.titleClass || '', 'title'); 37 | const subtitleClass = injectDefaultClasses( 38 | content.subtitleClass || '', 39 | 'subtitle' 40 | ); 41 | const footerClass = injectDefaultClasses(content.footerClass || '', 'footer'); 42 | const imageClass = injectDefaultClasses(content.imageClass || '', 'image'); 43 | 44 | const titleContent = content.title ? sanitize(content.title) : ''; 45 | const subtitleContent = content.subtitle ? sanitize(content.subtitle) : ''; 46 | const footerContent = content.footer ? sanitize(content.footer) : ''; 47 | 48 | let contentImage = ''; 49 | 50 | if (content.image) { 51 | const isValid = await isValidImage(content.image); 52 | 53 | if (isValid) { 54 | contentImage = content.image; 55 | } 56 | } 57 | 58 | const title = titleContent 59 | ? injectClassToElement(parse(titleContent), titleClass, 'h1') 60 | : ''; 61 | const subtitle = subtitleContent 62 | ? injectClassToElement(parse(subtitleContent), subtitleClass, 'h3') 63 | : ''; 64 | const img = contentImage 65 | ? `<img src="${contentImage}" class="${imageClass}" />` 66 | : ''; 67 | const footer = footerContent 68 | ? injectClassToElement(parse(footerContent), footerClass, 'p') 69 | : ''; 70 | 71 | templateMap.container = containerClass; 72 | templateMap.title = title; 73 | templateMap.subtitle = subtitle; 74 | templateMap.image = img; 75 | templateMap.footer = footer; 76 | 77 | return buildTemplate(template, templateMap); 78 | } 79 | -------------------------------------------------------------------------------- /src/lib/injector.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest'; 2 | 3 | import { 4 | buildTemplate, 5 | injectClassToElement, 6 | injectDefaultClasses, 7 | injectFonts, 8 | injectScripts, 9 | } from '@/lib/injector'; 10 | 11 | import { HERO_TEMPLATE } from '@/lib/template/hero'; 12 | 13 | import type { OpenGraphRequest, TemplateMap } from '@/lib/types'; 14 | 15 | describe('injectDefaultClasses', () => { 16 | describe('injectContainerClass', () => { 17 | it('should inject some fallback classes', () => { 18 | const input = 'p-24'; 19 | const output = injectDefaultClasses(input, 'container'); 20 | 21 | const classes = output.split(' '); 22 | expect(classes).toContain('w-screen'); 23 | expect(classes).toContain('h-screen'); 24 | expect(classes).not.toContain('p-16'); 25 | expect(classes).toContain('p-24'); 26 | }); 27 | 28 | it('should inject all fallback classes', () => { 29 | const input = ''; 30 | const output = injectDefaultClasses(input, 'container'); 31 | 32 | const classes = output.split(' '); 33 | expect(classes).toContain('w-screen'); 34 | expect(classes).toContain('h-screen'); 35 | expect(classes).toContain('p-16'); 36 | }); 37 | 38 | it('should not inject any classes', () => { 39 | const input = 'w-full h-full p-48 flex justify-center items-center'; 40 | const output = injectDefaultClasses(input, 'container'); 41 | 42 | const classes = output.split(' '); 43 | expect(classes).toContain('w-full'); 44 | expect(classes).toContain('h-full'); 45 | expect(classes).toContain('p-48'); 46 | expect(classes).toContain('flex'); 47 | expect(classes).toContain('justify-center'); 48 | expect(classes).toContain('items-center'); 49 | 50 | expect(classes).not.toContain('w-screen'); 51 | expect(classes).not.toContain('h-screen'); 52 | expect(classes).not.toContain('p-16'); 53 | expect(classes).not.toContain('flex-col'); 54 | }); 55 | }); 56 | 57 | describe('injectTitleClass', () => { 58 | it('should inject some fallback classes', () => { 59 | const input = 'text-5xl'; 60 | const output = injectDefaultClasses(input, 'title'); 61 | 62 | const classes = output.split(' '); 63 | 64 | expect(classes).toContain('text-5xl'); 65 | expect(classes).not.toContain('text-7xl'); 66 | }); 67 | 68 | it('should inject all fallback classes', () => { 69 | const input = ''; 70 | const output = injectDefaultClasses(input, 'title'); 71 | 72 | const classes = output.split(' '); 73 | expect(classes).toContain('text-7xl'); 74 | }); 75 | 76 | it('should not inject any classes', () => { 77 | const input = 78 | 'text-4xl leading-loose tracking-wider text-red-500 text-left'; 79 | const output = injectDefaultClasses(input, 'title'); 80 | 81 | const classes = output.split(' '); 82 | 83 | expect(classes).toContain('text-left'); 84 | expect(classes).toContain('text-red-500'); 85 | expect(classes).toContain('text-4xl'); 86 | expect(classes).toContain('leading-loose'); 87 | expect(classes).toContain('tracking-wider'); 88 | 89 | expect(classes).not.toContain('text-7xl'); 90 | }); 91 | }); 92 | 93 | describe('injectSubtitleClass', () => { 94 | it('should inject some fallback classes', () => { 95 | const input = 'text-3xl'; 96 | const output = injectDefaultClasses(input, 'subtitle'); 97 | 98 | const classes = output.split(' '); 99 | 100 | expect(classes).toContain('text-3xl'); 101 | expect(classes).not.toContain('text-2xl'); 102 | }); 103 | 104 | it('should inject all fallback classes', () => { 105 | const input = ''; 106 | const output = injectDefaultClasses(input, 'subtitle'); 107 | 108 | const classes = output.split(' '); 109 | expect(classes).toContain('text-3xl'); 110 | }); 111 | 112 | it('should not inject any classes', () => { 113 | const input = 'text-xl text-right text-gray-400'; 114 | const output = injectDefaultClasses(input, 'subtitle'); 115 | 116 | const classes = output.split(' '); 117 | 118 | expect(classes).toContain('text-right'); 119 | expect(classes).toContain('text-gray-400'); 120 | expect(classes).toContain('text-xl'); 121 | 122 | expect(classes).not.toContain('text-2xl'); 123 | expect(classes).not.toContain('text-center'); 124 | }); 125 | }); 126 | 127 | describe('injectImage', () => { 128 | it('should inject default classes', () => { 129 | const input = ''; 130 | 131 | const imageClass = injectDefaultClasses(input, 'image'); 132 | 133 | expect(imageClass).toBe('object-contain'); 134 | }); 135 | 136 | it('should inject nothing', () => { 137 | const input = 'object-fill'; 138 | 139 | const imageClass = injectDefaultClasses(input, 'image'); 140 | 141 | expect(imageClass).toBe('object-fill'); 142 | }); 143 | }); 144 | 145 | describe('injectFonts', () => { 146 | it('should generate sans and mono variants', () => { 147 | const content: OpenGraphRequest = { 148 | title: 'foo', 149 | fontSans: 'Inter', 150 | fontMono: 'Hack', 151 | }; 152 | 153 | const links = injectFonts(content); 154 | 155 | expect(links).toMatch( 156 | /<link rel="preconnect" href="https:\/\/fonts.googleapis.com">/ 157 | ); 158 | expect(links).toMatch( 159 | /<link rel="preconnect" href="https:\/\/fonts.gstatic.com" crossorigin>/ 160 | ); 161 | expect(links).toMatch( 162 | /<link href="https:\/\/fonts.googleapis.com\/css2\?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap" rel="stylesheet">/ 163 | ); 164 | expect(links).toMatch( 165 | /<link href="https:\/\/fonts.googleapis.com\/css2\?family=Hack:wght@100;200;300;400;500;600;700;800;900&display=swap" rel="stylesheet">/ 166 | ); 167 | }); 168 | 169 | it('should return an empty string', () => { 170 | const content: OpenGraphRequest = { 171 | title: 'foo', 172 | }; 173 | 174 | const links = injectFonts(content); 175 | 176 | expect(links.length).toBe(0); 177 | }); 178 | }); 179 | 180 | describe('injectScripts', () => { 181 | it('should return empty string', () => { 182 | const content: OpenGraphRequest = { 183 | title: 'foo', 184 | }; 185 | const output = injectScripts(content); 186 | 187 | expect(output).toBe(''); 188 | }); 189 | 190 | it('should inject custom fonts', () => { 191 | const content: OpenGraphRequest = { 192 | title: 'foo', 193 | fontSans: 'Open Sans', 194 | fontMono: 'Hack', 195 | fontSerif: 'Merriweather', 196 | }; 197 | const output = injectScripts(content); 198 | 199 | expect(output).toMatch(/sans: \['Open Sans'\]/); 200 | expect(output).toMatch(/mono: \['Hack'\]/); 201 | expect(output).toMatch(/serif: \['Merriweather'\]/); 202 | }); 203 | }); 204 | 205 | describe('injectClassToElement', () => { 206 | it('should inject classes to element', () => { 207 | const el = '<p>Hello World!</p>'; 208 | const className = 'text-dark'; 209 | 210 | const got = injectClassToElement(el, className); 211 | 212 | expect(got).toBe('<p class="text-dark">Hello World!</p>'); 213 | }); 214 | 215 | it('should replace the default element', () => { 216 | const el = '<p>Hello World!</p>'; 217 | const className = 'text-dark'; 218 | 219 | const got = injectClassToElement(el, className, 'h1'); 220 | 221 | expect(got).toBe('<h1 class="text-dark">Hello World!</h1>'); 222 | }); 223 | }); 224 | }); 225 | 226 | describe('buildTemplate', () => { 227 | it('should replace all string templates with correct values', () => { 228 | const base = HERO_TEMPLATE; 229 | const map: TemplateMap = { 230 | fonts: '', 231 | scripts: '<script></script>', 232 | container: 'bg-gray-400', 233 | image: '<img src="test.png />', 234 | title: '<h1 class="text-2xl">Test</h1>', 235 | subtitle: '<h3 class="text-sm">Ting</h3>', 236 | footer: '<p>a</p>', 237 | }; 238 | 239 | const result = buildTemplate(base, map); 240 | 241 | expect(result).toBe(`<!DOCTYPE html> 242 | <html> 243 | <head> 244 | <meta charset="UTF-8"> 245 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> 246 | 247 | <script src="https://cdn.tailwindcss.com"></script> 248 | <script></script> 249 | </head> 250 | 251 | <body class="grid grid-rows-3 place-items-center bg-gray-400"> 252 | <div class="row-start-2 flex flex-col items-center text-center"> 253 | <img src="test.png /> 254 | <h1 class="text-2xl">Test</h1> 255 | <h3 class="text-sm">Ting</h3> 256 | </div> 257 | 258 | <div class="self-end row-start-3 text-center"> 259 | <p>a</p> 260 | </div> 261 | </body> 262 | </html>`); 263 | }); 264 | 265 | it('should replace all keys that are not present with an empty string', () => { 266 | const base = HERO_TEMPLATE; 267 | const map: Partial<TemplateMap> = { 268 | container: 'bg-gray-900', 269 | title: '<h1 class="text-2xl">Test</h1>', 270 | }; 271 | 272 | const result = buildTemplate(base, map); 273 | 274 | expect(result).toBe(`<!DOCTYPE html> 275 | <html> 276 | <head> 277 | <meta charset="UTF-8"> 278 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> 279 | 280 | <script src="https://cdn.tailwindcss.com"></script> 281 | 282 | </head> 283 | 284 | <body class="grid grid-rows-3 place-items-center bg-gray-900"> 285 | <div class="row-start-2 flex flex-col items-center text-center"> 286 | 287 | <h1 class="text-2xl">Test</h1> 288 | 289 | </div> 290 | 291 | <div class="self-end row-start-3 text-center"> 292 | 293 | </div> 294 | </body> 295 | </html>`); 296 | }); 297 | }); 298 | -------------------------------------------------------------------------------- /src/lib/injector.ts: -------------------------------------------------------------------------------- 1 | import type { OpenGraphRequest, TemplateMap } from './types'; 2 | 3 | interface UtilMap { 4 | target: RegExp[]; 5 | default: string; 6 | } 7 | 8 | type OpenGraphElement = 'container' | 'title' | 'subtitle' | 'footer' | 'image'; 9 | 10 | const utilsMap: Record<OpenGraphElement, UtilMap[]> = { 11 | container: [ 12 | { 13 | target: [/\bw-.+\b/], 14 | default: 'w-screen', 15 | }, 16 | { 17 | target: [/\bh-.+\b/], 18 | default: 'h-screen', 19 | }, 20 | { 21 | target: [/\bp-.+\b/], 22 | default: 'p-16', 23 | }, 24 | ], 25 | title: [ 26 | { 27 | target: [ 28 | /\btext-([\d.]+)?(xs|sm|base|md|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|screen|px|rem|em|ch|vh|vw|ex)\b/, 29 | ], 30 | default: 'text-7xl', 31 | }, 32 | ], 33 | subtitle: [ 34 | { 35 | target: [ 36 | /\btext-([\d.]+)?(xs|sm|base|md|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|screen|px|rem|em|ch|vh|vw|ex)\b/, 37 | ], 38 | default: 'text-3xl', 39 | }, 40 | ], 41 | footer: [ 42 | { 43 | target: [ 44 | /\btext-([\d.]+)?(xs|sm|base|md|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|px|rem|em|ch|vh|vw|ex)\b/, 45 | ], 46 | default: 'text-sm', 47 | }, 48 | ], 49 | image: [ 50 | { 51 | target: [/\bobject-(contain|cover|fill|none|scale-down)\b/], 52 | default: 'object-contain', 53 | }, 54 | ], 55 | }; 56 | 57 | /** 58 | * Inject default styles to user-provided style if custom styles are 59 | * not provided 60 | * 61 | * @param {string} style user-provided CSS classes 62 | * @param {OpenGraphElement} el element type to be applied 63 | * @returns {string} user-provided CSS classes with fallback values 64 | */ 65 | export function injectDefaultClasses( 66 | style: string, 67 | el: OpenGraphElement 68 | ): string { 69 | let injected = style.trim(); 70 | 71 | for (const utils of utilsMap[el]) { 72 | const hasUtils = utils.target.some(p => p.test(style)); 73 | 74 | if (!hasUtils) { 75 | injected = `${injected} ${utils.default}`; 76 | } 77 | } 78 | 79 | return injected.trim(); 80 | } 81 | 82 | /** 83 | * Inject CSS classes to markdown-generated element 84 | * 85 | * @param {string} el HTML element in string form 86 | * @param {string} className CSS classes to inject 87 | * @param {string?} as output HTML tag, optional 88 | * @returns {string} HTML element with the provided class 89 | */ 90 | export function injectClassToElement( 91 | el: string, 92 | className: string, 93 | as?: string 94 | ): string { 95 | el = el.trim(); 96 | const tag = el.match(/^<(\w+)>/) as RegExpMatchArray; 97 | 98 | if (!as) { 99 | as = tag.pop(); 100 | } 101 | 102 | const textContent = el.slice(tag[0].length, -(tag[0].length + 1)); 103 | 104 | return `<${as} class="${className}">${textContent}</${as}>`; 105 | } 106 | 107 | /** 108 | * Dynamically generated Google Fonts links based on user input 109 | * 110 | * @param {OpenGraphRequest} content user input 111 | * @returns {string} font links 112 | */ 113 | export function injectFonts(content: OpenGraphRequest): string { 114 | const links: string[] = []; 115 | 116 | const fonts = Object.entries(content).filter( 117 | ([key, value]) => key.startsWith('font') && Boolean(value) 118 | ); 119 | 120 | if (fonts.length) { 121 | links.push( 122 | '<link rel="preconnect" href="https://fonts.googleapis.com">', 123 | '<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>' 124 | ); 125 | } 126 | 127 | links.push( 128 | ...fonts.map( 129 | font => 130 | `<link href="https://fonts.googleapis.com/css2?family=${font[1]}:wght@100;200;300;400;500;600;700;800;900&display=swap" rel="stylesheet">` 131 | ) 132 | ); 133 | 134 | return links.join('\n'); 135 | } 136 | 137 | /** 138 | * Dynamically generate Tailwind config based on user-input 139 | * 140 | * @param {OpenGraphRequest} content user input 141 | * @returns {string} Tailwind config as a string 142 | */ 143 | export function injectScripts(content: OpenGraphRequest): string { 144 | const fonts = Object.entries(content).filter( 145 | ([key, value]) => key.startsWith('font') && Boolean(value) 146 | ); 147 | 148 | if (!fonts.length) { 149 | return ''; 150 | } 151 | 152 | return `<script> 153 | tailwind.config = { 154 | theme: { 155 | fontFamily: { 156 | ${fonts 157 | .map( 158 | ([key, value]) => 159 | `${key.replace('font', '').toLowerCase()}: ['${value}']` 160 | ) 161 | .join(',\n')} 162 | } 163 | } 164 | } 165 | </script>`; 166 | } 167 | 168 | /** 169 | * Build template based on base template and user-defined values 170 | * 171 | * @param {string} base base template 172 | * @param {TemplateMap} value template replacement 173 | * @returns {string} template replaced with real values 174 | */ 175 | export function buildTemplate( 176 | base: string, 177 | value: Partial<TemplateMap> 178 | ): string { 179 | return base.replace( 180 | /{([^{}]+)}/g, 181 | (_, key: keyof TemplateMap) => value[key] || '' 182 | ); 183 | } 184 | -------------------------------------------------------------------------------- /src/lib/puppeteer.ts: -------------------------------------------------------------------------------- 1 | import chromium from 'chrome-aws-lambda'; 2 | 3 | import type { Page, ScreenshotOptions } from 'puppeteer-core'; 4 | import { EMOJI } from './constant/font'; 5 | import type { PageOptions } from './types'; 6 | 7 | let page: Page; 8 | 9 | /** 10 | * Get singleton page for screenshot purpose 11 | * 12 | * @returns {Promise<Page>} Puppeteer webpage 13 | */ 14 | async function getPage(): Promise<Page> { 15 | // Re-use the page if exists 16 | if (page) { 17 | return page; 18 | } 19 | 20 | const options = process.env.AWS_REGION 21 | ? { 22 | args: chromium.args, 23 | defaultViewport: chromium.defaultViewport, 24 | executablePath: await chromium.executablePath, 25 | headless: chromium.headless, 26 | ignoreHTTPSErrors: true, 27 | } 28 | : { 29 | args: [], 30 | defaultViewport: chromium.defaultViewport, 31 | executablePath: 32 | // Change this accordingly 33 | process.platform === 'win32' 34 | ? 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe' 35 | : process.platform === 'linux' 36 | ? '/usr/bin/google-chrome' 37 | : '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', 38 | headless: false, 39 | ignoreHTTPSErrors: true, 40 | }; 41 | 42 | await chromium.font(EMOJI); 43 | 44 | const browser = await chromium.puppeteer.launch(options); 45 | const pages = await browser.pages(); 46 | 47 | if (pages) { 48 | page = pages[0]; 49 | } else { 50 | const newPage = await browser.newPage(); 51 | page = newPage; 52 | } 53 | 54 | return page; 55 | } 56 | 57 | /** 58 | * Render an HTML content as a webpage screen and 59 | * capture it. 60 | * 61 | * @param {string} html HTML content to be captured 62 | * @param {PageOptions} options page rendering options 63 | * @returns {Promise<Buffer>} image file 64 | */ 65 | export async function captureScreen( 66 | html: string, 67 | options: PageOptions 68 | ): Promise<Buffer> { 69 | const page = await getPage(); 70 | await page.setViewport({ 71 | width: options.dimension.width as number, 72 | height: options.dimension.height as number, 73 | }); 74 | await page.setContent(html, { waitUntil: 'networkidle0' }); 75 | 76 | const ssOptions: ScreenshotOptions = { 77 | type: options.format, 78 | }; 79 | 80 | if (options.format === 'jpeg') { 81 | ssOptions.quality = options.compress ? 70 : 90; 82 | } 83 | 84 | const file = (await page.screenshot(ssOptions)) as Buffer; 85 | 86 | return file; 87 | } 88 | -------------------------------------------------------------------------------- /src/lib/sanitizer.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest'; 2 | 3 | import { sanitize } from '@/lib/sanitizer'; 4 | 5 | describe('sanitize', () => { 6 | it.concurrent('should sanitize escapable inputs', () => { 7 | const input = '<script>alert("XSS");</script>'; 8 | const output = sanitize(input); 9 | 10 | expect(output).toBe('<script>alert("XSS");</script>'); 11 | }); 12 | 13 | it.concurrent('should do nothing', () => { 14 | const input = '**Hello** World'; 15 | const output = sanitize(input); 16 | 17 | expect(output).toBe(input); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /src/lib/sanitizer.ts: -------------------------------------------------------------------------------- 1 | const entities: Record<string, string> = { 2 | '<': '<', 3 | '>': '>', 4 | '&': '&', 5 | '"': '"', 6 | "'": ''', 7 | }; 8 | 9 | /** 10 | * Sanitize content into HTML entities 11 | * 12 | * @param {string} str raw HTML contents 13 | * @returns {string} escaped HTML contents 14 | */ 15 | export function sanitize(str: string): string { 16 | return str.replace(/[&<>"']/g, key => entities[key]); 17 | } 18 | -------------------------------------------------------------------------------- /src/lib/template/blank.ts: -------------------------------------------------------------------------------- 1 | export const BLANK_TEMPLATE = `<!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="UTF-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 | {fonts} 7 | <script src="https://cdn.tailwindcss.com"></script> 8 | {scripts} 9 | </head> 10 | 11 | <body class="{container}"> 12 | {image} 13 | {title} 14 | {subtitle} 15 | {footer} 16 | </body> 17 | </html>`; 18 | -------------------------------------------------------------------------------- /src/lib/template/hero.ts: -------------------------------------------------------------------------------- 1 | export const HERO_TEMPLATE = `<!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="UTF-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 | {fonts} 7 | <script src="https://cdn.tailwindcss.com"></script> 8 | {scripts} 9 | </head> 10 | 11 | <body class="grid grid-rows-3 place-items-center {container}"> 12 | <div class="row-start-2 flex flex-col items-center text-center"> 13 | {image} 14 | {title} 15 | {subtitle} 16 | </div> 17 | 18 | <div class="self-end row-start-3 text-center"> 19 | {footer} 20 | </div> 21 | </body> 22 | </html>`; 23 | -------------------------------------------------------------------------------- /src/lib/template/image-left.ts: -------------------------------------------------------------------------------- 1 | export const IMAGE_LEFT = `<!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="UTF-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 | {fonts} 7 | <script src="https://cdn.tailwindcss.com"></script> 8 | {scripts} 9 | </head> 10 | 11 | <body class="grid grid-cols-2 {container}"> 12 | <div class="overflow-hidden mr-auto"> 13 | {image} 14 | </div> 15 | 16 | <div class="flex flex-col justify-between"> 17 | <div> 18 | {subtitle} 19 | {title} 20 | </div> 21 | 22 | {footer} 23 | </div> 24 | </body> 25 | </html>`; 26 | -------------------------------------------------------------------------------- /src/lib/template/image-right.ts: -------------------------------------------------------------------------------- 1 | export const IMAGE_RIGHT = `<!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta charset="UTF-8"> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 | {fonts} 7 | <script src="https://cdn.tailwindcss.com"></script> 8 | {scripts} 9 | </head> 10 | 11 | <body class="grid grid-cols-2 {container}"> 12 | <div class="flex flex-col justify-between"> 13 | <div> 14 | {subtitle} 15 | {title} 16 | </div> 17 | 18 | {footer} 19 | </div> 20 | 21 | <div class="overflow-hidden ml-auto"> 22 | {image} 23 | </div> 24 | </body> 25 | </html>`; 26 | -------------------------------------------------------------------------------- /src/lib/template/template.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest'; 2 | import { getTemplate } from './template'; 3 | 4 | import { BLANK_TEMPLATE } from './blank'; 5 | import { HERO_TEMPLATE } from './hero'; 6 | 7 | describe('getTemplate', () => { 8 | it('should return hero template', () => { 9 | const key = 'hero'; 10 | const template = getTemplate(key); 11 | 12 | expect(template).toBe(HERO_TEMPLATE); 13 | }); 14 | 15 | it('should return blank template', () => { 16 | const key = 'ERROR'; 17 | const template = getTemplate(key); 18 | 19 | expect(template).toBe(BLANK_TEMPLATE); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /src/lib/template/template.ts: -------------------------------------------------------------------------------- 1 | import { BLANK_TEMPLATE } from './blank'; 2 | import { HERO_TEMPLATE } from './hero'; 3 | import { IMAGE_LEFT } from './image-left'; 4 | import { IMAGE_RIGHT } from './image-right'; 5 | 6 | const TEMPLATES: Record<string, string> = { 7 | 'hero': HERO_TEMPLATE, 8 | 'blank': BLANK_TEMPLATE, 9 | 'image-left': IMAGE_LEFT, 10 | 'image-right': IMAGE_RIGHT, 11 | }; 12 | 13 | /** 14 | * Get the template string for open graph generation by key 15 | * 16 | * @param {string} key template identifier 17 | * @returns {string} HTML template for open graph generation, will return `blank` 18 | * if the key is not recognized 19 | */ 20 | export function getTemplate(key: string): string { 21 | if (key in TEMPLATES) { 22 | return TEMPLATES[key]; 23 | } 24 | 25 | return TEMPLATES.blank; 26 | } 27 | -------------------------------------------------------------------------------- /src/lib/types.ts: -------------------------------------------------------------------------------- 1 | export interface Dimension { 2 | width: number; 3 | height: number; 4 | } 5 | 6 | export interface PageOptions { 7 | dimension: Dimension; 8 | format: 'jpeg' | 'png'; 9 | compress: boolean; 10 | } 11 | 12 | export interface OpenGraphRequest { 13 | title: string; 14 | subtitle?: string; 15 | footer?: string; 16 | image?: string; 17 | containerClass?: string; 18 | titleClass?: string; 19 | subtitleClass?: string; 20 | footerClass?: string; 21 | imageClass?: string; 22 | fontSans?: string; 23 | fontSerif?: string; 24 | fontMono?: string; 25 | template?: string; 26 | } 27 | 28 | export interface TemplateMap { 29 | fonts: string; 30 | scripts: string; 31 | container: string; 32 | image: string; 33 | title: string; 34 | subtitle: string; 35 | footer: string; 36 | } 37 | -------------------------------------------------------------------------------- /src/lib/utils.test.ts: -------------------------------------------------------------------------------- 1 | import fetch from 'isomorphic-unfetch'; 2 | 3 | import { describe, it, beforeAll, afterEach, afterAll, expect } from 'vitest'; 4 | 5 | import { HEIGHT, WIDTH } from '@/constant/api'; 6 | 7 | import { imgMockServer } from '@/mocks/server'; 8 | import { isValidImage, generatePageOptions } from '@/lib/utils'; 9 | 10 | describe('isValidImage', () => { 11 | beforeAll(() => { 12 | global.fetch = fetch; 13 | imgMockServer.listen(); 14 | }); 15 | 16 | afterEach(() => { 17 | imgMockServer.resetHandlers(); 18 | }); 19 | 20 | afterAll(() => { 21 | imgMockServer.close(); 22 | }); 23 | 24 | it.concurrent('should return true', async () => { 25 | const result = await isValidImage('https://foo.bar/test.png'); 26 | expect(result).toBe(true); 27 | }); 28 | 29 | it.concurrent( 30 | 'should return false when image cannot be fetched', 31 | async () => { 32 | const result = await isValidImage('https://foo.bar/foo.jpeg'); 33 | expect(result).toBe(false); 34 | } 35 | ); 36 | 37 | it.concurrent( 38 | 'should return false when response is not a supported image', 39 | async () => { 40 | const result = await isValidImage('https://foo.bar/baz.html'); 41 | expect(result).toBe(false); 42 | } 43 | ); 44 | 45 | it.concurrent('should return false when url is invalid', async () => { 46 | const result = await isValidImage('ganteng'); 47 | expect(result).toBe(false); 48 | }); 49 | }); 50 | 51 | describe('generatePageOptions', () => { 52 | it('should fallback to JPG if format does not exist', () => { 53 | const req = {}; 54 | 55 | const opts = generatePageOptions(req); 56 | 57 | expect(opts.format).toBe('jpeg'); 58 | }); 59 | 60 | it('should fallback to JPG if format is illegal', () => { 61 | const req = { 62 | format: 'webp', 63 | }; 64 | 65 | const opts = generatePageOptions(req); 66 | 67 | expect(opts.format).toBe('jpeg'); 68 | }); 69 | 70 | it('should fix illegal width and height', () => { 71 | const req = { 72 | width: '-1', 73 | height: '0', 74 | format: 'png', 75 | }; 76 | 77 | const opts = generatePageOptions(req); 78 | 79 | expect(opts.dimension.width).toBe(WIDTH); 80 | expect(opts.dimension.height).toBe(HEIGHT); 81 | }); 82 | }); 83 | -------------------------------------------------------------------------------- /src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import fetch from 'isomorphic-unfetch'; 2 | 3 | import { HEIGHT, WIDTH } from './../constant/api'; 4 | 5 | import type { PageOptions } from './types'; 6 | 7 | /** 8 | * Check if the provided image url directs to an image resource 9 | * 10 | * @param {string} url provided image url 11 | * @returns {Promise<boolean>} whether if the provided URL responds 12 | * with an image or not 13 | */ 14 | export async function isValidImage(url: string): Promise<boolean> { 15 | try { 16 | const parsedUrl = new URL(url); 17 | const result = await fetch(parsedUrl.toString()); 18 | 19 | return ( 20 | result.ok && 21 | Boolean(result.headers.get('Content-Type')) && 22 | (result.headers.get('Content-Type') as string).startsWith('image') 23 | ); 24 | } catch (err) { 25 | return false; 26 | } 27 | } 28 | 29 | /** 30 | * Validate user request and perform auto correction with 31 | * default values 32 | * 33 | * @param {Record<string, string>} req open graph request 34 | * @returns {PageOptions} options for screen capture 35 | */ 36 | export function generatePageOptions(req: Record<string, string>): PageOptions { 37 | const width = Number.parseInt(req.width, 10); 38 | const height = Number.parseInt(req.height, 10); 39 | 40 | return { 41 | dimension: { 42 | width: !width || width < 0 ? WIDTH : width, 43 | height: !height || height < 0 ? HEIGHT : height, 44 | }, 45 | format: req.format === 'png' ? 'png' : 'jpeg', 46 | compress: 'compress' in req || Boolean(req.compress), 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /src/mocks/img.ts: -------------------------------------------------------------------------------- 1 | /* c8 ignore start */ 2 | import { rest } from 'msw'; 3 | 4 | export const handlers = [ 5 | rest.get('https://foo.bar/test.png', (req, res, ctx) => 6 | res(ctx.status(200), ctx.set('Content-Type', 'image/png')) 7 | ), 8 | 9 | rest.get('https://foo.bar/foo.jpeg', (req, res, ctx) => res(ctx.status(404))), 10 | 11 | rest.get('https://foo.bar/baz.html', (req, res, ctx) => 12 | res(ctx.status(200), ctx.set('Content-Type', 'text/html')) 13 | ), 14 | ]; 15 | /* c8 ignore end */ 16 | -------------------------------------------------------------------------------- /src/mocks/server.ts: -------------------------------------------------------------------------------- 1 | import { setupServer } from 'msw/node'; 2 | import { handlers } from '@/mocks/img'; 3 | 4 | export const imgMockServer = setupServer(...handlers); 5 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "incremental": true, 4 | "target": "esnext", 5 | "lib": [ 6 | "DOM", 7 | "ES2020.Promise" 8 | ], 9 | "jsx": "preserve", 10 | "module": "esnext", 11 | "moduleResolution": "node", 12 | "baseUrl": ".", 13 | "paths": { 14 | "@/*": [ 15 | "src/*" 16 | ] 17 | }, 18 | "resolveJsonModule": true, 19 | "allowJs": true, 20 | "checkJs": true, 21 | "outDir": "./dist", 22 | "esModuleInterop": true, 23 | "forceConsistentCasingInFileNames": true, 24 | "strict": true, 25 | "skipLibCheck": true, 26 | "isolatedModules": true 27 | }, 28 | "include": [ 29 | "**/*.ts", 30 | ], 31 | "exclude": [ 32 | "node_modules", 33 | "src/mocks/*.ts", 34 | "vite.config.ts", 35 | "**/*.test.ts" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "incremental": true, 4 | "target": "esnext", 5 | "lib": [ 6 | "DOM", 7 | "ES2020.Promise" 8 | ], 9 | "jsx": "preserve", 10 | "module": "esnext", 11 | "moduleResolution": "node", 12 | "baseUrl": ".", 13 | "paths": { 14 | "@/*": [ 15 | "src/*" 16 | ] 17 | }, 18 | "allowJs": true, 19 | "checkJs": true, 20 | "outDir": "./dist", 21 | "esModuleInterop": true, 22 | "forceConsistentCasingInFileNames": true, 23 | "strict": true, 24 | "skipLibCheck": true, 25 | "isolatedModules": true 26 | }, 27 | "include": [ 28 | "**/*.ts", 29 | ], 30 | "exclude": [ 31 | "node_modules" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "cleanUrls": true, 3 | "functions": { 4 | "api/og/[title].ts": { 5 | "excludeFiles": "{+(.vercel|docs|.github)/**,pnpm-lock.yaml,README.md,.editorconfig,.eslintrc.js,.gitignore,.prettier.config.js,vite.config.ts}" 6 | } 7 | }, 8 | "headers": [ 9 | { 10 | "source": "/api/og/(.*)", 11 | "headers": [ 12 | { 13 | "key": "Cache-Control", 14 | "value": "public, immutable, no-transform, s-maxage=31536000, max-age=31536000" 15 | }, 16 | { 17 | "key": "Access-Control-Allow-Origin", 18 | "value": "*" 19 | }, 20 | { 21 | "key": "X-Powered-By", 22 | "value": "Windgraph" 23 | } 24 | ] 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import { resolve } from 'path'; 3 | 4 | export default defineConfig({ 5 | resolve: { 6 | alias: { 7 | '@': resolve(__dirname, './src'), 8 | }, 9 | }, 10 | }); 11 | --------------------------------------------------------------------------------