├── .gitignore ├── README.md ├── dalle.py ├── image_categorization.py ├── image_laundering.py ├── image_search.py ├── image_splitter.py ├── multivision.py ├── package-lock.json ├── package.json ├── price_scraping.py ├── requirements.txt ├── screenshot.js ├── screenshot.py ├── sketch_to_site.py ├── vision.py ├── website_check.py └── website_check_init.py /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | node_modules/ 3 | screenshots/ 4 | splits/ 5 | images/ 6 | code.html 7 | creation.webp 8 | image_data.json 9 | original_screenshots.json 10 | translator.jpg 11 | screenshot.jpg 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GPT-4 Vision Examples 2 | 3 | These are some simple example use cases for the GPT-4 Vision API 4 | Video: https://www.youtube.com/watch?v=qEoHdscmFck 5 | 6 | ## 1. Image categorization 7 | 8 | Create keywords for images in the `images` folder and search for images based on the keywords 9 | 10 | - Create keywords: `image_categorization.py` 11 | - Search: `image_search.py` 12 | 13 | ## 2. Image laundering 14 | 15 | Create a replica of an image by feeding its description from GPT-4 Vision to DALL-E 3 16 | 17 | - `image_laundering.py IMAGE_FILE` 18 | 19 | ## 3. Web scraping 20 | 21 | Scrape prices from Amazon search results screenshot 22 | 23 | - `price_scraping.py` 24 | 25 | ## 4. Website monitoring 26 | 27 | Monitor changes to a website based on screenshots 28 | 29 | - Initialize: `website_check_init.py` 30 | - Check changes: `website_check.py` 31 | 32 | ## 5. Sketch to site 33 | 34 | Convert a sketch of a website / web app into the HTML and CSS 35 | 36 | - `sketch_to_site.py IMAGE_FILE` 37 | -------------------------------------------------------------------------------- /dalle.py: -------------------------------------------------------------------------------- 1 | from openai import OpenAI 2 | import base64 3 | 4 | model = OpenAI() 5 | 6 | def make(prompt="Something cool", output_file="creation.webp"): 7 | response = model.images.generate( 8 | model="dall-e-3", 9 | prompt=prompt, 10 | size="1024x1024", 11 | quality="standard", 12 | response_format="b64_json", 13 | n=1, 14 | ) 15 | 16 | image_b64 = response.data[0].b64_json 17 | 18 | with open(output_file, "wb") as f: 19 | f.write(base64.b64decode(image_b64)) 20 | 21 | return output_file 22 | -------------------------------------------------------------------------------- /image_categorization.py: -------------------------------------------------------------------------------- 1 | import vision 2 | import json 3 | import os 4 | 5 | data = {} 6 | 7 | if not os.path.exists("images"): 8 | os.mkdir("images") 9 | 10 | for image in os.listdir("images"): 11 | print(image) 12 | 13 | keywords = vision.look( 14 | image_path="images/"+image, 15 | prompt="Make a comma separated list of keywords that describe this image" 16 | ).split(", ") 17 | 18 | data[image] = keywords 19 | 20 | with open("image_data.json", "w") as f: 21 | json.dump(data, f, indent=4) 22 | 23 | print("DONE!") 24 | -------------------------------------------------------------------------------- /image_laundering.py: -------------------------------------------------------------------------------- 1 | import vision 2 | import dalle 3 | import sys 4 | 5 | if len(sys.argv) < 2: 6 | print(f"Usage: {sys.argv[0]} IMAGE_FILE") 7 | sys.exit(1) 8 | 9 | image_file = sys.argv[1] 10 | 11 | original = vision.look(image_file) 12 | laundered = dalle.make(original) 13 | 14 | print(laundered) 15 | -------------------------------------------------------------------------------- /image_search.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | with open("image_data.json") as f: 4 | image_data = json.load(f) 5 | 6 | search_words = input("Search: ").strip().split(" ") 7 | 8 | for image, keywords in image_data.items(): 9 | found = False 10 | for keyword in keywords: 11 | for word in search_words: 12 | if word in keyword: 13 | found = True 14 | break 15 | if found: 16 | print("images/"+image) 17 | break 18 | -------------------------------------------------------------------------------- /image_splitter.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | import os 3 | 4 | def split(input_image_path, output_folder, piece_height, offset=0): 5 | if not os.path.exists(output_folder): 6 | os.mkdir(output_folder) 7 | 8 | # Open the input image 9 | original_image = Image.open(input_image_path) 10 | 11 | # Get the width and height of the original image 12 | width, height = original_image.size 13 | 14 | # Initialize pieces and fist piece size 15 | pieces = [] 16 | upper = 0 17 | lower = piece_height 18 | 19 | # Loop to split the image vertically 20 | while lower <= height: 21 | left = 0 22 | right = width 23 | 24 | # Crop the piece from the original image 25 | piece = original_image.crop((left, upper, right, lower)) 26 | 27 | # Move the crop area down 28 | upper += piece_height - offset 29 | lower += piece_height - offset 30 | 31 | # Save the piece to the output folder with a unique name 32 | piece_file = f"{output_folder}/piece_{len(pieces)}.jpg" 33 | piece.save(piece_file) 34 | 35 | # Add piece filename to return value 36 | pieces.append(piece_file) 37 | 38 | return pieces 39 | -------------------------------------------------------------------------------- /multivision.py: -------------------------------------------------------------------------------- 1 | from openai import OpenAI 2 | import base64 3 | 4 | model = OpenAI() 5 | 6 | def image_b64(image_path): 7 | with open(image_path, "rb") as f: 8 | return base64.b64encode(f.read()).decode() 9 | 10 | def look( 11 | image_paths: list[str] | str, 12 | prompt="Describe this image", 13 | ): 14 | if not isinstance(image_paths, list): 15 | image_paths = [image_paths] 16 | 17 | images = [] 18 | 19 | for image in image_paths: 20 | b64_image = image_b64(image) 21 | images.append({ 22 | "type": "image_url", 23 | "image_url": f"data:image/jpeg;base64,{b64_image}", 24 | }) 25 | 26 | response = model.chat.completions.create( 27 | model="gpt-4-vision-preview", 28 | messages=[ 29 | { 30 | "role": "user", 31 | "content": images + [ 32 | { 33 | "type": "text", 34 | "text": prompt, 35 | } 36 | ] 37 | } 38 | ], 39 | max_tokens=1024, 40 | ) 41 | 42 | message = response.choices[0].message 43 | return message.content 44 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gpt4v", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "dependencies": { 8 | "puppeteer": "^21.5.2", 9 | "puppeteer-extra": "^3.3.6", 10 | "puppeteer-extra-plugin-stealth": "^2.11.2" 11 | } 12 | }, 13 | "node_modules/@babel/code-frame": { 14 | "version": "7.23.4", 15 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.4.tgz", 16 | "integrity": "sha512-r1IONyb6Ia+jYR2vvIDhdWdlTGhqbBoFqLTQidzZ4kepUFH15ejXvFHxCVbtl7BOXIudsIubf4E81xeA3h3IXA==", 17 | "dependencies": { 18 | "@babel/highlight": "^7.23.4", 19 | "chalk": "^2.4.2" 20 | }, 21 | "engines": { 22 | "node": ">=6.9.0" 23 | } 24 | }, 25 | "node_modules/@babel/helper-validator-identifier": { 26 | "version": "7.22.20", 27 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", 28 | "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", 29 | "engines": { 30 | "node": ">=6.9.0" 31 | } 32 | }, 33 | "node_modules/@babel/highlight": { 34 | "version": "7.23.4", 35 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", 36 | "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", 37 | "dependencies": { 38 | "@babel/helper-validator-identifier": "^7.22.20", 39 | "chalk": "^2.4.2", 40 | "js-tokens": "^4.0.0" 41 | }, 42 | "engines": { 43 | "node": ">=6.9.0" 44 | } 45 | }, 46 | "node_modules/@puppeteer/browsers": { 47 | "version": "1.8.0", 48 | "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.8.0.tgz", 49 | "integrity": "sha512-TkRHIV6k2D8OlUe8RtG+5jgOF/H98Myx0M6AOafC8DdNVOFiBSFa5cpRDtpm8LXOa9sVwe0+e6Q3FC56X/DZfg==", 50 | "dependencies": { 51 | "debug": "4.3.4", 52 | "extract-zip": "2.0.1", 53 | "progress": "2.0.3", 54 | "proxy-agent": "6.3.1", 55 | "tar-fs": "3.0.4", 56 | "unbzip2-stream": "1.4.3", 57 | "yargs": "17.7.2" 58 | }, 59 | "bin": { 60 | "browsers": "lib/cjs/main-cli.js" 61 | }, 62 | "engines": { 63 | "node": ">=16.3.0" 64 | } 65 | }, 66 | "node_modules/@tootallnate/quickjs-emscripten": { 67 | "version": "0.23.0", 68 | "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", 69 | "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" 70 | }, 71 | "node_modules/@types/debug": { 72 | "version": "4.1.12", 73 | "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", 74 | "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", 75 | "dependencies": { 76 | "@types/ms": "*" 77 | } 78 | }, 79 | "node_modules/@types/ms": { 80 | "version": "0.7.34", 81 | "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", 82 | "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" 83 | }, 84 | "node_modules/@types/node": { 85 | "version": "20.10.0", 86 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.0.tgz", 87 | "integrity": "sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==", 88 | "optional": true, 89 | "dependencies": { 90 | "undici-types": "~5.26.4" 91 | } 92 | }, 93 | "node_modules/@types/yauzl": { 94 | "version": "2.10.3", 95 | "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", 96 | "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", 97 | "optional": true, 98 | "dependencies": { 99 | "@types/node": "*" 100 | } 101 | }, 102 | "node_modules/agent-base": { 103 | "version": "7.1.0", 104 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", 105 | "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", 106 | "dependencies": { 107 | "debug": "^4.3.4" 108 | }, 109 | "engines": { 110 | "node": ">= 14" 111 | } 112 | }, 113 | "node_modules/ansi-regex": { 114 | "version": "5.0.1", 115 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 116 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 117 | "engines": { 118 | "node": ">=8" 119 | } 120 | }, 121 | "node_modules/ansi-styles": { 122 | "version": "3.2.1", 123 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 124 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 125 | "dependencies": { 126 | "color-convert": "^1.9.0" 127 | }, 128 | "engines": { 129 | "node": ">=4" 130 | } 131 | }, 132 | "node_modules/argparse": { 133 | "version": "2.0.1", 134 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 135 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" 136 | }, 137 | "node_modules/arr-union": { 138 | "version": "3.1.0", 139 | "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", 140 | "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", 141 | "engines": { 142 | "node": ">=0.10.0" 143 | } 144 | }, 145 | "node_modules/ast-types": { 146 | "version": "0.13.4", 147 | "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", 148 | "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", 149 | "dependencies": { 150 | "tslib": "^2.0.1" 151 | }, 152 | "engines": { 153 | "node": ">=4" 154 | } 155 | }, 156 | "node_modules/b4a": { 157 | "version": "1.6.4", 158 | "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", 159 | "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==" 160 | }, 161 | "node_modules/balanced-match": { 162 | "version": "1.0.2", 163 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 164 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 165 | }, 166 | "node_modules/base64-js": { 167 | "version": "1.5.1", 168 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 169 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 170 | "funding": [ 171 | { 172 | "type": "github", 173 | "url": "https://github.com/sponsors/feross" 174 | }, 175 | { 176 | "type": "patreon", 177 | "url": "https://www.patreon.com/feross" 178 | }, 179 | { 180 | "type": "consulting", 181 | "url": "https://feross.org/support" 182 | } 183 | ] 184 | }, 185 | "node_modules/basic-ftp": { 186 | "version": "5.0.3", 187 | "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.3.tgz", 188 | "integrity": "sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==", 189 | "engines": { 190 | "node": ">=10.0.0" 191 | } 192 | }, 193 | "node_modules/brace-expansion": { 194 | "version": "1.1.11", 195 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 196 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 197 | "dependencies": { 198 | "balanced-match": "^1.0.0", 199 | "concat-map": "0.0.1" 200 | } 201 | }, 202 | "node_modules/buffer": { 203 | "version": "5.7.1", 204 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 205 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 206 | "funding": [ 207 | { 208 | "type": "github", 209 | "url": "https://github.com/sponsors/feross" 210 | }, 211 | { 212 | "type": "patreon", 213 | "url": "https://www.patreon.com/feross" 214 | }, 215 | { 216 | "type": "consulting", 217 | "url": "https://feross.org/support" 218 | } 219 | ], 220 | "dependencies": { 221 | "base64-js": "^1.3.1", 222 | "ieee754": "^1.1.13" 223 | } 224 | }, 225 | "node_modules/buffer-crc32": { 226 | "version": "0.2.13", 227 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 228 | "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", 229 | "engines": { 230 | "node": "*" 231 | } 232 | }, 233 | "node_modules/callsites": { 234 | "version": "3.1.0", 235 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 236 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 237 | "engines": { 238 | "node": ">=6" 239 | } 240 | }, 241 | "node_modules/chalk": { 242 | "version": "2.4.2", 243 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 244 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 245 | "dependencies": { 246 | "ansi-styles": "^3.2.1", 247 | "escape-string-regexp": "^1.0.5", 248 | "supports-color": "^5.3.0" 249 | }, 250 | "engines": { 251 | "node": ">=4" 252 | } 253 | }, 254 | "node_modules/chromium-bidi": { 255 | "version": "0.4.33", 256 | "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.33.tgz", 257 | "integrity": "sha512-IxoFM5WGQOIAd95qrSXzJUv4eXIrh+RvU3rwwqIiwYuvfE7U/Llj4fejbsJnjJMUYCuGtVQsY2gv7oGl4aTNSQ==", 258 | "dependencies": { 259 | "mitt": "3.0.1", 260 | "urlpattern-polyfill": "9.0.0" 261 | }, 262 | "peerDependencies": { 263 | "devtools-protocol": "*" 264 | } 265 | }, 266 | "node_modules/cliui": { 267 | "version": "8.0.1", 268 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", 269 | "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", 270 | "dependencies": { 271 | "string-width": "^4.2.0", 272 | "strip-ansi": "^6.0.1", 273 | "wrap-ansi": "^7.0.0" 274 | }, 275 | "engines": { 276 | "node": ">=12" 277 | } 278 | }, 279 | "node_modules/clone-deep": { 280 | "version": "0.2.4", 281 | "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", 282 | "integrity": "sha512-we+NuQo2DHhSl+DP6jlUiAhyAjBQrYnpOk15rN6c6JSPScjiCLh8IbSU+VTcph6YS3o7mASE8a0+gbZ7ChLpgg==", 283 | "dependencies": { 284 | "for-own": "^0.1.3", 285 | "is-plain-object": "^2.0.1", 286 | "kind-of": "^3.0.2", 287 | "lazy-cache": "^1.0.3", 288 | "shallow-clone": "^0.1.2" 289 | }, 290 | "engines": { 291 | "node": ">=0.10.0" 292 | } 293 | }, 294 | "node_modules/color-convert": { 295 | "version": "1.9.3", 296 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 297 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 298 | "dependencies": { 299 | "color-name": "1.1.3" 300 | } 301 | }, 302 | "node_modules/color-name": { 303 | "version": "1.1.3", 304 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 305 | "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" 306 | }, 307 | "node_modules/concat-map": { 308 | "version": "0.0.1", 309 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 310 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 311 | }, 312 | "node_modules/cosmiconfig": { 313 | "version": "8.3.6", 314 | "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", 315 | "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", 316 | "dependencies": { 317 | "import-fresh": "^3.3.0", 318 | "js-yaml": "^4.1.0", 319 | "parse-json": "^5.2.0", 320 | "path-type": "^4.0.0" 321 | }, 322 | "engines": { 323 | "node": ">=14" 324 | }, 325 | "funding": { 326 | "url": "https://github.com/sponsors/d-fischer" 327 | }, 328 | "peerDependencies": { 329 | "typescript": ">=4.9.5" 330 | }, 331 | "peerDependenciesMeta": { 332 | "typescript": { 333 | "optional": true 334 | } 335 | } 336 | }, 337 | "node_modules/cross-fetch": { 338 | "version": "4.0.0", 339 | "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", 340 | "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", 341 | "dependencies": { 342 | "node-fetch": "^2.6.12" 343 | } 344 | }, 345 | "node_modules/data-uri-to-buffer": { 346 | "version": "6.0.1", 347 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.1.tgz", 348 | "integrity": "sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==", 349 | "engines": { 350 | "node": ">= 14" 351 | } 352 | }, 353 | "node_modules/debug": { 354 | "version": "4.3.4", 355 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 356 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 357 | "dependencies": { 358 | "ms": "2.1.2" 359 | }, 360 | "engines": { 361 | "node": ">=6.0" 362 | }, 363 | "peerDependenciesMeta": { 364 | "supports-color": { 365 | "optional": true 366 | } 367 | } 368 | }, 369 | "node_modules/deepmerge": { 370 | "version": "4.3.1", 371 | "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", 372 | "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", 373 | "engines": { 374 | "node": ">=0.10.0" 375 | } 376 | }, 377 | "node_modules/degenerator": { 378 | "version": "5.0.1", 379 | "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", 380 | "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", 381 | "dependencies": { 382 | "ast-types": "^0.13.4", 383 | "escodegen": "^2.1.0", 384 | "esprima": "^4.0.1" 385 | }, 386 | "engines": { 387 | "node": ">= 14" 388 | } 389 | }, 390 | "node_modules/devtools-protocol": { 391 | "version": "0.0.1203626", 392 | "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1203626.tgz", 393 | "integrity": "sha512-nEzHZteIUZfGCZtTiS1fRpC8UZmsfD1SiyPvaUNvS13dvKf666OAm8YTi0+Ca3n1nLEyu49Cy4+dPWpaHFJk9g==" 394 | }, 395 | "node_modules/emoji-regex": { 396 | "version": "8.0.0", 397 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 398 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 399 | }, 400 | "node_modules/end-of-stream": { 401 | "version": "1.4.4", 402 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 403 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 404 | "dependencies": { 405 | "once": "^1.4.0" 406 | } 407 | }, 408 | "node_modules/error-ex": { 409 | "version": "1.3.2", 410 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", 411 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", 412 | "dependencies": { 413 | "is-arrayish": "^0.2.1" 414 | } 415 | }, 416 | "node_modules/escalade": { 417 | "version": "3.1.1", 418 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 419 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 420 | "engines": { 421 | "node": ">=6" 422 | } 423 | }, 424 | "node_modules/escape-string-regexp": { 425 | "version": "1.0.5", 426 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 427 | "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", 428 | "engines": { 429 | "node": ">=0.8.0" 430 | } 431 | }, 432 | "node_modules/escodegen": { 433 | "version": "2.1.0", 434 | "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", 435 | "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", 436 | "dependencies": { 437 | "esprima": "^4.0.1", 438 | "estraverse": "^5.2.0", 439 | "esutils": "^2.0.2" 440 | }, 441 | "bin": { 442 | "escodegen": "bin/escodegen.js", 443 | "esgenerate": "bin/esgenerate.js" 444 | }, 445 | "engines": { 446 | "node": ">=6.0" 447 | }, 448 | "optionalDependencies": { 449 | "source-map": "~0.6.1" 450 | } 451 | }, 452 | "node_modules/esprima": { 453 | "version": "4.0.1", 454 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 455 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 456 | "bin": { 457 | "esparse": "bin/esparse.js", 458 | "esvalidate": "bin/esvalidate.js" 459 | }, 460 | "engines": { 461 | "node": ">=4" 462 | } 463 | }, 464 | "node_modules/estraverse": { 465 | "version": "5.3.0", 466 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 467 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 468 | "engines": { 469 | "node": ">=4.0" 470 | } 471 | }, 472 | "node_modules/esutils": { 473 | "version": "2.0.3", 474 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 475 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 476 | "engines": { 477 | "node": ">=0.10.0" 478 | } 479 | }, 480 | "node_modules/extract-zip": { 481 | "version": "2.0.1", 482 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", 483 | "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", 484 | "dependencies": { 485 | "debug": "^4.1.1", 486 | "get-stream": "^5.1.0", 487 | "yauzl": "^2.10.0" 488 | }, 489 | "bin": { 490 | "extract-zip": "cli.js" 491 | }, 492 | "engines": { 493 | "node": ">= 10.17.0" 494 | }, 495 | "optionalDependencies": { 496 | "@types/yauzl": "^2.9.1" 497 | } 498 | }, 499 | "node_modules/fast-fifo": { 500 | "version": "1.3.2", 501 | "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", 502 | "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" 503 | }, 504 | "node_modules/fd-slicer": { 505 | "version": "1.1.0", 506 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", 507 | "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", 508 | "dependencies": { 509 | "pend": "~1.2.0" 510 | } 511 | }, 512 | "node_modules/for-in": { 513 | "version": "1.0.2", 514 | "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", 515 | "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", 516 | "engines": { 517 | "node": ">=0.10.0" 518 | } 519 | }, 520 | "node_modules/for-own": { 521 | "version": "0.1.5", 522 | "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", 523 | "integrity": "sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==", 524 | "dependencies": { 525 | "for-in": "^1.0.1" 526 | }, 527 | "engines": { 528 | "node": ">=0.10.0" 529 | } 530 | }, 531 | "node_modules/fs-extra": { 532 | "version": "10.1.0", 533 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", 534 | "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", 535 | "dependencies": { 536 | "graceful-fs": "^4.2.0", 537 | "jsonfile": "^6.0.1", 538 | "universalify": "^2.0.0" 539 | }, 540 | "engines": { 541 | "node": ">=12" 542 | } 543 | }, 544 | "node_modules/fs.realpath": { 545 | "version": "1.0.0", 546 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 547 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" 548 | }, 549 | "node_modules/get-caller-file": { 550 | "version": "2.0.5", 551 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 552 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 553 | "engines": { 554 | "node": "6.* || 8.* || >= 10.*" 555 | } 556 | }, 557 | "node_modules/get-stream": { 558 | "version": "5.2.0", 559 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 560 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 561 | "dependencies": { 562 | "pump": "^3.0.0" 563 | }, 564 | "engines": { 565 | "node": ">=8" 566 | }, 567 | "funding": { 568 | "url": "https://github.com/sponsors/sindresorhus" 569 | } 570 | }, 571 | "node_modules/get-uri": { 572 | "version": "6.0.2", 573 | "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.2.tgz", 574 | "integrity": "sha512-5KLucCJobh8vBY1K07EFV4+cPZH3mrV9YeAruUseCQKHB58SGjjT2l9/eA9LD082IiuMjSlFJEcdJ27TXvbZNw==", 575 | "dependencies": { 576 | "basic-ftp": "^5.0.2", 577 | "data-uri-to-buffer": "^6.0.0", 578 | "debug": "^4.3.4", 579 | "fs-extra": "^8.1.0" 580 | }, 581 | "engines": { 582 | "node": ">= 14" 583 | } 584 | }, 585 | "node_modules/get-uri/node_modules/fs-extra": { 586 | "version": "8.1.0", 587 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", 588 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", 589 | "dependencies": { 590 | "graceful-fs": "^4.2.0", 591 | "jsonfile": "^4.0.0", 592 | "universalify": "^0.1.0" 593 | }, 594 | "engines": { 595 | "node": ">=6 <7 || >=8" 596 | } 597 | }, 598 | "node_modules/get-uri/node_modules/jsonfile": { 599 | "version": "4.0.0", 600 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 601 | "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", 602 | "optionalDependencies": { 603 | "graceful-fs": "^4.1.6" 604 | } 605 | }, 606 | "node_modules/get-uri/node_modules/universalify": { 607 | "version": "0.1.2", 608 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 609 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", 610 | "engines": { 611 | "node": ">= 4.0.0" 612 | } 613 | }, 614 | "node_modules/glob": { 615 | "version": "7.2.3", 616 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", 617 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 618 | "dependencies": { 619 | "fs.realpath": "^1.0.0", 620 | "inflight": "^1.0.4", 621 | "inherits": "2", 622 | "minimatch": "^3.1.1", 623 | "once": "^1.3.0", 624 | "path-is-absolute": "^1.0.0" 625 | }, 626 | "engines": { 627 | "node": "*" 628 | }, 629 | "funding": { 630 | "url": "https://github.com/sponsors/isaacs" 631 | } 632 | }, 633 | "node_modules/graceful-fs": { 634 | "version": "4.2.11", 635 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 636 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" 637 | }, 638 | "node_modules/has-flag": { 639 | "version": "3.0.0", 640 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 641 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 642 | "engines": { 643 | "node": ">=4" 644 | } 645 | }, 646 | "node_modules/http-proxy-agent": { 647 | "version": "7.0.0", 648 | "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", 649 | "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", 650 | "dependencies": { 651 | "agent-base": "^7.1.0", 652 | "debug": "^4.3.4" 653 | }, 654 | "engines": { 655 | "node": ">= 14" 656 | } 657 | }, 658 | "node_modules/https-proxy-agent": { 659 | "version": "7.0.2", 660 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", 661 | "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", 662 | "dependencies": { 663 | "agent-base": "^7.0.2", 664 | "debug": "4" 665 | }, 666 | "engines": { 667 | "node": ">= 14" 668 | } 669 | }, 670 | "node_modules/ieee754": { 671 | "version": "1.2.1", 672 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 673 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 674 | "funding": [ 675 | { 676 | "type": "github", 677 | "url": "https://github.com/sponsors/feross" 678 | }, 679 | { 680 | "type": "patreon", 681 | "url": "https://www.patreon.com/feross" 682 | }, 683 | { 684 | "type": "consulting", 685 | "url": "https://feross.org/support" 686 | } 687 | ] 688 | }, 689 | "node_modules/import-fresh": { 690 | "version": "3.3.0", 691 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 692 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 693 | "dependencies": { 694 | "parent-module": "^1.0.0", 695 | "resolve-from": "^4.0.0" 696 | }, 697 | "engines": { 698 | "node": ">=6" 699 | }, 700 | "funding": { 701 | "url": "https://github.com/sponsors/sindresorhus" 702 | } 703 | }, 704 | "node_modules/inflight": { 705 | "version": "1.0.6", 706 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 707 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 708 | "dependencies": { 709 | "once": "^1.3.0", 710 | "wrappy": "1" 711 | } 712 | }, 713 | "node_modules/inherits": { 714 | "version": "2.0.4", 715 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 716 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 717 | }, 718 | "node_modules/ip": { 719 | "version": "1.1.8", 720 | "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", 721 | "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==" 722 | }, 723 | "node_modules/is-arrayish": { 724 | "version": "0.2.1", 725 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 726 | "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" 727 | }, 728 | "node_modules/is-buffer": { 729 | "version": "1.1.6", 730 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 731 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 732 | }, 733 | "node_modules/is-extendable": { 734 | "version": "0.1.1", 735 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", 736 | "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", 737 | "engines": { 738 | "node": ">=0.10.0" 739 | } 740 | }, 741 | "node_modules/is-fullwidth-code-point": { 742 | "version": "3.0.0", 743 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 744 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 745 | "engines": { 746 | "node": ">=8" 747 | } 748 | }, 749 | "node_modules/is-plain-object": { 750 | "version": "2.0.4", 751 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", 752 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", 753 | "dependencies": { 754 | "isobject": "^3.0.1" 755 | }, 756 | "engines": { 757 | "node": ">=0.10.0" 758 | } 759 | }, 760 | "node_modules/isobject": { 761 | "version": "3.0.1", 762 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 763 | "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", 764 | "engines": { 765 | "node": ">=0.10.0" 766 | } 767 | }, 768 | "node_modules/js-tokens": { 769 | "version": "4.0.0", 770 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 771 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 772 | }, 773 | "node_modules/js-yaml": { 774 | "version": "4.1.0", 775 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 776 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 777 | "dependencies": { 778 | "argparse": "^2.0.1" 779 | }, 780 | "bin": { 781 | "js-yaml": "bin/js-yaml.js" 782 | } 783 | }, 784 | "node_modules/json-parse-even-better-errors": { 785 | "version": "2.3.1", 786 | "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", 787 | "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" 788 | }, 789 | "node_modules/jsonfile": { 790 | "version": "6.1.0", 791 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", 792 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", 793 | "dependencies": { 794 | "universalify": "^2.0.0" 795 | }, 796 | "optionalDependencies": { 797 | "graceful-fs": "^4.1.6" 798 | } 799 | }, 800 | "node_modules/kind-of": { 801 | "version": "3.2.2", 802 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 803 | "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", 804 | "dependencies": { 805 | "is-buffer": "^1.1.5" 806 | }, 807 | "engines": { 808 | "node": ">=0.10.0" 809 | } 810 | }, 811 | "node_modules/lazy-cache": { 812 | "version": "1.0.4", 813 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", 814 | "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==", 815 | "engines": { 816 | "node": ">=0.10.0" 817 | } 818 | }, 819 | "node_modules/lines-and-columns": { 820 | "version": "1.2.4", 821 | "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", 822 | "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" 823 | }, 824 | "node_modules/lru-cache": { 825 | "version": "7.18.3", 826 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", 827 | "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", 828 | "engines": { 829 | "node": ">=12" 830 | } 831 | }, 832 | "node_modules/merge-deep": { 833 | "version": "3.0.3", 834 | "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.3.tgz", 835 | "integrity": "sha512-qtmzAS6t6grwEkNrunqTBdn0qKwFgNWvlxUbAV8es9M7Ot1EbyApytCnvE0jALPa46ZpKDUo527kKiaWplmlFA==", 836 | "dependencies": { 837 | "arr-union": "^3.1.0", 838 | "clone-deep": "^0.2.4", 839 | "kind-of": "^3.0.2" 840 | }, 841 | "engines": { 842 | "node": ">=0.10.0" 843 | } 844 | }, 845 | "node_modules/minimatch": { 846 | "version": "3.1.2", 847 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 848 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 849 | "dependencies": { 850 | "brace-expansion": "^1.1.7" 851 | }, 852 | "engines": { 853 | "node": "*" 854 | } 855 | }, 856 | "node_modules/mitt": { 857 | "version": "3.0.1", 858 | "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", 859 | "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==" 860 | }, 861 | "node_modules/mixin-object": { 862 | "version": "2.0.1", 863 | "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", 864 | "integrity": "sha512-ALGF1Jt9ouehcaXaHhn6t1yGWRqGaHkPFndtFVHfZXOvkIZ/yoGaSi0AHVTafb3ZBGg4dr/bDwnaEKqCXzchMA==", 865 | "dependencies": { 866 | "for-in": "^0.1.3", 867 | "is-extendable": "^0.1.1" 868 | }, 869 | "engines": { 870 | "node": ">=0.10.0" 871 | } 872 | }, 873 | "node_modules/mixin-object/node_modules/for-in": { 874 | "version": "0.1.8", 875 | "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", 876 | "integrity": "sha512-F0to7vbBSHP8E3l6dCjxNOLuSFAACIxFy3UehTUlG7svlXi37HHsDkyVcHo0Pq8QwrE+pXvWSVX3ZT1T9wAZ9g==", 877 | "engines": { 878 | "node": ">=0.10.0" 879 | } 880 | }, 881 | "node_modules/mkdirp-classic": { 882 | "version": "0.5.3", 883 | "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", 884 | "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" 885 | }, 886 | "node_modules/ms": { 887 | "version": "2.1.2", 888 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 889 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 890 | }, 891 | "node_modules/netmask": { 892 | "version": "2.0.2", 893 | "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", 894 | "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", 895 | "engines": { 896 | "node": ">= 0.4.0" 897 | } 898 | }, 899 | "node_modules/node-fetch": { 900 | "version": "2.7.0", 901 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", 902 | "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", 903 | "dependencies": { 904 | "whatwg-url": "^5.0.0" 905 | }, 906 | "engines": { 907 | "node": "4.x || >=6.0.0" 908 | }, 909 | "peerDependencies": { 910 | "encoding": "^0.1.0" 911 | }, 912 | "peerDependenciesMeta": { 913 | "encoding": { 914 | "optional": true 915 | } 916 | } 917 | }, 918 | "node_modules/once": { 919 | "version": "1.4.0", 920 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 921 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 922 | "dependencies": { 923 | "wrappy": "1" 924 | } 925 | }, 926 | "node_modules/pac-proxy-agent": { 927 | "version": "7.0.1", 928 | "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", 929 | "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", 930 | "dependencies": { 931 | "@tootallnate/quickjs-emscripten": "^0.23.0", 932 | "agent-base": "^7.0.2", 933 | "debug": "^4.3.4", 934 | "get-uri": "^6.0.1", 935 | "http-proxy-agent": "^7.0.0", 936 | "https-proxy-agent": "^7.0.2", 937 | "pac-resolver": "^7.0.0", 938 | "socks-proxy-agent": "^8.0.2" 939 | }, 940 | "engines": { 941 | "node": ">= 14" 942 | } 943 | }, 944 | "node_modules/pac-resolver": { 945 | "version": "7.0.0", 946 | "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", 947 | "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", 948 | "dependencies": { 949 | "degenerator": "^5.0.0", 950 | "ip": "^1.1.8", 951 | "netmask": "^2.0.2" 952 | }, 953 | "engines": { 954 | "node": ">= 14" 955 | } 956 | }, 957 | "node_modules/parent-module": { 958 | "version": "1.0.1", 959 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 960 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 961 | "dependencies": { 962 | "callsites": "^3.0.0" 963 | }, 964 | "engines": { 965 | "node": ">=6" 966 | } 967 | }, 968 | "node_modules/parse-json": { 969 | "version": "5.2.0", 970 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", 971 | "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", 972 | "dependencies": { 973 | "@babel/code-frame": "^7.0.0", 974 | "error-ex": "^1.3.1", 975 | "json-parse-even-better-errors": "^2.3.0", 976 | "lines-and-columns": "^1.1.6" 977 | }, 978 | "engines": { 979 | "node": ">=8" 980 | }, 981 | "funding": { 982 | "url": "https://github.com/sponsors/sindresorhus" 983 | } 984 | }, 985 | "node_modules/path-is-absolute": { 986 | "version": "1.0.1", 987 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 988 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 989 | "engines": { 990 | "node": ">=0.10.0" 991 | } 992 | }, 993 | "node_modules/path-type": { 994 | "version": "4.0.0", 995 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", 996 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 997 | "engines": { 998 | "node": ">=8" 999 | } 1000 | }, 1001 | "node_modules/pend": { 1002 | "version": "1.2.0", 1003 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 1004 | "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" 1005 | }, 1006 | "node_modules/progress": { 1007 | "version": "2.0.3", 1008 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 1009 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 1010 | "engines": { 1011 | "node": ">=0.4.0" 1012 | } 1013 | }, 1014 | "node_modules/proxy-agent": { 1015 | "version": "6.3.1", 1016 | "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", 1017 | "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", 1018 | "dependencies": { 1019 | "agent-base": "^7.0.2", 1020 | "debug": "^4.3.4", 1021 | "http-proxy-agent": "^7.0.0", 1022 | "https-proxy-agent": "^7.0.2", 1023 | "lru-cache": "^7.14.1", 1024 | "pac-proxy-agent": "^7.0.1", 1025 | "proxy-from-env": "^1.1.0", 1026 | "socks-proxy-agent": "^8.0.2" 1027 | }, 1028 | "engines": { 1029 | "node": ">= 14" 1030 | } 1031 | }, 1032 | "node_modules/proxy-from-env": { 1033 | "version": "1.1.0", 1034 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", 1035 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" 1036 | }, 1037 | "node_modules/pump": { 1038 | "version": "3.0.0", 1039 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 1040 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 1041 | "dependencies": { 1042 | "end-of-stream": "^1.1.0", 1043 | "once": "^1.3.1" 1044 | } 1045 | }, 1046 | "node_modules/puppeteer": { 1047 | "version": "21.5.2", 1048 | "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-21.5.2.tgz", 1049 | "integrity": "sha512-BaAGJOq8Fl6/cck6obmwaNLksuY0Bg/lIahCLhJPGXBFUD2mCffypa4A592MaWnDcye7eaHmSK9yot0pxctY8A==", 1050 | "hasInstallScript": true, 1051 | "dependencies": { 1052 | "@puppeteer/browsers": "1.8.0", 1053 | "cosmiconfig": "8.3.6", 1054 | "puppeteer-core": "21.5.2" 1055 | }, 1056 | "engines": { 1057 | "node": ">=16.13.2" 1058 | } 1059 | }, 1060 | "node_modules/puppeteer-core": { 1061 | "version": "21.5.2", 1062 | "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-21.5.2.tgz", 1063 | "integrity": "sha512-v4T0cWnujSKs+iEfmb8ccd7u4/x8oblEyKqplqKnJ582Kw8PewYAWvkH4qUWhitN3O2q9RF7dzkvjyK5HbzjLA==", 1064 | "dependencies": { 1065 | "@puppeteer/browsers": "1.8.0", 1066 | "chromium-bidi": "0.4.33", 1067 | "cross-fetch": "4.0.0", 1068 | "debug": "4.3.4", 1069 | "devtools-protocol": "0.0.1203626", 1070 | "ws": "8.14.2" 1071 | }, 1072 | "engines": { 1073 | "node": ">=16.13.2" 1074 | } 1075 | }, 1076 | "node_modules/puppeteer-extra": { 1077 | "version": "3.3.6", 1078 | "resolved": "https://registry.npmjs.org/puppeteer-extra/-/puppeteer-extra-3.3.6.tgz", 1079 | "integrity": "sha512-rsLBE/6mMxAjlLd06LuGacrukP2bqbzKCLzV1vrhHFavqQE/taQ2UXv3H5P0Ls7nsrASa+6x3bDbXHpqMwq+7A==", 1080 | "dependencies": { 1081 | "@types/debug": "^4.1.0", 1082 | "debug": "^4.1.1", 1083 | "deepmerge": "^4.2.2" 1084 | }, 1085 | "engines": { 1086 | "node": ">=8" 1087 | }, 1088 | "peerDependencies": { 1089 | "@types/puppeteer": "*", 1090 | "puppeteer": "*", 1091 | "puppeteer-core": "*" 1092 | }, 1093 | "peerDependenciesMeta": { 1094 | "@types/puppeteer": { 1095 | "optional": true 1096 | }, 1097 | "puppeteer": { 1098 | "optional": true 1099 | }, 1100 | "puppeteer-core": { 1101 | "optional": true 1102 | } 1103 | } 1104 | }, 1105 | "node_modules/puppeteer-extra-plugin": { 1106 | "version": "3.2.3", 1107 | "resolved": "https://registry.npmjs.org/puppeteer-extra-plugin/-/puppeteer-extra-plugin-3.2.3.tgz", 1108 | "integrity": "sha512-6RNy0e6pH8vaS3akPIKGg28xcryKscczt4wIl0ePciZENGE2yoaQJNd17UiEbdmh5/6WW6dPcfRWT9lxBwCi2Q==", 1109 | "dependencies": { 1110 | "@types/debug": "^4.1.0", 1111 | "debug": "^4.1.1", 1112 | "merge-deep": "^3.0.1" 1113 | }, 1114 | "engines": { 1115 | "node": ">=9.11.2" 1116 | }, 1117 | "peerDependencies": { 1118 | "playwright-extra": "*", 1119 | "puppeteer-extra": "*" 1120 | }, 1121 | "peerDependenciesMeta": { 1122 | "playwright-extra": { 1123 | "optional": true 1124 | }, 1125 | "puppeteer-extra": { 1126 | "optional": true 1127 | } 1128 | } 1129 | }, 1130 | "node_modules/puppeteer-extra-plugin-stealth": { 1131 | "version": "2.11.2", 1132 | "resolved": "https://registry.npmjs.org/puppeteer-extra-plugin-stealth/-/puppeteer-extra-plugin-stealth-2.11.2.tgz", 1133 | "integrity": "sha512-bUemM5XmTj9i2ZerBzsk2AN5is0wHMNE6K0hXBzBXOzP5m5G3Wl0RHhiqKeHToe/uIH8AoZiGhc1tCkLZQPKTQ==", 1134 | "dependencies": { 1135 | "debug": "^4.1.1", 1136 | "puppeteer-extra-plugin": "^3.2.3", 1137 | "puppeteer-extra-plugin-user-preferences": "^2.4.1" 1138 | }, 1139 | "engines": { 1140 | "node": ">=8" 1141 | }, 1142 | "peerDependencies": { 1143 | "playwright-extra": "*", 1144 | "puppeteer-extra": "*" 1145 | }, 1146 | "peerDependenciesMeta": { 1147 | "playwright-extra": { 1148 | "optional": true 1149 | }, 1150 | "puppeteer-extra": { 1151 | "optional": true 1152 | } 1153 | } 1154 | }, 1155 | "node_modules/puppeteer-extra-plugin-user-data-dir": { 1156 | "version": "2.4.1", 1157 | "resolved": "https://registry.npmjs.org/puppeteer-extra-plugin-user-data-dir/-/puppeteer-extra-plugin-user-data-dir-2.4.1.tgz", 1158 | "integrity": "sha512-kH1GnCcqEDoBXO7epAse4TBPJh9tEpVEK/vkedKfjOVOhZAvLkHGc9swMs5ChrJbRnf8Hdpug6TJlEuimXNQ+g==", 1159 | "dependencies": { 1160 | "debug": "^4.1.1", 1161 | "fs-extra": "^10.0.0", 1162 | "puppeteer-extra-plugin": "^3.2.3", 1163 | "rimraf": "^3.0.2" 1164 | }, 1165 | "engines": { 1166 | "node": ">=8" 1167 | }, 1168 | "peerDependencies": { 1169 | "playwright-extra": "*", 1170 | "puppeteer-extra": "*" 1171 | }, 1172 | "peerDependenciesMeta": { 1173 | "playwright-extra": { 1174 | "optional": true 1175 | }, 1176 | "puppeteer-extra": { 1177 | "optional": true 1178 | } 1179 | } 1180 | }, 1181 | "node_modules/puppeteer-extra-plugin-user-preferences": { 1182 | "version": "2.4.1", 1183 | "resolved": "https://registry.npmjs.org/puppeteer-extra-plugin-user-preferences/-/puppeteer-extra-plugin-user-preferences-2.4.1.tgz", 1184 | "integrity": "sha512-i1oAZxRbc1bk8MZufKCruCEC3CCafO9RKMkkodZltI4OqibLFXF3tj6HZ4LZ9C5vCXZjYcDWazgtY69mnmrQ9A==", 1185 | "dependencies": { 1186 | "debug": "^4.1.1", 1187 | "deepmerge": "^4.2.2", 1188 | "puppeteer-extra-plugin": "^3.2.3", 1189 | "puppeteer-extra-plugin-user-data-dir": "^2.4.1" 1190 | }, 1191 | "engines": { 1192 | "node": ">=8" 1193 | }, 1194 | "peerDependencies": { 1195 | "playwright-extra": "*", 1196 | "puppeteer-extra": "*" 1197 | }, 1198 | "peerDependenciesMeta": { 1199 | "playwright-extra": { 1200 | "optional": true 1201 | }, 1202 | "puppeteer-extra": { 1203 | "optional": true 1204 | } 1205 | } 1206 | }, 1207 | "node_modules/queue-tick": { 1208 | "version": "1.0.1", 1209 | "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", 1210 | "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" 1211 | }, 1212 | "node_modules/require-directory": { 1213 | "version": "2.1.1", 1214 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1215 | "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", 1216 | "engines": { 1217 | "node": ">=0.10.0" 1218 | } 1219 | }, 1220 | "node_modules/resolve-from": { 1221 | "version": "4.0.0", 1222 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1223 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1224 | "engines": { 1225 | "node": ">=4" 1226 | } 1227 | }, 1228 | "node_modules/rimraf": { 1229 | "version": "3.0.2", 1230 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1231 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1232 | "dependencies": { 1233 | "glob": "^7.1.3" 1234 | }, 1235 | "bin": { 1236 | "rimraf": "bin.js" 1237 | }, 1238 | "funding": { 1239 | "url": "https://github.com/sponsors/isaacs" 1240 | } 1241 | }, 1242 | "node_modules/shallow-clone": { 1243 | "version": "0.1.2", 1244 | "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", 1245 | "integrity": "sha512-J1zdXCky5GmNnuauESROVu31MQSnLoYvlyEn6j2Ztk6Q5EHFIhxkMhYcv6vuDzl2XEzoRr856QwzMgWM/TmZgw==", 1246 | "dependencies": { 1247 | "is-extendable": "^0.1.1", 1248 | "kind-of": "^2.0.1", 1249 | "lazy-cache": "^0.2.3", 1250 | "mixin-object": "^2.0.1" 1251 | }, 1252 | "engines": { 1253 | "node": ">=0.10.0" 1254 | } 1255 | }, 1256 | "node_modules/shallow-clone/node_modules/kind-of": { 1257 | "version": "2.0.1", 1258 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", 1259 | "integrity": "sha512-0u8i1NZ/mg0b+W3MGGw5I7+6Eib2nx72S/QvXa0hYjEkjTknYmEYQJwGu3mLC0BrhtJjtQafTkyRUQ75Kx0LVg==", 1260 | "dependencies": { 1261 | "is-buffer": "^1.0.2" 1262 | }, 1263 | "engines": { 1264 | "node": ">=0.10.0" 1265 | } 1266 | }, 1267 | "node_modules/shallow-clone/node_modules/lazy-cache": { 1268 | "version": "0.2.7", 1269 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", 1270 | "integrity": "sha512-gkX52wvU/R8DVMMt78ATVPFMJqfW8FPz1GZ1sVHBVQHmu/WvhIWE4cE1GBzhJNFicDeYhnwp6Rl35BcAIM3YOQ==", 1271 | "engines": { 1272 | "node": ">=0.10.0" 1273 | } 1274 | }, 1275 | "node_modules/smart-buffer": { 1276 | "version": "4.2.0", 1277 | "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", 1278 | "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", 1279 | "engines": { 1280 | "node": ">= 6.0.0", 1281 | "npm": ">= 3.0.0" 1282 | } 1283 | }, 1284 | "node_modules/socks": { 1285 | "version": "2.7.1", 1286 | "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", 1287 | "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", 1288 | "dependencies": { 1289 | "ip": "^2.0.0", 1290 | "smart-buffer": "^4.2.0" 1291 | }, 1292 | "engines": { 1293 | "node": ">= 10.13.0", 1294 | "npm": ">= 3.0.0" 1295 | } 1296 | }, 1297 | "node_modules/socks-proxy-agent": { 1298 | "version": "8.0.2", 1299 | "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", 1300 | "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", 1301 | "dependencies": { 1302 | "agent-base": "^7.0.2", 1303 | "debug": "^4.3.4", 1304 | "socks": "^2.7.1" 1305 | }, 1306 | "engines": { 1307 | "node": ">= 14" 1308 | } 1309 | }, 1310 | "node_modules/socks/node_modules/ip": { 1311 | "version": "2.0.0", 1312 | "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", 1313 | "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" 1314 | }, 1315 | "node_modules/source-map": { 1316 | "version": "0.6.1", 1317 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1318 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1319 | "optional": true, 1320 | "engines": { 1321 | "node": ">=0.10.0" 1322 | } 1323 | }, 1324 | "node_modules/streamx": { 1325 | "version": "2.15.5", 1326 | "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.5.tgz", 1327 | "integrity": "sha512-9thPGMkKC2GctCzyCUjME3yR03x2xNo0GPKGkRw2UMYN+gqWa9uqpyNWhmsNCutU5zHmkUum0LsCRQTXUgUCAg==", 1328 | "dependencies": { 1329 | "fast-fifo": "^1.1.0", 1330 | "queue-tick": "^1.0.1" 1331 | } 1332 | }, 1333 | "node_modules/string-width": { 1334 | "version": "4.2.3", 1335 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1336 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1337 | "dependencies": { 1338 | "emoji-regex": "^8.0.0", 1339 | "is-fullwidth-code-point": "^3.0.0", 1340 | "strip-ansi": "^6.0.1" 1341 | }, 1342 | "engines": { 1343 | "node": ">=8" 1344 | } 1345 | }, 1346 | "node_modules/strip-ansi": { 1347 | "version": "6.0.1", 1348 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1349 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1350 | "dependencies": { 1351 | "ansi-regex": "^5.0.1" 1352 | }, 1353 | "engines": { 1354 | "node": ">=8" 1355 | } 1356 | }, 1357 | "node_modules/supports-color": { 1358 | "version": "5.5.0", 1359 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1360 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1361 | "dependencies": { 1362 | "has-flag": "^3.0.0" 1363 | }, 1364 | "engines": { 1365 | "node": ">=4" 1366 | } 1367 | }, 1368 | "node_modules/tar-fs": { 1369 | "version": "3.0.4", 1370 | "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", 1371 | "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", 1372 | "dependencies": { 1373 | "mkdirp-classic": "^0.5.2", 1374 | "pump": "^3.0.0", 1375 | "tar-stream": "^3.1.5" 1376 | } 1377 | }, 1378 | "node_modules/tar-stream": { 1379 | "version": "3.1.6", 1380 | "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.6.tgz", 1381 | "integrity": "sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==", 1382 | "dependencies": { 1383 | "b4a": "^1.6.4", 1384 | "fast-fifo": "^1.2.0", 1385 | "streamx": "^2.15.0" 1386 | } 1387 | }, 1388 | "node_modules/through": { 1389 | "version": "2.3.8", 1390 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1391 | "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" 1392 | }, 1393 | "node_modules/tr46": { 1394 | "version": "0.0.3", 1395 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 1396 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" 1397 | }, 1398 | "node_modules/tslib": { 1399 | "version": "2.6.2", 1400 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", 1401 | "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" 1402 | }, 1403 | "node_modules/unbzip2-stream": { 1404 | "version": "1.4.3", 1405 | "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", 1406 | "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", 1407 | "dependencies": { 1408 | "buffer": "^5.2.1", 1409 | "through": "^2.3.8" 1410 | } 1411 | }, 1412 | "node_modules/undici-types": { 1413 | "version": "5.26.5", 1414 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 1415 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", 1416 | "optional": true 1417 | }, 1418 | "node_modules/universalify": { 1419 | "version": "2.0.1", 1420 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", 1421 | "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", 1422 | "engines": { 1423 | "node": ">= 10.0.0" 1424 | } 1425 | }, 1426 | "node_modules/urlpattern-polyfill": { 1427 | "version": "9.0.0", 1428 | "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-9.0.0.tgz", 1429 | "integrity": "sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g==" 1430 | }, 1431 | "node_modules/webidl-conversions": { 1432 | "version": "3.0.1", 1433 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 1434 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" 1435 | }, 1436 | "node_modules/whatwg-url": { 1437 | "version": "5.0.0", 1438 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 1439 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 1440 | "dependencies": { 1441 | "tr46": "~0.0.3", 1442 | "webidl-conversions": "^3.0.0" 1443 | } 1444 | }, 1445 | "node_modules/wrap-ansi": { 1446 | "version": "7.0.0", 1447 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 1448 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 1449 | "dependencies": { 1450 | "ansi-styles": "^4.0.0", 1451 | "string-width": "^4.1.0", 1452 | "strip-ansi": "^6.0.0" 1453 | }, 1454 | "engines": { 1455 | "node": ">=10" 1456 | }, 1457 | "funding": { 1458 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 1459 | } 1460 | }, 1461 | "node_modules/wrap-ansi/node_modules/ansi-styles": { 1462 | "version": "4.3.0", 1463 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1464 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1465 | "dependencies": { 1466 | "color-convert": "^2.0.1" 1467 | }, 1468 | "engines": { 1469 | "node": ">=8" 1470 | }, 1471 | "funding": { 1472 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 1473 | } 1474 | }, 1475 | "node_modules/wrap-ansi/node_modules/color-convert": { 1476 | "version": "2.0.1", 1477 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1478 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1479 | "dependencies": { 1480 | "color-name": "~1.1.4" 1481 | }, 1482 | "engines": { 1483 | "node": ">=7.0.0" 1484 | } 1485 | }, 1486 | "node_modules/wrap-ansi/node_modules/color-name": { 1487 | "version": "1.1.4", 1488 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1489 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 1490 | }, 1491 | "node_modules/wrappy": { 1492 | "version": "1.0.2", 1493 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1494 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 1495 | }, 1496 | "node_modules/ws": { 1497 | "version": "8.14.2", 1498 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", 1499 | "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", 1500 | "engines": { 1501 | "node": ">=10.0.0" 1502 | }, 1503 | "peerDependencies": { 1504 | "bufferutil": "^4.0.1", 1505 | "utf-8-validate": ">=5.0.2" 1506 | }, 1507 | "peerDependenciesMeta": { 1508 | "bufferutil": { 1509 | "optional": true 1510 | }, 1511 | "utf-8-validate": { 1512 | "optional": true 1513 | } 1514 | } 1515 | }, 1516 | "node_modules/y18n": { 1517 | "version": "5.0.8", 1518 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 1519 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 1520 | "engines": { 1521 | "node": ">=10" 1522 | } 1523 | }, 1524 | "node_modules/yargs": { 1525 | "version": "17.7.2", 1526 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", 1527 | "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", 1528 | "dependencies": { 1529 | "cliui": "^8.0.1", 1530 | "escalade": "^3.1.1", 1531 | "get-caller-file": "^2.0.5", 1532 | "require-directory": "^2.1.1", 1533 | "string-width": "^4.2.3", 1534 | "y18n": "^5.0.5", 1535 | "yargs-parser": "^21.1.1" 1536 | }, 1537 | "engines": { 1538 | "node": ">=12" 1539 | } 1540 | }, 1541 | "node_modules/yargs-parser": { 1542 | "version": "21.1.1", 1543 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", 1544 | "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", 1545 | "engines": { 1546 | "node": ">=12" 1547 | } 1548 | }, 1549 | "node_modules/yauzl": { 1550 | "version": "2.10.0", 1551 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", 1552 | "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", 1553 | "dependencies": { 1554 | "buffer-crc32": "~0.2.3", 1555 | "fd-slicer": "~1.1.0" 1556 | } 1557 | } 1558 | } 1559 | } 1560 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "puppeteer": "^21.5.2", 4 | "puppeteer-extra": "^3.3.6", 5 | "puppeteer-extra-plugin-stealth": "^2.11.2" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /price_scraping.py: -------------------------------------------------------------------------------- 1 | import screenshot 2 | import multivision 3 | import image_splitter 4 | 5 | url = "https://www.amazon.com/s?k=raspberry+pi" 6 | 7 | shot = screenshot.take(url, full_page=True) 8 | 9 | shots = image_splitter.split(shot, "splits", 1200, offset=300) 10 | 11 | response = multivision.look(shots, 'Extract all the products and their prices from these website screenshots and return them in JSON format [{"name": "Name here", "price": 1.23}]') 12 | 13 | print(response) 14 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | openai 2 | pillow 3 | -------------------------------------------------------------------------------- /screenshot.js: -------------------------------------------------------------------------------- 1 | const puppeteer = require('puppeteer-extra'); 2 | const StealthPlugin = require('puppeteer-extra-plugin-stealth'); 3 | puppeteer.use(StealthPlugin()); 4 | 5 | const url = process.argv[2]; 6 | const full_page = !!process.argv[3]; 7 | const timeout = 8000; 8 | 9 | (async () => { 10 | const browser = await puppeteer.launch( { 11 | headless: "new", 12 | } ); 13 | 14 | const page = await browser.newPage(); 15 | 16 | await page.setViewport( { 17 | width: 1200, 18 | height: 1200, 19 | deviceScaleFactor: 1, 20 | } ); 21 | 22 | setTimeout(async () => { 23 | await page.screenshot( { 24 | path: "screenshot.jpg", 25 | fullPage: full_page, 26 | } ); 27 | }, timeout-2000); 28 | 29 | await page.goto( url, { 30 | waitUntil: "networkidle0", 31 | timeout: timeout, 32 | } ); 33 | 34 | await page.screenshot( { 35 | path: "screenshot.jpg", 36 | fullPage: full_page, 37 | } ); 38 | 39 | await browser.close(); 40 | })(); 41 | -------------------------------------------------------------------------------- /screenshot.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import os 3 | 4 | def take(url, filename="screenshot.jpg", full_page=False ): 5 | subprocess.run( 6 | ["node", "screenshot.js", url, str(full_page)], 7 | capture_output=True 8 | ) 9 | 10 | if filename != "screenshot.jpg": 11 | os.rename("screenshot.jpg", filename) 12 | 13 | return filename 14 | -------------------------------------------------------------------------------- /sketch_to_site.py: -------------------------------------------------------------------------------- 1 | import vision 2 | import sys 3 | 4 | if len(sys.argv) < 2: 5 | print(f"Usage: {sys.argv[0]} IMAGE_FILE") 6 | sys.exit(1) 7 | 8 | sketch = sys.argv[1] 9 | 10 | response = vision.look( 11 | image_path=sketch, 12 | prompt='Convert this sketch into a full, professional HTML and CSS template using Tailwind from a CDN (). Respond only with the code' 13 | ) 14 | 15 | print(response) 16 | 17 | code = "\n".join(response.split("```")[1].split("```")[0].split("\n")[1:-1]) 18 | 19 | with open("code.html", "w") as f: 20 | f.write(code) 21 | -------------------------------------------------------------------------------- /vision.py: -------------------------------------------------------------------------------- 1 | from openai import OpenAI 2 | import base64 3 | 4 | model = OpenAI() 5 | 6 | def image_b64(image_path): 7 | with open(image_path, "rb") as f: 8 | return base64.b64encode(f.read()).decode() 9 | 10 | def look(image_path, prompt="Describe this image"): 11 | b64_image = image_b64(image_path) 12 | 13 | response = model.chat.completions.create( 14 | model="gpt-4-vision-preview", 15 | messages=[ 16 | { 17 | "role": "user", 18 | "content": [ 19 | { 20 | "type": "image_url", 21 | "image_url": f"data:image/jpeg;base64,{b64_image}", 22 | }, 23 | { 24 | "type": "text", 25 | "text": prompt, 26 | } 27 | ] 28 | } 29 | ], 30 | max_tokens=1024, 31 | ) 32 | 33 | message = response.choices[0].message 34 | return message.content 35 | -------------------------------------------------------------------------------- /website_check.py: -------------------------------------------------------------------------------- 1 | import screenshot 2 | import multivision 3 | import json 4 | 5 | with open("original_screenshots.json") as f: 6 | originals = json.load(f) 7 | 8 | for url, original_shot in originals.items(): 9 | new_shot = screenshot.take(url) 10 | response = multivision.look( 11 | image_paths=[original_shot, new_shot], 12 | prompt="Compare these two screenshots and check for errors on the second image compared to the first one. If no errors are found, respond with JSON {\"status\": \"OK\"}. Otherwise, respond with JSON {\"status\": \"ERROR\", \"details\": \"Put here the details of the error\"}", 13 | ) 14 | 15 | if '"status": "OK"' not in response: 16 | print(response) 17 | -------------------------------------------------------------------------------- /website_check_init.py: -------------------------------------------------------------------------------- 1 | import screenshot 2 | import json 3 | import os 4 | 5 | urls = [ 6 | "http://localhost:8043/", 7 | "http://localhost:8043/?p=75", 8 | ] 9 | 10 | data = {} 11 | 12 | if not os.path.exists("screenshots"): 13 | os.mkdir("screenshots") 14 | 15 | for i, url in enumerate(urls): 16 | shot = screenshot.take(url, f"screenshots/{i}.jpg") 17 | 18 | data[url] = shot 19 | 20 | with open("original_screenshots.json", "w") as f: 21 | json.dump(data, f) 22 | --------------------------------------------------------------------------------