├── .gitignore ├── docs ├── LICENSE └── README.md ├── export.py ├── package-lock.json ├── package.json ├── requirements.txt └── singlefile.py /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | __pycache__/ 3 | node_modules/ 4 | output/ 5 | 6 | credentials.yaml 7 | cookies.txt 8 | -------------------------------------------------------------------------------- /docs/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 David Katsandres 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | The Canvas Student Data Export Tool can export nearly all of a student's data from Instructure Canvas Learning Management System (Canvas LMS). 3 | This is useful when you are graduating or leaving your college or university, and would like to have a backup of all the data you had in canvas. 4 | 5 | The tool exports all of the following data: 6 | - Course Assignments 7 | - Course Announcements 8 | - Course Discussions 9 | - Course Pages 10 | - Course Files 11 | - Course Modules 12 | - SingleFile HTML of Assignments, Announcements, Discussions, Modules 13 | 14 | 15 | The tool will export your data in JSON format, and will organize it nicely into folders named for every term of every year. 16 | Example: 17 | - Fall 2013 18 | - Econ 101 19 | - course files 20 | - modules 21 | - Econ 101.json 22 | - English 101 23 | - course files 24 | - modules 25 | - English 101.json 26 | - Fall 2014 27 | - Fall 2015 28 | - Fall 2016 29 | - Spring 2014 30 | - Spring 2015 31 | - Spring 2016 32 | - Spring 2017 33 | - Winter 2014 34 | - Winter 2015 35 | - Winter 2016 36 | - Winter 2017 37 | - all_output.json 38 | 39 | # Getting Started 40 | 41 | ## Dependencies 42 | To run the program, you will need the following dependencies: 43 | 44 | Install [Deno](https://docs.deno.com/runtime/getting_started/installation/). 45 | 46 | `pip install requests` 47 | `pip install jsonpickle` 48 | `pip install canvasapi` 49 | `pip install python-dateutil` 50 | `pip install PyYAML` 51 | 52 | `npm i github:gildas-lormeau/single-file-cli` 53 | 54 | You can install these dependencies using 55 | `pip install -r requirements.txt` 56 | AND 57 | `npm i` 58 | 59 | Then run from the command line: 60 | `python export.py` 61 | 62 | ## Configuration 63 | These are the configuration parameters for the program: 64 | - Canvas API URL - this is the URL of your institution, for example `https://example.instructure.com` 65 | - Canvas API key - this can be created by going to Canvas and navigating to `Account` > `Settings` > `Approved Integrations` > `New Access Token` 66 | - Canvas User ID - this can be found at `https://example.instructure.com/api/v1/users/self` in the `id` field 67 | - Path to Cookies File - file needs to be in netscape format, you can get your cookies via a tool like "Get cookies.txt Clean" on chrome. This can also be left blank if an html images are unwanted. 68 | - Directory in which to download course information to (will be created if not present) 69 | - List of Course IDs that should be skipped 70 | 71 | If single file fails to find your browser, you can set a path in singlefile.py. If you also want to run additional singlefile arguments that can also be done there. 72 | 73 | ### Loading credentials from a file 74 | To avoid manually entering credentials every time you run the program, you can create a `credentials.yaml` file in the same directory as the script that has the following fields: 75 | 76 | ```yaml 77 | API_URL: < URL of your institution > 78 | API_KEY: < API Key from Canvas > 79 | USER_ID: < User ID from Canvas > 80 | COOKIES_PATH: < Path to cookies file > 81 | ``` 82 | 83 | You can then run the script as normal: 84 | `python export.py` 85 | 86 | # Contribute 87 | I would love to see this script's functionality expanded and improved! I welcome all pull requests :) Thank you! 88 | -------------------------------------------------------------------------------- /export.py: -------------------------------------------------------------------------------- 1 | # built in 2 | import json 3 | import os 4 | import string 5 | 6 | # external 7 | from canvasapi import Canvas 8 | from canvasapi.exceptions import ResourceDoesNotExist, Unauthorized, Forbidden 9 | 10 | from singlefile import download_page 11 | 12 | import dateutil.parser 13 | import jsonpickle 14 | import requests 15 | import yaml 16 | 17 | try: 18 | with open("credentials.yaml", 'r') as f: 19 | credentials = yaml.full_load(f) 20 | except OSError: 21 | # Canvas API URL 22 | API_URL = "" 23 | # Canvas API key 24 | API_KEY = "" 25 | # My Canvas User ID 26 | USER_ID = 0000000 27 | # Browser Cookies File 28 | COOKIES_PATH = "" 29 | else: 30 | API_URL = credentials["API_URL"] 31 | API_KEY = credentials["API_KEY"] 32 | USER_ID = credentials["USER_ID"] 33 | COOKIES_PATH = credentials["COOKIES_PATH"] 34 | 35 | # Directory in which to download course information to (will be created if not 36 | # present) 37 | DL_LOCATION = "./output" 38 | # List of Course IDs that should be skipped (need to be integers) 39 | COURSES_TO_SKIP = [288290, 512033] 40 | 41 | DATE_TEMPLATE = "%B %d, %Y %I:%M %p" 42 | 43 | # Max PATH length is 260 characters on Windows. 70 is just an estimate for a reasonable max folder name to prevent the chance of reaching the limit 44 | # Applies to modules, assignments, announcements, and discussions 45 | # If a folder exceeds this limit, a "-" will be added to the end to indicate it was shortened ("..." not valid) 46 | MAX_FOLDER_NAME_SIZE = 70 47 | 48 | class moduleItemView(): 49 | id = 0 50 | 51 | title = "" 52 | content_type = "" 53 | 54 | url = "" 55 | external_url = "" 56 | 57 | 58 | class moduleView(): 59 | id = 0 60 | 61 | name = "" 62 | items = [] 63 | 64 | def __init__(self): 65 | self.items = [] 66 | 67 | 68 | class pageView(): 69 | id = 0 70 | 71 | title = "" 72 | body = "" 73 | created_date = "" 74 | last_updated_date = "" 75 | 76 | 77 | class topicReplyView(): 78 | id = 0 79 | 80 | author = "" 81 | posted_date = "" 82 | body = "" 83 | 84 | 85 | class topicEntryView(): 86 | id = 0 87 | 88 | author = "" 89 | posted_date = "" 90 | body = "" 91 | topic_replies = [] 92 | 93 | def __init__(self): 94 | self.topic_replies = [] 95 | 96 | 97 | class discussionView(): 98 | id = 0 99 | 100 | title = "" 101 | author = "" 102 | posted_date = "" 103 | body = "" 104 | topic_entries = [] 105 | 106 | url = "" 107 | amount_pages = 0 108 | 109 | def __init__(self): 110 | self.topic_entries = [] 111 | 112 | 113 | class submissionView(): 114 | id = 0 115 | 116 | attachments = [] 117 | grade = "" 118 | raw_score = "" 119 | submission_comments = "" 120 | total_possible_points = "" 121 | attempt = 0 122 | user_id = "no-id" 123 | 124 | preview_url = "" 125 | ext_url = "" 126 | 127 | def __init__(self): 128 | self.attachments = [] 129 | 130 | class attachmentView(): 131 | id = 0 132 | 133 | filename = "" 134 | url = "" 135 | 136 | class assignmentView(): 137 | id = 0 138 | 139 | title = "" 140 | description = "" 141 | assigned_date = "" 142 | due_date = "" 143 | submissions = [] 144 | 145 | html_url = "" 146 | ext_url = "" 147 | updated_url = "" 148 | 149 | def __init__(self): 150 | self.submissions = [] 151 | 152 | 153 | class courseView(): 154 | course_id = 0 155 | 156 | term = "" 157 | course_code = "" 158 | name = "" 159 | assignments = [] 160 | announcements = [] 161 | discussions = [] 162 | modules = [] 163 | 164 | def __init__(self): 165 | self.assignments = [] 166 | self.announcements = [] 167 | self.discussions = [] 168 | self.modules = [] 169 | 170 | def makeValidFilename(input_str): 171 | if(not input_str): 172 | return input_str 173 | 174 | # Remove invalid characters 175 | valid_chars = "-_.() %s%s" % (string.ascii_letters, string.digits) 176 | input_str = input_str.replace("+"," ") # Canvas default for spaces 177 | input_str = input_str.replace(":","-") 178 | input_str = input_str.replace("/","-") 179 | input_str = "".join(c for c in input_str if c in valid_chars) 180 | 181 | # Remove leading and trailing whitespace 182 | input_str = input_str.lstrip().rstrip() 183 | 184 | # Remove trailing periods 185 | input_str = input_str.rstrip(".") 186 | 187 | return input_str 188 | 189 | def makeValidFolderPath(input_str): 190 | # Remove invalid characters 191 | valid_chars = "-_.()/ %s%s" % (string.ascii_letters, string.digits) 192 | input_str = input_str.replace("+"," ") # Canvas default for spaces 193 | input_str = input_str.replace(":","-") 194 | input_str = "".join(c for c in input_str if c in valid_chars) 195 | 196 | # Remove leading and trailing whitespace, separators 197 | input_str = input_str.lstrip().rstrip().strip("/").strip("\\") 198 | 199 | # Remove trailing periods 200 | input_str = input_str.rstrip(".") 201 | 202 | # Replace path separators with OS default 203 | input_str=input_str.replace("/",os.sep) 204 | 205 | return input_str 206 | 207 | def shortenFileName(string, shorten_by) -> str: 208 | if (not string or shorten_by <= 0): 209 | return string 210 | 211 | # Shorten string by specified value + 1 for "-" to indicate incomplete file name (trailing periods not allowed) 212 | string = string[:len(string)-(shorten_by + 1)] 213 | 214 | string = string.rstrip().rstrip(".").rstrip("-") 215 | string += "-" 216 | 217 | return string 218 | 219 | 220 | def findCourseModules(course, course_view): 221 | modules_dir = os.path.join(DL_LOCATION, course_view.term, 222 | course_view.course_code, "modules") 223 | 224 | # Create modules directory if not present 225 | if not os.path.exists(modules_dir): 226 | os.makedirs(modules_dir) 227 | 228 | module_views = [] 229 | 230 | try: 231 | modules = course.get_modules() 232 | 233 | for module in modules: 234 | module_view = moduleView() 235 | 236 | # ID 237 | module_view.id = module.id if hasattr(module, "id") else "" 238 | 239 | # Name 240 | module_view.name = str(module.name) if hasattr(module, "name") else "" 241 | 242 | try: 243 | # Get module items 244 | module_items = module.get_module_items() 245 | 246 | for module_item in module_items: 247 | module_item_view = moduleItemView() 248 | 249 | # ID 250 | module_item_view.id = module_item.id if hasattr(module_item, "id") else 0 251 | 252 | # Title 253 | module_item_view.title = str(module_item.title) if hasattr(module_item, "title") else "" 254 | # Type 255 | module_item_view.content_type = str(module_item.type) if hasattr(module_item, "type") else "" 256 | 257 | # URL 258 | module_item_view.url = str(module_item.html_url) if hasattr(module_item, "html_url") else "" 259 | # External URL 260 | module_item_view.external_url = str(module_item.external_url) if hasattr(module_item, "external_url") else "" 261 | 262 | if module_item_view.content_type == "File": 263 | # If problems arise due to long pathnames, changing module.name to module.id might help 264 | # A change would also have to be made in downloadCourseModulePages(api_url, course_view, cookies_path) 265 | module_name = makeValidFilename(str(module.name)) 266 | module_name = shortenFileName(module_name, len(module_name) - MAX_FOLDER_NAME_SIZE) 267 | module_dir = os.path.join(modules_dir, module_name, "files") 268 | 269 | try: 270 | # Create directory for current module if not present 271 | if not os.path.exists(module_dir): 272 | os.makedirs(module_dir) 273 | 274 | # Get the file object 275 | module_file = course.get_file(str(module_item.content_id)) 276 | 277 | # Create path for module file download 278 | module_file_path = os.path.join(module_dir, makeValidFilename(str(module_file.display_name))) 279 | 280 | # Download file if it doesn't already exist 281 | if not os.path.exists(module_file_path): 282 | module_file.download(module_file_path) 283 | except Exception as e: 284 | print("Skipping module file download that gave the following error:") 285 | print(e) 286 | 287 | module_view.items.append(module_item_view) 288 | except Exception as e: 289 | print("Skipping module item that gave the following error:") 290 | print(e) 291 | 292 | module_views.append(module_view) 293 | 294 | except Exception as e: 295 | print("Skipping entire module that gave the following error:") 296 | print(e) 297 | 298 | return module_views 299 | 300 | 301 | def downloadCourseFiles(course, course_view): 302 | # file full_name starts with "course files" 303 | dl_dir = os.path.join(DL_LOCATION, course_view.term, 304 | course_view.course_code) 305 | 306 | # Create directory if not present 307 | if not os.path.exists(dl_dir): 308 | os.makedirs(dl_dir) 309 | 310 | try: 311 | files = course.get_files() 312 | 313 | for file in files: 314 | file_folder=course.get_folder(file.folder_id) 315 | 316 | folder_dl_dir=os.path.join(dl_dir, makeValidFolderPath(file_folder.full_name)) 317 | 318 | if not os.path.exists(folder_dl_dir): 319 | os.makedirs(folder_dl_dir) 320 | 321 | dl_path = os.path.join(folder_dl_dir, makeValidFilename(str(file.display_name))) 322 | 323 | # Download file if it doesn't already exist 324 | if not os.path.exists(dl_path): 325 | print('Downloading: {}'.format(dl_path)) 326 | file.download(dl_path) 327 | except Exception as e: 328 | print("Skipping file download that gave the following error:") 329 | print(e) 330 | 331 | 332 | def download_submission_attachments(course, course_view): 333 | course_dir = os.path.join(DL_LOCATION, course_view.term, 334 | course_view.course_code) 335 | 336 | # Create directory if not present 337 | if not os.path.exists(course_dir): 338 | os.makedirs(course_dir) 339 | 340 | for assignment in course_view.assignments: 341 | for submission in assignment.submissions: 342 | assignment_title = makeValidFilename(str(assignment.title)) 343 | assignment_title = shortenFileName(assignment_title, len(assignment_title) - MAX_FOLDER_NAME_SIZE) 344 | attachment_dir = os.path.join(course_dir, "assignments", assignment_title) 345 | if(len(assignment.submissions)!=1): 346 | attachment_dir = os.path.join(attachment_dir,str(submission.user_id)) 347 | if (not os.path.exists(attachment_dir)) and (submission.attachments): 348 | os.makedirs(attachment_dir) 349 | for attachment in submission.attachments: 350 | filepath = os.path.join(attachment_dir, makeValidFilename(str(attachment.id) + 351 | "_" + attachment.filename)) 352 | if not os.path.exists(filepath): 353 | print('Downloading attachment: {}'.format(filepath)) 354 | r = requests.get(attachment.url, allow_redirects=True) 355 | with open(filepath, 'wb') as f: 356 | f.write(r.content) 357 | else: 358 | print('File already exists: {}'.format(filepath)) 359 | 360 | 361 | def getCoursePageUrls(course): 362 | page_urls = [] 363 | 364 | try: 365 | # Get all pages 366 | pages = course.get_pages() 367 | 368 | for page in pages: 369 | if hasattr(page, "url"): 370 | page_urls.append(str(page.url)) 371 | except Exception as e: 372 | if e.message != "Not Found": 373 | print("Skipping page that gave the following error:") 374 | print(e) 375 | 376 | return page_urls 377 | 378 | 379 | def findCoursePages(course): 380 | page_views = [] 381 | 382 | try: 383 | # Get all page URLs 384 | page_urls = getCoursePageUrls(course) 385 | 386 | for url in page_urls: 387 | page = course.get_page(url) 388 | 389 | page_view = pageView() 390 | 391 | # ID 392 | page_view.id = page.id if hasattr(page, "id") else 0 393 | 394 | # Title 395 | page_view.title = str(page.title) if hasattr(page, "title") else "" 396 | # Body 397 | page_view.body = str(page.body) if hasattr(page, "body") else "" 398 | # Date created 399 | page_view.created_date = dateutil.parser.parse(page.created_at).strftime(DATE_TEMPLATE) if \ 400 | hasattr(page, "created_at") else "" 401 | # Date last updated 402 | page_view.last_updated_date = dateutil.parser.parse(page.updated_at).strftime(DATE_TEMPLATE) if \ 403 | hasattr(page, "updated_at") else "" 404 | 405 | page_views.append(page_view) 406 | except Exception as e: 407 | print("Skipping page download that gave the following error:") 408 | print(e) 409 | 410 | return page_views 411 | 412 | 413 | def findCourseAssignments(course): 414 | assignment_views = [] 415 | 416 | # Get all assignments 417 | assignments = course.get_assignments() 418 | 419 | try: 420 | for assignment in assignments: 421 | # Create a new assignment view 422 | assignment_view = assignmentView() 423 | 424 | #ID 425 | assignment_view.id = assignment.id if \ 426 | hasattr(assignment, "id") else "" 427 | 428 | # Title 429 | assignment_view.title = makeValidFilename(str(assignment.name)) if \ 430 | hasattr(assignment, "name") else "" 431 | # Description 432 | assignment_view.description = str(assignment.description) if \ 433 | hasattr(assignment, "description") else "" 434 | 435 | # Assigned date 436 | assignment_view.assigned_date = assignment.created_at_date.strftime(DATE_TEMPLATE) if \ 437 | hasattr(assignment, "created_at_date") else "" 438 | # Due date 439 | assignment_view.due_date = assignment.due_at_date.strftime(DATE_TEMPLATE) if \ 440 | hasattr(assignment, "due_at_date") else "" 441 | 442 | # HTML Url 443 | assignment_view.html_url = assignment.html_url if \ 444 | hasattr(assignment, "html_url") else "" 445 | # External URL 446 | assignment_view.ext_url = str(assignment.url) if \ 447 | hasattr(assignment, "url") else "" 448 | # Other URL (more up-to-date) 449 | assignment_view.updated_url = str(assignment.submissions_download_url).split("submissions?")[0] if \ 450 | hasattr(assignment, "submissions_download_url") else "" 451 | 452 | try: 453 | try: # Download all submissions for entire class 454 | submissions = assignment.get_submissions() 455 | submissions[0] # Trigger Unauthorized if not allowed 456 | except (Unauthorized, Forbidden): 457 | print("Not authorized to download entire class submissions for this assignment") 458 | # Download submission for this user only 459 | submissions = [assignment.get_submission(USER_ID)] 460 | submissions[0] #throw error if no submissions found at all but without error 461 | except (ResourceDoesNotExist, NameError, IndexError): 462 | print('Got no submissions from either class or user: {}'.format(USER_ID)) 463 | except Exception as e: 464 | print("Failed to retrieve submissions for this assignment") 465 | print(e.__class__.__name__) 466 | else: 467 | try: 468 | for submission in submissions: 469 | 470 | sub_view = submissionView() 471 | 472 | # Submission ID 473 | sub_view.id = submission.id if \ 474 | hasattr(submission, "id") else 0 475 | 476 | # My grade 477 | sub_view.grade = str(submission.grade) if \ 478 | hasattr(submission, "grade") else "" 479 | # My raw score 480 | sub_view.raw_score = str(submission.score) if \ 481 | hasattr(submission, "score") else "" 482 | # Total possible score 483 | sub_view.total_possible_points = str(assignment.points_possible) if \ 484 | hasattr(assignment, "points_possible") else "" 485 | # Submission comments 486 | sub_view.submission_comments = str(submission.submission_comments) if \ 487 | hasattr(submission, "submission_comments") else "" 488 | # Attempt 489 | sub_view.attempt = submission.attempt if \ 490 | hasattr(submission, "attempt") and submission.attempt is not None else 0 491 | # User ID 492 | sub_view.user_id = str(submission.user_id) if \ 493 | hasattr(submission, "user_id") else "" 494 | 495 | # Submission URL 496 | sub_view.preview_url = str(submission.preview_url) if \ 497 | hasattr(submission, "preview_url") else "" 498 | # External URL 499 | sub_view.ext_url = str(submission.url) if \ 500 | hasattr(submission, "url") else "" 501 | 502 | try: 503 | submission.attachments 504 | except AttributeError: 505 | print('No attachments') 506 | else: 507 | for attachment in submission.attachments: 508 | attach_view = attachmentView() 509 | attach_view.url = attachment.url 510 | attach_view.id = attachment.id 511 | attach_view.filename = attachment.filename 512 | sub_view.attachments.append(attach_view) 513 | assignment_view.submissions.append(sub_view) 514 | except Exception as e: 515 | print("Skipping submission that gave the following error:") 516 | print(e) 517 | 518 | assignment_views.append(assignment_view) 519 | except Exception as e: 520 | print("Skipping course assignments that gave the following error:") 521 | print(e) 522 | 523 | return assignment_views 524 | 525 | 526 | def findCourseAnnouncements(course): 527 | announcement_views = [] 528 | 529 | try: 530 | announcements = course.get_discussion_topics(only_announcements=True) 531 | 532 | for announcement in announcements: 533 | discussion_view = getDiscussionView(announcement) 534 | 535 | announcement_views.append(discussion_view) 536 | except Exception as e: 537 | print("Skipping announcement that gave the following error:") 538 | print(e) 539 | 540 | return announcement_views 541 | 542 | 543 | def getDiscussionView(discussion_topic): 544 | # Create discussion view 545 | discussion_view = discussionView() 546 | 547 | #ID 548 | discussion_view.id = discussion_topic.id if hasattr(discussion_topic, "id") else 0 549 | 550 | # Title 551 | discussion_view.title = str(discussion_topic.title) if hasattr(discussion_topic, "title") else "" 552 | # Author 553 | discussion_view.author = str(discussion_topic.user_name) if hasattr(discussion_topic, "user_name") else "" 554 | # Posted date 555 | discussion_view.posted_date = discussion_topic.created_at_date.strftime("%B %d, %Y %I:%M %p") if hasattr(discussion_topic, "created_at_date") else "" 556 | # Body 557 | discussion_view.body = str(discussion_topic.message) if hasattr(discussion_topic, "message") else "" 558 | 559 | # URL 560 | discussion_view.url = str(discussion_topic.html_url) if hasattr(discussion_topic, "html_url") else "" 561 | 562 | # Keeps track of how many topic_entries there are. 563 | topic_entries_counter = 0 564 | 565 | # Topic entries 566 | if hasattr(discussion_topic, "discussion_subentry_count") and discussion_topic.discussion_subentry_count > 0: 567 | # Need to get replies to entries recursively? 568 | 569 | discussion_topic_entries = discussion_topic.get_topic_entries() 570 | 571 | try: 572 | for topic_entry in discussion_topic_entries: 573 | topic_entries_counter += 1 574 | 575 | # Create new discussion view for the topic_entry 576 | topic_entry_view = topicEntryView() 577 | 578 | # ID 579 | topic_entry_view.id = topic_entry.id if hasattr(topic_entry, "id") else 0 580 | # Author 581 | topic_entry_view.author = str(topic_entry.user_name) if hasattr(topic_entry, "user_name") else "" 582 | # Posted date 583 | topic_entry_view.posted_date = topic_entry.created_at_date.strftime("%B %d, %Y %I:%M %p") if hasattr(topic_entry, "created_at_date") else "" 584 | # Body 585 | topic_entry_view.body = str(topic_entry.message) if hasattr(topic_entry, "message") else "" 586 | 587 | # Get this topic's replies 588 | topic_entry_replies = topic_entry.get_replies() 589 | 590 | try: 591 | for topic_reply in topic_entry_replies: 592 | # Create new topic reply view 593 | topic_reply_view = topicReplyView() 594 | 595 | # ID 596 | topic_reply_view.id = topic_reply.id if hasattr(topic_reply, "id") else 0 597 | 598 | # Author 599 | topic_reply_view.author = str(topic_reply.user_name) if hasattr(topic_reply, "user_name") else "" 600 | # Posted Date 601 | topic_reply_view.posted_date = topic_reply.created_at_date.strftime("%B %d, %Y %I:%M %p") if hasattr(topic_reply, "created_at_date") else "" 602 | # Body 603 | topic_reply_view.message = str(topic_reply.message) if hasattr(topic_reply, "message") else "" 604 | 605 | topic_entry_view.topic_replies.append(topic_reply_view) 606 | except Exception as e: 607 | print("Tried to enumerate discussion topic entry replies but received the following error:") 608 | print(e) 609 | 610 | discussion_view.topic_entries.append(topic_entry_view) 611 | except Exception as e: 612 | print("Tried to enumerate discussion topic entries but received the following error:") 613 | print(e) 614 | 615 | # Amount of pages 616 | discussion_view.amount_pages = int(topic_entries_counter/50) + 1 # Typically 50 topic entries are stored on a page before it creates another page. 617 | 618 | return discussion_view 619 | 620 | 621 | def findCourseDiscussions(course): 622 | discussion_views = [] 623 | 624 | try: 625 | discussion_topics = course.get_discussion_topics() 626 | 627 | for discussion_topic in discussion_topics: 628 | discussion_view = None 629 | discussion_view = getDiscussionView(discussion_topic) 630 | 631 | discussion_views.append(discussion_view) 632 | except Exception as e: 633 | print("Skipping discussion that gave the following error:") 634 | print(e) 635 | 636 | return discussion_views 637 | 638 | 639 | def getCourseView(course): 640 | course_view = courseView() 641 | 642 | # Course ID 643 | course_view.course_id = course.id if hasattr(course, "id") else 0 644 | 645 | # Course term 646 | course_view.term = makeValidFilename(course.term["name"] if hasattr(course, "term") and "name" in course.term.keys() else "") 647 | 648 | # Course code 649 | course_view.course_code = makeValidFilename(course.course_code if hasattr(course, "course_code") else "") 650 | 651 | # Course name 652 | course_view.name = course.name if hasattr(course, "name") else "" 653 | 654 | print("Working on " + course_view.term + ": " + course_view.name) 655 | 656 | # Course assignments 657 | print(" Getting assignments") 658 | course_view.assignments = findCourseAssignments(course) 659 | 660 | # Course announcements 661 | print(" Getting announcements") 662 | course_view.announcements = findCourseAnnouncements(course) 663 | 664 | # Course discussions 665 | print(" Getting discussions") 666 | course_view.discussions = findCourseDiscussions(course) 667 | 668 | # Course pages 669 | print(" Getting pages") 670 | course_view.pages = findCoursePages(course) 671 | 672 | return course_view 673 | 674 | 675 | def exportAllCourseData(course_view): 676 | json_str = json.dumps(json.loads(jsonpickle.encode(course_view, unpicklable = False)), indent = 4) 677 | 678 | course_output_dir = os.path.join(DL_LOCATION, course_view.term, 679 | course_view.course_code) 680 | 681 | # Create directory if not present 682 | if not os.path.exists(course_output_dir): 683 | os.makedirs(course_output_dir) 684 | 685 | course_output_path = os.path.join(course_output_dir, 686 | course_view.course_code + ".json") 687 | 688 | with open(course_output_path, "w") as out_file: 689 | out_file.write(json_str) 690 | 691 | def downloadCourseHTML(api_url, cookies_path): 692 | if(cookies_path == ""): 693 | return 694 | 695 | course_dir = DL_LOCATION 696 | 697 | if not os.path.exists(course_dir): 698 | os.makedirs(course_dir) 699 | 700 | course_list_path = os.path.join(course_dir, "course_list.html") 701 | 702 | # Downloads the course list. 703 | if not os.path.exists(course_list_path): 704 | download_page(api_url + "/courses/", cookies_path, course_dir, "course_list.html") 705 | 706 | def downloadCourseHomePageHTML(api_url, course_view, cookies_path): 707 | if(cookies_path == ""): 708 | return 709 | 710 | dl_dir = os.path.join(DL_LOCATION, course_view.term, 711 | course_view.course_code) 712 | 713 | # Create directory if not present 714 | if not os.path.exists(dl_dir): 715 | os.makedirs(dl_dir) 716 | 717 | homepage_path = os.path.join(dl_dir, "homepage.html") 718 | 719 | # Downloads the course home page. 720 | if not os.path.exists(homepage_path): 721 | download_page(api_url + "/courses/" + str(course_view.course_id), cookies_path, dl_dir, "homepage.html") 722 | 723 | def downloadAssignmentPages(api_url, course_view, cookies_path): 724 | if(cookies_path == "" or len(course_view.assignments) == 0): 725 | return 726 | 727 | base_assign_dir = os.path.join(DL_LOCATION, course_view.term, 728 | course_view.course_code, "assignments") 729 | 730 | # Create directory if not present 731 | if not os.path.exists(base_assign_dir): 732 | os.makedirs(base_assign_dir) 733 | 734 | assignment_list_path = os.path.join(base_assign_dir, "assignment_list.html") 735 | 736 | # Download assignment list (theres a chance this might be the course homepage if the course has the assignments page disabled) 737 | if not os.path.exists(assignment_list_path): 738 | download_page(api_url + "/courses/" + str(course_view.course_id) + "/assignments/", cookies_path, base_assign_dir, "assignment_list.html") 739 | 740 | for assignment in course_view.assignments: 741 | assignment_title = makeValidFilename(str(assignment.title)) 742 | assignment_title = shortenFileName(assignment_title, len(assignment_title) - MAX_FOLDER_NAME_SIZE) 743 | assign_dir = os.path.join(base_assign_dir, assignment_title) 744 | 745 | # Download an html image of each assignment (includes assignment instructions and other stuff). 746 | # Currently, this will only download the main assignment page and not external pages, this is 747 | # because these external pages are given in a json format. Saving these would require a lot 748 | # more work then normal. 749 | if assignment.html_url != "": 750 | if not os.path.exists(assign_dir): 751 | os.makedirs(assign_dir) 752 | 753 | assignment_page_path = os.path.join(assign_dir, "assignment.html") 754 | 755 | # Download assignment page, this usually has instructions and etc. 756 | if not os.path.exists(assignment_page_path): 757 | download_page(assignment.html_url, cookies_path, assign_dir, "assignment.html") 758 | 759 | for submission in assignment.submissions: 760 | submission_dir = assign_dir 761 | 762 | # If theres more then 1 submission, add unique id to download dir 763 | if len(assignment.submissions) != 1: 764 | submission_dir = os.path.join(assign_dir, str(submission.user_id)) 765 | 766 | if submission.preview_url != "": 767 | if not os.path.exists(submission_dir): 768 | os.makedirs(submission_dir) 769 | 770 | submission_page_dir = os.path.join(submission_dir, "submission.html") 771 | 772 | # Download submission url, this is typically a more focused page 773 | if not os.path.exists(submission_page_dir): 774 | download_page(submission.preview_url, cookies_path, submission_dir, "submission.html") 775 | 776 | # If theres more then 1 attempt, save each attempt in attempts folder 777 | if (submission.attempt != 1 and assignment.updated_url != "" and assignment.html_url != "" 778 | and assignment.html_url.rstrip("/") != assignment.updated_url.rstrip("/")): 779 | submission_dir = os.path.join(assign_dir, "attempts") 780 | 781 | if not os.path.exists(submission_dir): 782 | os.makedirs(submission_dir) 783 | 784 | # Saves the attempts if multiple were taken, doesn't account for 785 | # different ID's however, as I wasnt able to find out what the url 786 | # for the specific id's attempts would be. 787 | for i in range(submission.attempt): 788 | filename = "attempt_" + str(i+1) + ".html" 789 | submission_page_attempt_dir = os.path.join(submission_dir, filename) 790 | 791 | if not os.path.exists(submission_page_attempt_dir): 792 | download_page(assignment.updated_url + "/history?version=" + str(i+1), cookies_path, submission_dir, filename) 793 | 794 | def downloadCourseModulePages(api_url, course_view, cookies_path): 795 | if(cookies_path == "" or len(course_view.modules) == 0): 796 | return 797 | 798 | modules_dir = os.path.join(DL_LOCATION, course_view.term, 799 | course_view.course_code, "modules") 800 | 801 | # Create modules directory if not present 802 | if not os.path.exists(modules_dir): 803 | os.makedirs(modules_dir) 804 | 805 | module_list_dir = os.path.join(modules_dir, "modules_list.html") 806 | 807 | # Downloads the modules page (possible this is disabled by the teacher) 808 | if not os.path.exists(module_list_dir): 809 | download_page(api_url + "/courses/" + str(course_view.course_id) + "/modules/", COOKIES_PATH, modules_dir, "modules_list.html") 810 | 811 | for module in course_view.modules: 812 | for item in module.items: 813 | # If problems arise due to long pathnames, changing module.name to module.id might help, this can also be done with item.title 814 | # A change would also have to be made in findCourseModules(course, course_view) 815 | module_name = makeValidFilename(str(module.name)) 816 | module_name = shortenFileName(module_name, len(module_name) - MAX_FOLDER_NAME_SIZE) 817 | items_dir = os.path.join(modules_dir, module_name) 818 | 819 | # Create modules directory if not present 820 | if item.url != "": 821 | if not os.path.exists(items_dir): 822 | os.makedirs(items_dir) 823 | 824 | filename = makeValidFilename(str(item.title)) + ".html" 825 | module_item_dir = os.path.join(items_dir, filename) 826 | 827 | # Download the module page. 828 | if not os.path.exists(module_item_dir): 829 | download_page(item.url, cookies_path, items_dir, filename) 830 | 831 | def downloadCourseAnnouncementPages(api_url, course_view, cookies_path): 832 | if(cookies_path == "" or len(course_view.announcements) == 0): 833 | return 834 | 835 | base_announce_dir = os.path.join(DL_LOCATION, course_view.term, 836 | course_view.course_code, "announcements") 837 | 838 | # Create directory if not present 839 | if not os.path.exists(base_announce_dir): 840 | os.makedirs(base_announce_dir) 841 | 842 | announcement_list_dir = os.path.join(base_announce_dir, "announcement_list.html") 843 | 844 | # Download assignment list (theres a chance this might be the course homepage if the course has the assignments page disabled) 845 | if not os.path.exists(announcement_list_dir): 846 | download_page(api_url + "/courses/" + str(course_view.course_id) + "/announcements/", cookies_path, base_announce_dir, "announcement_list.html") 847 | 848 | for announcements in course_view.announcements: 849 | announcements_title = makeValidFilename(str(announcements.title)) 850 | announcements_title = shortenFileName(announcements_title, len(announcements_title) - MAX_FOLDER_NAME_SIZE) 851 | announce_dir = os.path.join(base_announce_dir, announcements_title) 852 | 853 | if announcements.url == "": 854 | continue 855 | 856 | if not os.path.exists(announce_dir): 857 | os.makedirs(announce_dir) 858 | 859 | # Downloads each page that a discussion takes. 860 | for i in range(announcements.amount_pages): 861 | filename = "announcement_" + str(i+1) + ".html" 862 | announcement_page_dir = os.path.join(announce_dir, filename) 863 | 864 | # Download assignment page, this usually has instructions and etc. 865 | if not os.path.exists(announcement_page_dir): 866 | download_page(announcements.url + "/page-" + str(i+1), cookies_path, announce_dir, filename) 867 | 868 | def downloadCourseDiscussionPages(api_url, course_view, cookies_path): 869 | if(cookies_path == "" or len(course_view.discussions) == 0): 870 | return 871 | 872 | base_discussion_dir = os.path.join(DL_LOCATION, course_view.term, 873 | course_view.course_code, "discussions") 874 | 875 | # Create directory if not present 876 | if not os.path.exists(base_discussion_dir): 877 | os.makedirs(base_discussion_dir) 878 | 879 | discussion_list_dir = os.path.join(base_discussion_dir, "discussion_list.html") 880 | 881 | # Download assignment list (theres a chance this might be the course homepage if the course has the assignments page disabled) 882 | if not os.path.exists(discussion_list_dir): 883 | download_page(api_url + "/courses/" + str(course_view.course_id) + "/discussion_topics/", cookies_path, base_discussion_dir, "discussion_list.html") 884 | 885 | for discussion in course_view.discussions: 886 | discussion_title = makeValidFilename(str(discussion.title)) 887 | discussion_title = shortenFileName(discussion_title, len(discussion_title) - MAX_FOLDER_NAME_SIZE) 888 | discussion_dir = os.path.join(base_discussion_dir, discussion_title) 889 | 890 | if discussion.url == "": 891 | continue 892 | 893 | if not os.path.exists(discussion_dir): 894 | os.makedirs(discussion_dir) 895 | 896 | # Downloads each page that a discussion takes. 897 | for i in range(discussion.amount_pages): 898 | filename = "discussion_" + str(i+1) + ".html" 899 | discussion_page_dir = os.path.join(discussion_dir, filename) 900 | 901 | # Download assignment page, this usually has instructions and etc. 902 | if not os.path.exists(discussion_page_dir): 903 | download_page(discussion.url + "/page-" + str(i+1), cookies_path, discussion_dir, filename) 904 | 905 | if __name__ == "__main__": 906 | 907 | print("Welcome to the Canvas Student Data Export Tool\n") 908 | 909 | if API_URL == "": 910 | # Canvas API URL 911 | print("We will need your organization's Canvas Base URL. This is " 912 | "probably something like https://{schoolName}.instructure.com)") 913 | API_URL = input("Enter your organization's Canvas Base URL: ") 914 | 915 | if API_KEY == "": 916 | # Canvas API key 917 | print("\nWe will need a valid API key for your user. You can generate " 918 | "one in Canvas once you are logged in.") 919 | API_KEY = input("Enter a valid API key for your user: ") 920 | 921 | if USER_ID == 0000000: 922 | # My Canvas User ID 923 | print("\nWe will need your Canvas User ID. You can find this by " 924 | "logging in to canvas and then going to this URL in the same " 925 | "browser {yourCanvasBaseUrl}/api/v1/users/self") 926 | USER_ID = input("Enter your Canvas User ID: ") 927 | 928 | if COOKIES_PATH == "": 929 | # Cookies path 930 | print("\nWe will need your browsers cookies file. This needs to be " 931 | "exported using another tool. This needs to be a path to a file " 932 | "formatted in the NetScape format. This can be left blank if an html " 933 | "images aren't wanted. ") 934 | COOKIES_PATH = input("Enter your cookies path: ") 935 | 936 | print("\nConnecting to canvas\n") 937 | 938 | # Initialize a new Canvas object 939 | canvas = Canvas(API_URL, API_KEY) 940 | 941 | print("Creating output directory: " + DL_LOCATION + "\n") 942 | # Create directory if not present 943 | if not os.path.exists(DL_LOCATION): 944 | os.makedirs(DL_LOCATION) 945 | 946 | all_courses_views = [] 947 | 948 | print("Getting list of all courses\n") 949 | courses = canvas.get_courses(include="term") 950 | 951 | skip = set(COURSES_TO_SKIP) 952 | 953 | 954 | if (COOKIES_PATH): 955 | print(" Downloading course list page") 956 | downloadCourseHTML(API_URL, COOKIES_PATH) 957 | 958 | for course in courses: 959 | if course.id in skip or not hasattr(course, "name") or not hasattr(course, "term"): 960 | continue 961 | 962 | course_view = getCourseView(course) 963 | 964 | all_courses_views.append(course_view) 965 | 966 | print(" Downloading all files") 967 | downloadCourseFiles(course, course_view) 968 | 969 | print(" Downloading submission attachments") 970 | download_submission_attachments(course, course_view) 971 | 972 | print(" Getting modules and downloading module files") 973 | course_view.modules = findCourseModules(course, course_view) 974 | 975 | if(COOKIES_PATH): 976 | print(" Downloading course home page") 977 | downloadCourseHomePageHTML(API_URL, course_view, COOKIES_PATH) 978 | 979 | print(" Downloading assignment pages") 980 | downloadAssignmentPages(API_URL, course_view, COOKIES_PATH) 981 | 982 | print(" Downloading course module pages") 983 | downloadCourseModulePages(API_URL, course_view, COOKIES_PATH) 984 | 985 | print(" Downloading course announcements pages") 986 | downloadCourseAnnouncementPages(API_URL, course_view, COOKIES_PATH) 987 | 988 | print(" Downloading course discussion pages") 989 | downloadCourseDiscussionPages(API_URL, course_view, COOKIES_PATH) 990 | 991 | print(" Exporting all course data") 992 | exportAllCourseData(course_view) 993 | 994 | print("Exporting data from all courses combined as one file: " 995 | "all_output.json") 996 | # Awful hack to make the JSON pretty. Decode it with Python stdlib json 997 | # module then re-encode with indentation 998 | json_str = json.dumps(json.loads(jsonpickle.encode(all_courses_views, 999 | unpicklable=False)), 1000 | indent=4) 1001 | 1002 | all_output_path = os.path.join(DL_LOCATION, "all_output.json") 1003 | 1004 | with open(all_output_path, "w") as out_file: 1005 | out_file.write(json_str) 1006 | 1007 | print("\nProcess complete. All canvas data exported!") 1008 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "canvas-student-data-export", 3 | "lockfileVersion": 2, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "dependencies": { 8 | "single-file": "github:gildas-lormeau/SingleFile" 9 | } 10 | }, 11 | "node_modules/@tootallnate/once": { 12 | "version": "2.0.0", 13 | "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", 14 | "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | }, 19 | "node_modules/@types/node": { 20 | "version": "17.0.0", 21 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.0.tgz", 22 | "integrity": "sha512-eMhwJXc931Ihh4tkU+Y7GiLzT/y/DBNpNtr4yU9O2w3SYBsr9NaOPhQlLKRmoWtI54uNwuo0IOUFQjVOTZYRvw==", 23 | "optional": true 24 | }, 25 | "node_modules/@types/yauzl": { 26 | "version": "2.9.2", 27 | "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", 28 | "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==", 29 | "optional": true, 30 | "dependencies": { 31 | "@types/node": "*" 32 | } 33 | }, 34 | "node_modules/abab": { 35 | "version": "2.0.5", 36 | "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", 37 | "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==" 38 | }, 39 | "node_modules/acorn": { 40 | "version": "8.6.0", 41 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", 42 | "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", 43 | "bin": { 44 | "acorn": "bin/acorn" 45 | }, 46 | "engines": { 47 | "node": ">=0.4.0" 48 | } 49 | }, 50 | "node_modules/acorn-globals": { 51 | "version": "6.0.0", 52 | "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", 53 | "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", 54 | "dependencies": { 55 | "acorn": "^7.1.1", 56 | "acorn-walk": "^7.1.1" 57 | } 58 | }, 59 | "node_modules/acorn-globals/node_modules/acorn": { 60 | "version": "7.4.1", 61 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", 62 | "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", 63 | "bin": { 64 | "acorn": "bin/acorn" 65 | }, 66 | "engines": { 67 | "node": ">=0.4.0" 68 | } 69 | }, 70 | "node_modules/acorn-walk": { 71 | "version": "7.2.0", 72 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", 73 | "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", 74 | "engines": { 75 | "node": ">=0.4.0" 76 | } 77 | }, 78 | "node_modules/agent-base": { 79 | "version": "6.0.2", 80 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", 81 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", 82 | "dependencies": { 83 | "debug": "4" 84 | }, 85 | "engines": { 86 | "node": ">= 6.0.0" 87 | } 88 | }, 89 | "node_modules/ansi-regex": { 90 | "version": "5.0.1", 91 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 92 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 93 | "engines": { 94 | "node": ">=8" 95 | } 96 | }, 97 | "node_modules/ansi-styles": { 98 | "version": "4.3.0", 99 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 100 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 101 | "dependencies": { 102 | "color-convert": "^2.0.1" 103 | }, 104 | "engines": { 105 | "node": ">=8" 106 | }, 107 | "funding": { 108 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 109 | } 110 | }, 111 | "node_modules/asynckit": { 112 | "version": "0.4.0", 113 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 114 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 115 | }, 116 | "node_modules/balanced-match": { 117 | "version": "1.0.2", 118 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 119 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 120 | }, 121 | "node_modules/base64-js": { 122 | "version": "1.5.1", 123 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 124 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 125 | "funding": [ 126 | { 127 | "type": "github", 128 | "url": "https://github.com/sponsors/feross" 129 | }, 130 | { 131 | "type": "patreon", 132 | "url": "https://www.patreon.com/feross" 133 | }, 134 | { 135 | "type": "consulting", 136 | "url": "https://feross.org/support" 137 | } 138 | ] 139 | }, 140 | "node_modules/bl": { 141 | "version": "4.1.0", 142 | "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", 143 | "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", 144 | "dependencies": { 145 | "buffer": "^5.5.0", 146 | "inherits": "^2.0.4", 147 | "readable-stream": "^3.4.0" 148 | } 149 | }, 150 | "node_modules/bl/node_modules/readable-stream": { 151 | "version": "3.6.0", 152 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 153 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 154 | "dependencies": { 155 | "inherits": "^2.0.3", 156 | "string_decoder": "^1.1.1", 157 | "util-deprecate": "^1.0.1" 158 | }, 159 | "engines": { 160 | "node": ">= 6" 161 | } 162 | }, 163 | "node_modules/brace-expansion": { 164 | "version": "1.1.11", 165 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 166 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 167 | "dependencies": { 168 | "balanced-match": "^1.0.0", 169 | "concat-map": "0.0.1" 170 | } 171 | }, 172 | "node_modules/browser-process-hrtime": { 173 | "version": "1.0.0", 174 | "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", 175 | "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" 176 | }, 177 | "node_modules/buffer": { 178 | "version": "5.7.1", 179 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 180 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 181 | "funding": [ 182 | { 183 | "type": "github", 184 | "url": "https://github.com/sponsors/feross" 185 | }, 186 | { 187 | "type": "patreon", 188 | "url": "https://www.patreon.com/feross" 189 | }, 190 | { 191 | "type": "consulting", 192 | "url": "https://feross.org/support" 193 | } 194 | ], 195 | "dependencies": { 196 | "base64-js": "^1.3.1", 197 | "ieee754": "^1.1.13" 198 | } 199 | }, 200 | "node_modules/buffer-crc32": { 201 | "version": "0.2.13", 202 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 203 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", 204 | "engines": { 205 | "node": "*" 206 | } 207 | }, 208 | "node_modules/chownr": { 209 | "version": "1.1.4", 210 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", 211 | "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" 212 | }, 213 | "node_modules/cliui": { 214 | "version": "7.0.4", 215 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 216 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 217 | "dependencies": { 218 | "string-width": "^4.2.0", 219 | "strip-ansi": "^6.0.0", 220 | "wrap-ansi": "^7.0.0" 221 | } 222 | }, 223 | "node_modules/color-convert": { 224 | "version": "2.0.1", 225 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 226 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 227 | "dependencies": { 228 | "color-name": "~1.1.4" 229 | }, 230 | "engines": { 231 | "node": ">=7.0.0" 232 | } 233 | }, 234 | "node_modules/color-name": { 235 | "version": "1.1.4", 236 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 237 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 238 | }, 239 | "node_modules/combined-stream": { 240 | "version": "1.0.8", 241 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 242 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 243 | "dependencies": { 244 | "delayed-stream": "~1.0.0" 245 | }, 246 | "engines": { 247 | "node": ">= 0.8" 248 | } 249 | }, 250 | "node_modules/concat-map": { 251 | "version": "0.0.1", 252 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 253 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 254 | }, 255 | "node_modules/core-util-is": { 256 | "version": "1.0.3", 257 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", 258 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" 259 | }, 260 | "node_modules/cssom": { 261 | "version": "0.5.0", 262 | "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", 263 | "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==" 264 | }, 265 | "node_modules/cssstyle": { 266 | "version": "2.3.0", 267 | "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", 268 | "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", 269 | "dependencies": { 270 | "cssom": "~0.3.6" 271 | }, 272 | "engines": { 273 | "node": ">=8" 274 | } 275 | }, 276 | "node_modules/cssstyle/node_modules/cssom": { 277 | "version": "0.3.8", 278 | "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", 279 | "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" 280 | }, 281 | "node_modules/data-urls": { 282 | "version": "3.0.1", 283 | "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.1.tgz", 284 | "integrity": "sha512-Ds554NeT5Gennfoo9KN50Vh6tpgtvYEwraYjejXnyTpu1C7oXKxdFk75REooENHE8ndTVOJuv+BEs4/J/xcozw==", 285 | "dependencies": { 286 | "abab": "^2.0.3", 287 | "whatwg-mimetype": "^3.0.0", 288 | "whatwg-url": "^10.0.0" 289 | }, 290 | "engines": { 291 | "node": ">=12" 292 | } 293 | }, 294 | "node_modules/debug": { 295 | "version": "4.3.3", 296 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", 297 | "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", 298 | "dependencies": { 299 | "ms": "2.1.2" 300 | }, 301 | "engines": { 302 | "node": ">=6.0" 303 | }, 304 | "peerDependenciesMeta": { 305 | "supports-color": { 306 | "optional": true 307 | } 308 | } 309 | }, 310 | "node_modules/decimal.js": { 311 | "version": "10.3.1", 312 | "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", 313 | "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==" 314 | }, 315 | "node_modules/deep-is": { 316 | "version": "0.1.4", 317 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 318 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" 319 | }, 320 | "node_modules/delayed-stream": { 321 | "version": "1.0.0", 322 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 323 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 324 | "engines": { 325 | "node": ">=0.4.0" 326 | } 327 | }, 328 | "node_modules/devtools-protocol": { 329 | "version": "0.0.901419", 330 | "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.901419.tgz", 331 | "integrity": "sha512-4INMPwNm9XRpBukhNbF7OB6fNTTCaI8pzy/fXg0xQzAy5h3zL1P8xT3QazgKqBrb/hAYwIBizqDBZ7GtJE74QQ==" 332 | }, 333 | "node_modules/domexception": { 334 | "version": "4.0.0", 335 | "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", 336 | "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", 337 | "dependencies": { 338 | "webidl-conversions": "^7.0.0" 339 | }, 340 | "engines": { 341 | "node": ">=12" 342 | } 343 | }, 344 | "node_modules/emoji-regex": { 345 | "version": "8.0.0", 346 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 347 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 348 | }, 349 | "node_modules/end-of-stream": { 350 | "version": "1.4.4", 351 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 352 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 353 | "dependencies": { 354 | "once": "^1.4.0" 355 | } 356 | }, 357 | "node_modules/escalade": { 358 | "version": "3.1.1", 359 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 360 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 361 | "engines": { 362 | "node": ">=6" 363 | } 364 | }, 365 | "node_modules/escodegen": { 366 | "version": "2.0.0", 367 | "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", 368 | "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", 369 | "dependencies": { 370 | "esprima": "^4.0.1", 371 | "estraverse": "^5.2.0", 372 | "esutils": "^2.0.2", 373 | "optionator": "^0.8.1" 374 | }, 375 | "bin": { 376 | "escodegen": "bin/escodegen.js", 377 | "esgenerate": "bin/esgenerate.js" 378 | }, 379 | "engines": { 380 | "node": ">=6.0" 381 | }, 382 | "optionalDependencies": { 383 | "source-map": "~0.6.1" 384 | } 385 | }, 386 | "node_modules/esprima": { 387 | "version": "4.0.1", 388 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 389 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 390 | "bin": { 391 | "esparse": "bin/esparse.js", 392 | "esvalidate": "bin/esvalidate.js" 393 | }, 394 | "engines": { 395 | "node": ">=4" 396 | } 397 | }, 398 | "node_modules/estraverse": { 399 | "version": "5.3.0", 400 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 401 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 402 | "engines": { 403 | "node": ">=4.0" 404 | } 405 | }, 406 | "node_modules/esutils": { 407 | "version": "2.0.3", 408 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 409 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 410 | "engines": { 411 | "node": ">=0.10.0" 412 | } 413 | }, 414 | "node_modules/extract-zip": { 415 | "version": "2.0.1", 416 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", 417 | "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", 418 | "dependencies": { 419 | "debug": "^4.1.1", 420 | "get-stream": "^5.1.0", 421 | "yauzl": "^2.10.0" 422 | }, 423 | "bin": { 424 | "extract-zip": "cli.js" 425 | }, 426 | "engines": { 427 | "node": ">= 10.17.0" 428 | }, 429 | "optionalDependencies": { 430 | "@types/yauzl": "^2.9.1" 431 | } 432 | }, 433 | "node_modules/fast-levenshtein": { 434 | "version": "2.0.6", 435 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 436 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" 437 | }, 438 | "node_modules/fd-slicer": { 439 | "version": "1.1.0", 440 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", 441 | "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", 442 | "dependencies": { 443 | "pend": "~1.2.0" 444 | } 445 | }, 446 | "node_modules/file-url": { 447 | "version": "3.0.0", 448 | "resolved": "https://registry.npmjs.org/file-url/-/file-url-3.0.0.tgz", 449 | "integrity": "sha512-g872QGsHexznxkIAdK8UiZRe7SkE6kvylShU4Nsj8NvfvZag7S0QuQ4IgvPDkk75HxgjIVDwycFTDAgIiO4nDA==", 450 | "engines": { 451 | "node": ">=8" 452 | } 453 | }, 454 | "node_modules/find-up": { 455 | "version": "4.1.0", 456 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 457 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 458 | "dependencies": { 459 | "locate-path": "^5.0.0", 460 | "path-exists": "^4.0.0" 461 | }, 462 | "engines": { 463 | "node": ">=8" 464 | } 465 | }, 466 | "node_modules/form-data": { 467 | "version": "4.0.0", 468 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", 469 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", 470 | "dependencies": { 471 | "asynckit": "^0.4.0", 472 | "combined-stream": "^1.0.8", 473 | "mime-types": "^2.1.12" 474 | }, 475 | "engines": { 476 | "node": ">= 6" 477 | } 478 | }, 479 | "node_modules/fs-constants": { 480 | "version": "1.0.0", 481 | "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", 482 | "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" 483 | }, 484 | "node_modules/fs.realpath": { 485 | "version": "1.0.0", 486 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 487 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 488 | }, 489 | "node_modules/get-caller-file": { 490 | "version": "2.0.5", 491 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 492 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 493 | "engines": { 494 | "node": "6.* || 8.* || >= 10.*" 495 | } 496 | }, 497 | "node_modules/get-stream": { 498 | "version": "5.2.0", 499 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 500 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 501 | "dependencies": { 502 | "pump": "^3.0.0" 503 | }, 504 | "engines": { 505 | "node": ">=8" 506 | }, 507 | "funding": { 508 | "url": "https://github.com/sponsors/sindresorhus" 509 | } 510 | }, 511 | "node_modules/glob": { 512 | "version": "7.2.0", 513 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 514 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 515 | "dependencies": { 516 | "fs.realpath": "^1.0.0", 517 | "inflight": "^1.0.4", 518 | "inherits": "2", 519 | "minimatch": "^3.0.4", 520 | "once": "^1.3.0", 521 | "path-is-absolute": "^1.0.0" 522 | }, 523 | "engines": { 524 | "node": "*" 525 | }, 526 | "funding": { 527 | "url": "https://github.com/sponsors/isaacs" 528 | } 529 | }, 530 | "node_modules/html-encoding-sniffer": { 531 | "version": "3.0.0", 532 | "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", 533 | "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", 534 | "dependencies": { 535 | "whatwg-encoding": "^2.0.0" 536 | }, 537 | "engines": { 538 | "node": ">=12" 539 | } 540 | }, 541 | "node_modules/http-proxy-agent": { 542 | "version": "5.0.0", 543 | "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", 544 | "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", 545 | "dependencies": { 546 | "@tootallnate/once": "2", 547 | "agent-base": "6", 548 | "debug": "4" 549 | }, 550 | "engines": { 551 | "node": ">= 6" 552 | } 553 | }, 554 | "node_modules/https-proxy-agent": { 555 | "version": "5.0.0", 556 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", 557 | "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", 558 | "dependencies": { 559 | "agent-base": "6", 560 | "debug": "4" 561 | }, 562 | "engines": { 563 | "node": ">= 6" 564 | } 565 | }, 566 | "node_modules/iconv-lite": { 567 | "version": "0.6.3", 568 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 569 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 570 | "dependencies": { 571 | "safer-buffer": ">= 2.1.2 < 3.0.0" 572 | }, 573 | "engines": { 574 | "node": ">=0.10.0" 575 | } 576 | }, 577 | "node_modules/ieee754": { 578 | "version": "1.2.1", 579 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 580 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 581 | "funding": [ 582 | { 583 | "type": "github", 584 | "url": "https://github.com/sponsors/feross" 585 | }, 586 | { 587 | "type": "patreon", 588 | "url": "https://www.patreon.com/feross" 589 | }, 590 | { 591 | "type": "consulting", 592 | "url": "https://feross.org/support" 593 | } 594 | ] 595 | }, 596 | "node_modules/immediate": { 597 | "version": "3.0.6", 598 | "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", 599 | "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" 600 | }, 601 | "node_modules/inflight": { 602 | "version": "1.0.6", 603 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 604 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 605 | "dependencies": { 606 | "once": "^1.3.0", 607 | "wrappy": "1" 608 | } 609 | }, 610 | "node_modules/inherits": { 611 | "version": "2.0.4", 612 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 613 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 614 | }, 615 | "node_modules/is-fullwidth-code-point": { 616 | "version": "3.0.0", 617 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 618 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 619 | "engines": { 620 | "node": ">=8" 621 | } 622 | }, 623 | "node_modules/is-potential-custom-element-name": { 624 | "version": "1.0.1", 625 | "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", 626 | "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" 627 | }, 628 | "node_modules/isarray": { 629 | "version": "1.0.0", 630 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 631 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 632 | }, 633 | "node_modules/jsdom": { 634 | "version": "18.1.1", 635 | "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-18.1.1.tgz", 636 | "integrity": "sha512-NmJQbjQ/gpS/1at/ce3nCx89HbXL/f5OcenBe8wU1Eik0ROhyUc3LtmG3567dEHAGXkN8rmILW/qtCOPxPHQJw==", 637 | "dependencies": { 638 | "abab": "^2.0.5", 639 | "acorn": "^8.5.0", 640 | "acorn-globals": "^6.0.0", 641 | "cssom": "^0.5.0", 642 | "cssstyle": "^2.3.0", 643 | "data-urls": "^3.0.1", 644 | "decimal.js": "^10.3.1", 645 | "domexception": "^4.0.0", 646 | "escodegen": "^2.0.0", 647 | "form-data": "^4.0.0", 648 | "html-encoding-sniffer": "^3.0.0", 649 | "http-proxy-agent": "^5.0.0", 650 | "https-proxy-agent": "^5.0.0", 651 | "is-potential-custom-element-name": "^1.0.1", 652 | "nwsapi": "^2.2.0", 653 | "parse5": "6.0.1", 654 | "saxes": "^5.0.1", 655 | "symbol-tree": "^3.2.4", 656 | "tough-cookie": "^4.0.0", 657 | "w3c-hr-time": "^1.0.2", 658 | "w3c-xmlserializer": "^3.0.0", 659 | "webidl-conversions": "^7.0.0", 660 | "whatwg-encoding": "^2.0.0", 661 | "whatwg-mimetype": "^3.0.0", 662 | "whatwg-url": "^10.0.0", 663 | "ws": "^8.2.3", 664 | "xml-name-validator": "^4.0.0" 665 | }, 666 | "engines": { 667 | "node": ">=12" 668 | }, 669 | "peerDependencies": { 670 | "canvas": "^2.5.0" 671 | }, 672 | "peerDependenciesMeta": { 673 | "canvas": { 674 | "optional": true 675 | } 676 | } 677 | }, 678 | "node_modules/jszip": { 679 | "version": "3.7.1", 680 | "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz", 681 | "integrity": "sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==", 682 | "dependencies": { 683 | "lie": "~3.3.0", 684 | "pako": "~1.0.2", 685 | "readable-stream": "~2.3.6", 686 | "set-immediate-shim": "~1.0.1" 687 | } 688 | }, 689 | "node_modules/levn": { 690 | "version": "0.3.0", 691 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 692 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 693 | "dependencies": { 694 | "prelude-ls": "~1.1.2", 695 | "type-check": "~0.3.2" 696 | }, 697 | "engines": { 698 | "node": ">= 0.8.0" 699 | } 700 | }, 701 | "node_modules/lie": { 702 | "version": "3.3.0", 703 | "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", 704 | "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", 705 | "dependencies": { 706 | "immediate": "~3.0.5" 707 | } 708 | }, 709 | "node_modules/locate-path": { 710 | "version": "5.0.0", 711 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 712 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 713 | "dependencies": { 714 | "p-locate": "^4.1.0" 715 | }, 716 | "engines": { 717 | "node": ">=8" 718 | } 719 | }, 720 | "node_modules/mime-db": { 721 | "version": "1.51.0", 722 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", 723 | "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", 724 | "engines": { 725 | "node": ">= 0.6" 726 | } 727 | }, 728 | "node_modules/mime-types": { 729 | "version": "2.1.34", 730 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", 731 | "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", 732 | "dependencies": { 733 | "mime-db": "1.51.0" 734 | }, 735 | "engines": { 736 | "node": ">= 0.6" 737 | } 738 | }, 739 | "node_modules/minimatch": { 740 | "version": "3.0.4", 741 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 742 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 743 | "dependencies": { 744 | "brace-expansion": "^1.1.7" 745 | }, 746 | "engines": { 747 | "node": "*" 748 | } 749 | }, 750 | "node_modules/mkdirp-classic": { 751 | "version": "0.5.3", 752 | "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", 753 | "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" 754 | }, 755 | "node_modules/ms": { 756 | "version": "2.1.2", 757 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 758 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 759 | }, 760 | "node_modules/node-fetch": { 761 | "version": "2.6.5", 762 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz", 763 | "integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==", 764 | "dependencies": { 765 | "whatwg-url": "^5.0.0" 766 | }, 767 | "engines": { 768 | "node": "4.x || >=6.0.0" 769 | } 770 | }, 771 | "node_modules/node-fetch/node_modules/tr46": { 772 | "version": "0.0.3", 773 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 774 | "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" 775 | }, 776 | "node_modules/node-fetch/node_modules/webidl-conversions": { 777 | "version": "3.0.1", 778 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 779 | "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" 780 | }, 781 | "node_modules/node-fetch/node_modules/whatwg-url": { 782 | "version": "5.0.0", 783 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 784 | "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", 785 | "dependencies": { 786 | "tr46": "~0.0.3", 787 | "webidl-conversions": "^3.0.0" 788 | } 789 | }, 790 | "node_modules/nwsapi": { 791 | "version": "2.2.0", 792 | "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", 793 | "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==" 794 | }, 795 | "node_modules/once": { 796 | "version": "1.4.0", 797 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 798 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 799 | "dependencies": { 800 | "wrappy": "1" 801 | } 802 | }, 803 | "node_modules/optionator": { 804 | "version": "0.8.3", 805 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", 806 | "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", 807 | "dependencies": { 808 | "deep-is": "~0.1.3", 809 | "fast-levenshtein": "~2.0.6", 810 | "levn": "~0.3.0", 811 | "prelude-ls": "~1.1.2", 812 | "type-check": "~0.3.2", 813 | "word-wrap": "~1.2.3" 814 | }, 815 | "engines": { 816 | "node": ">= 0.8.0" 817 | } 818 | }, 819 | "node_modules/p-limit": { 820 | "version": "2.3.0", 821 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 822 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 823 | "dependencies": { 824 | "p-try": "^2.0.0" 825 | }, 826 | "engines": { 827 | "node": ">=6" 828 | }, 829 | "funding": { 830 | "url": "https://github.com/sponsors/sindresorhus" 831 | } 832 | }, 833 | "node_modules/p-locate": { 834 | "version": "4.1.0", 835 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 836 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 837 | "dependencies": { 838 | "p-limit": "^2.2.0" 839 | }, 840 | "engines": { 841 | "node": ">=8" 842 | } 843 | }, 844 | "node_modules/p-try": { 845 | "version": "2.2.0", 846 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 847 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 848 | "engines": { 849 | "node": ">=6" 850 | } 851 | }, 852 | "node_modules/pako": { 853 | "version": "1.0.11", 854 | "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", 855 | "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" 856 | }, 857 | "node_modules/parse5": { 858 | "version": "6.0.1", 859 | "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", 860 | "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" 861 | }, 862 | "node_modules/path-exists": { 863 | "version": "4.0.0", 864 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 865 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 866 | "engines": { 867 | "node": ">=8" 868 | } 869 | }, 870 | "node_modules/path-is-absolute": { 871 | "version": "1.0.1", 872 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 873 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 874 | "engines": { 875 | "node": ">=0.10.0" 876 | } 877 | }, 878 | "node_modules/pend": { 879 | "version": "1.2.0", 880 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 881 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" 882 | }, 883 | "node_modules/pkg-dir": { 884 | "version": "4.2.0", 885 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", 886 | "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", 887 | "dependencies": { 888 | "find-up": "^4.0.0" 889 | }, 890 | "engines": { 891 | "node": ">=8" 892 | } 893 | }, 894 | "node_modules/prelude-ls": { 895 | "version": "1.1.2", 896 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 897 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 898 | "engines": { 899 | "node": ">= 0.8.0" 900 | } 901 | }, 902 | "node_modules/process-nextick-args": { 903 | "version": "2.0.1", 904 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 905 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 906 | }, 907 | "node_modules/progress": { 908 | "version": "2.0.3", 909 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 910 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 911 | "engines": { 912 | "node": ">=0.4.0" 913 | } 914 | }, 915 | "node_modules/proxy-from-env": { 916 | "version": "1.1.0", 917 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", 918 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" 919 | }, 920 | "node_modules/psl": { 921 | "version": "1.8.0", 922 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", 923 | "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" 924 | }, 925 | "node_modules/pump": { 926 | "version": "3.0.0", 927 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 928 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 929 | "dependencies": { 930 | "end-of-stream": "^1.1.0", 931 | "once": "^1.3.1" 932 | } 933 | }, 934 | "node_modules/punycode": { 935 | "version": "2.1.1", 936 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 937 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 938 | "engines": { 939 | "node": ">=6" 940 | } 941 | }, 942 | "node_modules/puppeteer-core": { 943 | "version": "11.0.0", 944 | "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-11.0.0.tgz", 945 | "integrity": "sha512-hfQ39KNP0qKplQ86iaCNXHH9zpWlV01UFdggt2qffgWeCBF9KMavwP/k/iK/JidPPWfOnKZhDLSHZVSUr73DtA==", 946 | "dependencies": { 947 | "debug": "4.3.2", 948 | "devtools-protocol": "0.0.901419", 949 | "extract-zip": "2.0.1", 950 | "https-proxy-agent": "5.0.0", 951 | "node-fetch": "2.6.5", 952 | "pkg-dir": "4.2.0", 953 | "progress": "2.0.3", 954 | "proxy-from-env": "1.1.0", 955 | "rimraf": "3.0.2", 956 | "tar-fs": "2.1.1", 957 | "unbzip2-stream": "1.4.3", 958 | "ws": "8.2.3" 959 | }, 960 | "engines": { 961 | "node": ">=10.18.1" 962 | } 963 | }, 964 | "node_modules/puppeteer-core/node_modules/debug": { 965 | "version": "4.3.2", 966 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", 967 | "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", 968 | "dependencies": { 969 | "ms": "2.1.2" 970 | }, 971 | "engines": { 972 | "node": ">=6.0" 973 | }, 974 | "peerDependenciesMeta": { 975 | "supports-color": { 976 | "optional": true 977 | } 978 | } 979 | }, 980 | "node_modules/puppeteer-core/node_modules/ws": { 981 | "version": "8.2.3", 982 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", 983 | "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", 984 | "engines": { 985 | "node": ">=10.0.0" 986 | }, 987 | "peerDependencies": { 988 | "bufferutil": "^4.0.1", 989 | "utf-8-validate": "^5.0.2" 990 | }, 991 | "peerDependenciesMeta": { 992 | "bufferutil": { 993 | "optional": true 994 | }, 995 | "utf-8-validate": { 996 | "optional": true 997 | } 998 | } 999 | }, 1000 | "node_modules/readable-stream": { 1001 | "version": "2.3.7", 1002 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 1003 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 1004 | "dependencies": { 1005 | "core-util-is": "~1.0.0", 1006 | "inherits": "~2.0.3", 1007 | "isarray": "~1.0.0", 1008 | "process-nextick-args": "~2.0.0", 1009 | "safe-buffer": "~5.1.1", 1010 | "string_decoder": "~1.1.1", 1011 | "util-deprecate": "~1.0.1" 1012 | } 1013 | }, 1014 | "node_modules/require-directory": { 1015 | "version": "2.1.1", 1016 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1017 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 1018 | "engines": { 1019 | "node": ">=0.10.0" 1020 | } 1021 | }, 1022 | "node_modules/rimraf": { 1023 | "version": "3.0.2", 1024 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1025 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1026 | "dependencies": { 1027 | "glob": "^7.1.3" 1028 | }, 1029 | "bin": { 1030 | "rimraf": "bin.js" 1031 | }, 1032 | "funding": { 1033 | "url": "https://github.com/sponsors/isaacs" 1034 | } 1035 | }, 1036 | "node_modules/safe-buffer": { 1037 | "version": "5.1.2", 1038 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1039 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1040 | }, 1041 | "node_modules/safer-buffer": { 1042 | "version": "2.1.2", 1043 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1044 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1045 | }, 1046 | "node_modules/saxes": { 1047 | "version": "5.0.1", 1048 | "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", 1049 | "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", 1050 | "dependencies": { 1051 | "xmlchars": "^2.2.0" 1052 | }, 1053 | "engines": { 1054 | "node": ">=10" 1055 | } 1056 | }, 1057 | "node_modules/selenium-webdriver": { 1058 | "version": "4.1.0", 1059 | "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.1.0.tgz", 1060 | "integrity": "sha512-kUDH4N8WruYprTzvug4Pl73Th+WKb5YiLz8z/anOpHyUNUdM3UzrdTOxmSNaf9AczzBeY+qXihzku8D1lMaKOg==", 1061 | "dependencies": { 1062 | "jszip": "^3.6.0", 1063 | "tmp": "^0.2.1", 1064 | "ws": ">=7.4.6" 1065 | }, 1066 | "engines": { 1067 | "node": ">= 10.15.0" 1068 | } 1069 | }, 1070 | "node_modules/set-immediate-shim": { 1071 | "version": "1.0.1", 1072 | "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", 1073 | "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", 1074 | "engines": { 1075 | "node": ">=0.10.0" 1076 | } 1077 | }, 1078 | "node_modules/single-file": { 1079 | "version": "0.3.32", 1080 | "resolved": "git+ssh://git@github.com/gildas-lormeau/SingleFile.git#ce34d3f8c657acf808c5273b6b7e01413500763d", 1081 | "license": "AGPL-3.0-or-later", 1082 | "dependencies": { 1083 | "file-url": "^3.0.0", 1084 | "iconv-lite": "^0.6.3", 1085 | "jsdom": "^18.1.0", 1086 | "puppeteer-core": "^11.0.0", 1087 | "selenium-webdriver": "^4.0.0", 1088 | "strong-data-uri": "^1.0.6", 1089 | "yargs": "^17.2.1" 1090 | }, 1091 | "bin": { 1092 | "single-file": "cli/single-file" 1093 | } 1094 | }, 1095 | "node_modules/source-map": { 1096 | "version": "0.6.1", 1097 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1098 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1099 | "optional": true, 1100 | "engines": { 1101 | "node": ">=0.10.0" 1102 | } 1103 | }, 1104 | "node_modules/string_decoder": { 1105 | "version": "1.1.1", 1106 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1107 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1108 | "dependencies": { 1109 | "safe-buffer": "~5.1.0" 1110 | } 1111 | }, 1112 | "node_modules/string-width": { 1113 | "version": "4.2.3", 1114 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1115 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1116 | "dependencies": { 1117 | "emoji-regex": "^8.0.0", 1118 | "is-fullwidth-code-point": "^3.0.0", 1119 | "strip-ansi": "^6.0.1" 1120 | }, 1121 | "engines": { 1122 | "node": ">=8" 1123 | } 1124 | }, 1125 | "node_modules/strip-ansi": { 1126 | "version": "6.0.1", 1127 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1128 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1129 | "dependencies": { 1130 | "ansi-regex": "^5.0.1" 1131 | }, 1132 | "engines": { 1133 | "node": ">=8" 1134 | } 1135 | }, 1136 | "node_modules/strong-data-uri": { 1137 | "version": "1.0.6", 1138 | "resolved": "https://registry.npmjs.org/strong-data-uri/-/strong-data-uri-1.0.6.tgz", 1139 | "integrity": "sha512-zhzBZev0uhT2IrFUerenXhfaE0vFUYwAZsnG0gIKGpfM/Gi6jOUQ3cmcvyTsXeDLIPiTubHESeO7EbD6FoPmzw==", 1140 | "dependencies": { 1141 | "truncate": "^2.0.1" 1142 | }, 1143 | "engines": { 1144 | "node": ">=0.8.0" 1145 | } 1146 | }, 1147 | "node_modules/symbol-tree": { 1148 | "version": "3.2.4", 1149 | "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", 1150 | "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" 1151 | }, 1152 | "node_modules/tar-fs": { 1153 | "version": "2.1.1", 1154 | "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", 1155 | "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", 1156 | "dependencies": { 1157 | "chownr": "^1.1.1", 1158 | "mkdirp-classic": "^0.5.2", 1159 | "pump": "^3.0.0", 1160 | "tar-stream": "^2.1.4" 1161 | } 1162 | }, 1163 | "node_modules/tar-stream": { 1164 | "version": "2.2.0", 1165 | "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", 1166 | "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", 1167 | "dependencies": { 1168 | "bl": "^4.0.3", 1169 | "end-of-stream": "^1.4.1", 1170 | "fs-constants": "^1.0.0", 1171 | "inherits": "^2.0.3", 1172 | "readable-stream": "^3.1.1" 1173 | }, 1174 | "engines": { 1175 | "node": ">=6" 1176 | } 1177 | }, 1178 | "node_modules/tar-stream/node_modules/readable-stream": { 1179 | "version": "3.6.0", 1180 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 1181 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 1182 | "dependencies": { 1183 | "inherits": "^2.0.3", 1184 | "string_decoder": "^1.1.1", 1185 | "util-deprecate": "^1.0.1" 1186 | }, 1187 | "engines": { 1188 | "node": ">= 6" 1189 | } 1190 | }, 1191 | "node_modules/through": { 1192 | "version": "2.3.8", 1193 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1194 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 1195 | }, 1196 | "node_modules/tmp": { 1197 | "version": "0.2.1", 1198 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", 1199 | "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", 1200 | "dependencies": { 1201 | "rimraf": "^3.0.0" 1202 | }, 1203 | "engines": { 1204 | "node": ">=8.17.0" 1205 | } 1206 | }, 1207 | "node_modules/tough-cookie": { 1208 | "version": "4.0.0", 1209 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", 1210 | "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", 1211 | "dependencies": { 1212 | "psl": "^1.1.33", 1213 | "punycode": "^2.1.1", 1214 | "universalify": "^0.1.2" 1215 | }, 1216 | "engines": { 1217 | "node": ">=6" 1218 | } 1219 | }, 1220 | "node_modules/tr46": { 1221 | "version": "3.0.0", 1222 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", 1223 | "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", 1224 | "dependencies": { 1225 | "punycode": "^2.1.1" 1226 | }, 1227 | "engines": { 1228 | "node": ">=12" 1229 | } 1230 | }, 1231 | "node_modules/truncate": { 1232 | "version": "2.1.0", 1233 | "resolved": "https://registry.npmjs.org/truncate/-/truncate-2.1.0.tgz", 1234 | "integrity": "sha512-em3E3SUDONOjTBcZ36DTm3RvDded3IRU9rX32oHwwXNt3rJD5MVaFlJTQvs8tJoHRoeYP36OuQ1eL/Q7bNEWIQ==", 1235 | "engines": { 1236 | "node": "*" 1237 | } 1238 | }, 1239 | "node_modules/type-check": { 1240 | "version": "0.3.2", 1241 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 1242 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 1243 | "dependencies": { 1244 | "prelude-ls": "~1.1.2" 1245 | }, 1246 | "engines": { 1247 | "node": ">= 0.8.0" 1248 | } 1249 | }, 1250 | "node_modules/unbzip2-stream": { 1251 | "version": "1.4.3", 1252 | "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", 1253 | "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", 1254 | "dependencies": { 1255 | "buffer": "^5.2.1", 1256 | "through": "^2.3.8" 1257 | } 1258 | }, 1259 | "node_modules/universalify": { 1260 | "version": "0.1.2", 1261 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 1262 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", 1263 | "engines": { 1264 | "node": ">= 4.0.0" 1265 | } 1266 | }, 1267 | "node_modules/util-deprecate": { 1268 | "version": "1.0.2", 1269 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1270 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1271 | }, 1272 | "node_modules/w3c-hr-time": { 1273 | "version": "1.0.2", 1274 | "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", 1275 | "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", 1276 | "dependencies": { 1277 | "browser-process-hrtime": "^1.0.0" 1278 | } 1279 | }, 1280 | "node_modules/w3c-xmlserializer": { 1281 | "version": "3.0.0", 1282 | "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", 1283 | "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", 1284 | "dependencies": { 1285 | "xml-name-validator": "^4.0.0" 1286 | }, 1287 | "engines": { 1288 | "node": ">=12" 1289 | } 1290 | }, 1291 | "node_modules/webidl-conversions": { 1292 | "version": "7.0.0", 1293 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", 1294 | "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", 1295 | "engines": { 1296 | "node": ">=12" 1297 | } 1298 | }, 1299 | "node_modules/whatwg-encoding": { 1300 | "version": "2.0.0", 1301 | "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", 1302 | "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", 1303 | "dependencies": { 1304 | "iconv-lite": "0.6.3" 1305 | }, 1306 | "engines": { 1307 | "node": ">=12" 1308 | } 1309 | }, 1310 | "node_modules/whatwg-mimetype": { 1311 | "version": "3.0.0", 1312 | "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", 1313 | "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", 1314 | "engines": { 1315 | "node": ">=12" 1316 | } 1317 | }, 1318 | "node_modules/whatwg-url": { 1319 | "version": "10.0.0", 1320 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-10.0.0.tgz", 1321 | "integrity": "sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w==", 1322 | "dependencies": { 1323 | "tr46": "^3.0.0", 1324 | "webidl-conversions": "^7.0.0" 1325 | }, 1326 | "engines": { 1327 | "node": ">=12" 1328 | } 1329 | }, 1330 | "node_modules/word-wrap": { 1331 | "version": "1.2.3", 1332 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 1333 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 1334 | "engines": { 1335 | "node": ">=0.10.0" 1336 | } 1337 | }, 1338 | "node_modules/wrap-ansi": { 1339 | "version": "7.0.0", 1340 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 1341 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 1342 | "dependencies": { 1343 | "ansi-styles": "^4.0.0", 1344 | "string-width": "^4.1.0", 1345 | "strip-ansi": "^6.0.0" 1346 | }, 1347 | "engines": { 1348 | "node": ">=10" 1349 | }, 1350 | "funding": { 1351 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 1352 | } 1353 | }, 1354 | "node_modules/wrappy": { 1355 | "version": "1.0.2", 1356 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1357 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 1358 | }, 1359 | "node_modules/ws": { 1360 | "version": "8.3.0", 1361 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.3.0.tgz", 1362 | "integrity": "sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw==", 1363 | "engines": { 1364 | "node": ">=10.0.0" 1365 | }, 1366 | "peerDependencies": { 1367 | "bufferutil": "^4.0.1", 1368 | "utf-8-validate": "^5.0.2" 1369 | }, 1370 | "peerDependenciesMeta": { 1371 | "bufferutil": { 1372 | "optional": true 1373 | }, 1374 | "utf-8-validate": { 1375 | "optional": true 1376 | } 1377 | } 1378 | }, 1379 | "node_modules/xml-name-validator": { 1380 | "version": "4.0.0", 1381 | "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", 1382 | "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", 1383 | "engines": { 1384 | "node": ">=12" 1385 | } 1386 | }, 1387 | "node_modules/xmlchars": { 1388 | "version": "2.2.0", 1389 | "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", 1390 | "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" 1391 | }, 1392 | "node_modules/y18n": { 1393 | "version": "5.0.8", 1394 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 1395 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 1396 | "engines": { 1397 | "node": ">=10" 1398 | } 1399 | }, 1400 | "node_modules/yargs": { 1401 | "version": "17.3.0", 1402 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.0.tgz", 1403 | "integrity": "sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew==", 1404 | "dependencies": { 1405 | "cliui": "^7.0.2", 1406 | "escalade": "^3.1.1", 1407 | "get-caller-file": "^2.0.5", 1408 | "require-directory": "^2.1.1", 1409 | "string-width": "^4.2.3", 1410 | "y18n": "^5.0.5", 1411 | "yargs-parser": "^21.0.0" 1412 | }, 1413 | "engines": { 1414 | "node": ">=12" 1415 | } 1416 | }, 1417 | "node_modules/yargs-parser": { 1418 | "version": "21.0.0", 1419 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", 1420 | "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==", 1421 | "engines": { 1422 | "node": ">=12" 1423 | } 1424 | }, 1425 | "node_modules/yauzl": { 1426 | "version": "2.10.0", 1427 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", 1428 | "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", 1429 | "dependencies": { 1430 | "buffer-crc32": "~0.2.3", 1431 | "fd-slicer": "~1.1.0" 1432 | } 1433 | } 1434 | }, 1435 | "dependencies": { 1436 | "@tootallnate/once": { 1437 | "version": "2.0.0", 1438 | "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", 1439 | "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" 1440 | }, 1441 | "@types/node": { 1442 | "version": "17.0.0", 1443 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.0.tgz", 1444 | "integrity": "sha512-eMhwJXc931Ihh4tkU+Y7GiLzT/y/DBNpNtr4yU9O2w3SYBsr9NaOPhQlLKRmoWtI54uNwuo0IOUFQjVOTZYRvw==", 1445 | "optional": true 1446 | }, 1447 | "@types/yauzl": { 1448 | "version": "2.9.2", 1449 | "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", 1450 | "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==", 1451 | "optional": true, 1452 | "requires": { 1453 | "@types/node": "*" 1454 | } 1455 | }, 1456 | "abab": { 1457 | "version": "2.0.5", 1458 | "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", 1459 | "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==" 1460 | }, 1461 | "acorn": { 1462 | "version": "8.6.0", 1463 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", 1464 | "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==" 1465 | }, 1466 | "acorn-globals": { 1467 | "version": "6.0.0", 1468 | "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", 1469 | "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", 1470 | "requires": { 1471 | "acorn": "^7.1.1", 1472 | "acorn-walk": "^7.1.1" 1473 | }, 1474 | "dependencies": { 1475 | "acorn": { 1476 | "version": "7.4.1", 1477 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", 1478 | "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" 1479 | } 1480 | } 1481 | }, 1482 | "acorn-walk": { 1483 | "version": "7.2.0", 1484 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", 1485 | "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" 1486 | }, 1487 | "agent-base": { 1488 | "version": "6.0.2", 1489 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", 1490 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", 1491 | "requires": { 1492 | "debug": "4" 1493 | } 1494 | }, 1495 | "ansi-regex": { 1496 | "version": "5.0.1", 1497 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1498 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" 1499 | }, 1500 | "ansi-styles": { 1501 | "version": "4.3.0", 1502 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1503 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1504 | "requires": { 1505 | "color-convert": "^2.0.1" 1506 | } 1507 | }, 1508 | "asynckit": { 1509 | "version": "0.4.0", 1510 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 1511 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 1512 | }, 1513 | "balanced-match": { 1514 | "version": "1.0.2", 1515 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1516 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 1517 | }, 1518 | "base64-js": { 1519 | "version": "1.5.1", 1520 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 1521 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" 1522 | }, 1523 | "bl": { 1524 | "version": "4.1.0", 1525 | "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", 1526 | "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", 1527 | "requires": { 1528 | "buffer": "^5.5.0", 1529 | "inherits": "^2.0.4", 1530 | "readable-stream": "^3.4.0" 1531 | }, 1532 | "dependencies": { 1533 | "readable-stream": { 1534 | "version": "3.6.0", 1535 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 1536 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 1537 | "requires": { 1538 | "inherits": "^2.0.3", 1539 | "string_decoder": "^1.1.1", 1540 | "util-deprecate": "^1.0.1" 1541 | } 1542 | } 1543 | } 1544 | }, 1545 | "brace-expansion": { 1546 | "version": "1.1.11", 1547 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 1548 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 1549 | "requires": { 1550 | "balanced-match": "^1.0.0", 1551 | "concat-map": "0.0.1" 1552 | } 1553 | }, 1554 | "browser-process-hrtime": { 1555 | "version": "1.0.0", 1556 | "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", 1557 | "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" 1558 | }, 1559 | "buffer": { 1560 | "version": "5.7.1", 1561 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 1562 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 1563 | "requires": { 1564 | "base64-js": "^1.3.1", 1565 | "ieee754": "^1.1.13" 1566 | } 1567 | }, 1568 | "buffer-crc32": { 1569 | "version": "0.2.13", 1570 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 1571 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" 1572 | }, 1573 | "chownr": { 1574 | "version": "1.1.4", 1575 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", 1576 | "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" 1577 | }, 1578 | "cliui": { 1579 | "version": "7.0.4", 1580 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 1581 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 1582 | "requires": { 1583 | "string-width": "^4.2.0", 1584 | "strip-ansi": "^6.0.0", 1585 | "wrap-ansi": "^7.0.0" 1586 | } 1587 | }, 1588 | "color-convert": { 1589 | "version": "2.0.1", 1590 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1591 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1592 | "requires": { 1593 | "color-name": "~1.1.4" 1594 | } 1595 | }, 1596 | "color-name": { 1597 | "version": "1.1.4", 1598 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1599 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 1600 | }, 1601 | "combined-stream": { 1602 | "version": "1.0.8", 1603 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 1604 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 1605 | "requires": { 1606 | "delayed-stream": "~1.0.0" 1607 | } 1608 | }, 1609 | "concat-map": { 1610 | "version": "0.0.1", 1611 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 1612 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 1613 | }, 1614 | "core-util-is": { 1615 | "version": "1.0.3", 1616 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", 1617 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" 1618 | }, 1619 | "cssom": { 1620 | "version": "0.5.0", 1621 | "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", 1622 | "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==" 1623 | }, 1624 | "cssstyle": { 1625 | "version": "2.3.0", 1626 | "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", 1627 | "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", 1628 | "requires": { 1629 | "cssom": "~0.3.6" 1630 | }, 1631 | "dependencies": { 1632 | "cssom": { 1633 | "version": "0.3.8", 1634 | "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", 1635 | "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" 1636 | } 1637 | } 1638 | }, 1639 | "data-urls": { 1640 | "version": "3.0.1", 1641 | "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.1.tgz", 1642 | "integrity": "sha512-Ds554NeT5Gennfoo9KN50Vh6tpgtvYEwraYjejXnyTpu1C7oXKxdFk75REooENHE8ndTVOJuv+BEs4/J/xcozw==", 1643 | "requires": { 1644 | "abab": "^2.0.3", 1645 | "whatwg-mimetype": "^3.0.0", 1646 | "whatwg-url": "^10.0.0" 1647 | } 1648 | }, 1649 | "debug": { 1650 | "version": "4.3.3", 1651 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", 1652 | "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", 1653 | "requires": { 1654 | "ms": "2.1.2" 1655 | } 1656 | }, 1657 | "decimal.js": { 1658 | "version": "10.3.1", 1659 | "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", 1660 | "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==" 1661 | }, 1662 | "deep-is": { 1663 | "version": "0.1.4", 1664 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 1665 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" 1666 | }, 1667 | "delayed-stream": { 1668 | "version": "1.0.0", 1669 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 1670 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 1671 | }, 1672 | "devtools-protocol": { 1673 | "version": "0.0.901419", 1674 | "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.901419.tgz", 1675 | "integrity": "sha512-4INMPwNm9XRpBukhNbF7OB6fNTTCaI8pzy/fXg0xQzAy5h3zL1P8xT3QazgKqBrb/hAYwIBizqDBZ7GtJE74QQ==" 1676 | }, 1677 | "domexception": { 1678 | "version": "4.0.0", 1679 | "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", 1680 | "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", 1681 | "requires": { 1682 | "webidl-conversions": "^7.0.0" 1683 | } 1684 | }, 1685 | "emoji-regex": { 1686 | "version": "8.0.0", 1687 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1688 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 1689 | }, 1690 | "end-of-stream": { 1691 | "version": "1.4.4", 1692 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 1693 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 1694 | "requires": { 1695 | "once": "^1.4.0" 1696 | } 1697 | }, 1698 | "escalade": { 1699 | "version": "3.1.1", 1700 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 1701 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" 1702 | }, 1703 | "escodegen": { 1704 | "version": "2.0.0", 1705 | "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", 1706 | "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", 1707 | "requires": { 1708 | "esprima": "^4.0.1", 1709 | "estraverse": "^5.2.0", 1710 | "esutils": "^2.0.2", 1711 | "optionator": "^0.8.1", 1712 | "source-map": "~0.6.1" 1713 | } 1714 | }, 1715 | "esprima": { 1716 | "version": "4.0.1", 1717 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 1718 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" 1719 | }, 1720 | "estraverse": { 1721 | "version": "5.3.0", 1722 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 1723 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" 1724 | }, 1725 | "esutils": { 1726 | "version": "2.0.3", 1727 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 1728 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" 1729 | }, 1730 | "extract-zip": { 1731 | "version": "2.0.1", 1732 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", 1733 | "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", 1734 | "requires": { 1735 | "@types/yauzl": "^2.9.1", 1736 | "debug": "^4.1.1", 1737 | "get-stream": "^5.1.0", 1738 | "yauzl": "^2.10.0" 1739 | } 1740 | }, 1741 | "fast-levenshtein": { 1742 | "version": "2.0.6", 1743 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 1744 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" 1745 | }, 1746 | "fd-slicer": { 1747 | "version": "1.1.0", 1748 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", 1749 | "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", 1750 | "requires": { 1751 | "pend": "~1.2.0" 1752 | } 1753 | }, 1754 | "file-url": { 1755 | "version": "3.0.0", 1756 | "resolved": "https://registry.npmjs.org/file-url/-/file-url-3.0.0.tgz", 1757 | "integrity": "sha512-g872QGsHexznxkIAdK8UiZRe7SkE6kvylShU4Nsj8NvfvZag7S0QuQ4IgvPDkk75HxgjIVDwycFTDAgIiO4nDA==" 1758 | }, 1759 | "find-up": { 1760 | "version": "4.1.0", 1761 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 1762 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 1763 | "requires": { 1764 | "locate-path": "^5.0.0", 1765 | "path-exists": "^4.0.0" 1766 | } 1767 | }, 1768 | "form-data": { 1769 | "version": "4.0.0", 1770 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", 1771 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", 1772 | "requires": { 1773 | "asynckit": "^0.4.0", 1774 | "combined-stream": "^1.0.8", 1775 | "mime-types": "^2.1.12" 1776 | } 1777 | }, 1778 | "fs-constants": { 1779 | "version": "1.0.0", 1780 | "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", 1781 | "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" 1782 | }, 1783 | "fs.realpath": { 1784 | "version": "1.0.0", 1785 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1786 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 1787 | }, 1788 | "get-caller-file": { 1789 | "version": "2.0.5", 1790 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 1791 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" 1792 | }, 1793 | "get-stream": { 1794 | "version": "5.2.0", 1795 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 1796 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 1797 | "requires": { 1798 | "pump": "^3.0.0" 1799 | } 1800 | }, 1801 | "glob": { 1802 | "version": "7.2.0", 1803 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 1804 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 1805 | "requires": { 1806 | "fs.realpath": "^1.0.0", 1807 | "inflight": "^1.0.4", 1808 | "inherits": "2", 1809 | "minimatch": "^3.0.4", 1810 | "once": "^1.3.0", 1811 | "path-is-absolute": "^1.0.0" 1812 | } 1813 | }, 1814 | "html-encoding-sniffer": { 1815 | "version": "3.0.0", 1816 | "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", 1817 | "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", 1818 | "requires": { 1819 | "whatwg-encoding": "^2.0.0" 1820 | } 1821 | }, 1822 | "http-proxy-agent": { 1823 | "version": "5.0.0", 1824 | "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", 1825 | "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", 1826 | "requires": { 1827 | "@tootallnate/once": "2", 1828 | "agent-base": "6", 1829 | "debug": "4" 1830 | } 1831 | }, 1832 | "https-proxy-agent": { 1833 | "version": "5.0.0", 1834 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", 1835 | "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", 1836 | "requires": { 1837 | "agent-base": "6", 1838 | "debug": "4" 1839 | } 1840 | }, 1841 | "iconv-lite": { 1842 | "version": "0.6.3", 1843 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 1844 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 1845 | "requires": { 1846 | "safer-buffer": ">= 2.1.2 < 3.0.0" 1847 | } 1848 | }, 1849 | "ieee754": { 1850 | "version": "1.2.1", 1851 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 1852 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" 1853 | }, 1854 | "immediate": { 1855 | "version": "3.0.6", 1856 | "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", 1857 | "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" 1858 | }, 1859 | "inflight": { 1860 | "version": "1.0.6", 1861 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1862 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1863 | "requires": { 1864 | "once": "^1.3.0", 1865 | "wrappy": "1" 1866 | } 1867 | }, 1868 | "inherits": { 1869 | "version": "2.0.4", 1870 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1871 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1872 | }, 1873 | "is-fullwidth-code-point": { 1874 | "version": "3.0.0", 1875 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1876 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" 1877 | }, 1878 | "is-potential-custom-element-name": { 1879 | "version": "1.0.1", 1880 | "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", 1881 | "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" 1882 | }, 1883 | "isarray": { 1884 | "version": "1.0.0", 1885 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1886 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 1887 | }, 1888 | "jsdom": { 1889 | "version": "18.1.1", 1890 | "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-18.1.1.tgz", 1891 | "integrity": "sha512-NmJQbjQ/gpS/1at/ce3nCx89HbXL/f5OcenBe8wU1Eik0ROhyUc3LtmG3567dEHAGXkN8rmILW/qtCOPxPHQJw==", 1892 | "requires": { 1893 | "abab": "^2.0.5", 1894 | "acorn": "^8.5.0", 1895 | "acorn-globals": "^6.0.0", 1896 | "cssom": "^0.5.0", 1897 | "cssstyle": "^2.3.0", 1898 | "data-urls": "^3.0.1", 1899 | "decimal.js": "^10.3.1", 1900 | "domexception": "^4.0.0", 1901 | "escodegen": "^2.0.0", 1902 | "form-data": "^4.0.0", 1903 | "html-encoding-sniffer": "^3.0.0", 1904 | "http-proxy-agent": "^5.0.0", 1905 | "https-proxy-agent": "^5.0.0", 1906 | "is-potential-custom-element-name": "^1.0.1", 1907 | "nwsapi": "^2.2.0", 1908 | "parse5": "6.0.1", 1909 | "saxes": "^5.0.1", 1910 | "symbol-tree": "^3.2.4", 1911 | "tough-cookie": "^4.0.0", 1912 | "w3c-hr-time": "^1.0.2", 1913 | "w3c-xmlserializer": "^3.0.0", 1914 | "webidl-conversions": "^7.0.0", 1915 | "whatwg-encoding": "^2.0.0", 1916 | "whatwg-mimetype": "^3.0.0", 1917 | "whatwg-url": "^10.0.0", 1918 | "ws": "^8.2.3", 1919 | "xml-name-validator": "^4.0.0" 1920 | } 1921 | }, 1922 | "jszip": { 1923 | "version": "3.7.1", 1924 | "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz", 1925 | "integrity": "sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==", 1926 | "requires": { 1927 | "lie": "~3.3.0", 1928 | "pako": "~1.0.2", 1929 | "readable-stream": "~2.3.6", 1930 | "set-immediate-shim": "~1.0.1" 1931 | } 1932 | }, 1933 | "levn": { 1934 | "version": "0.3.0", 1935 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 1936 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 1937 | "requires": { 1938 | "prelude-ls": "~1.1.2", 1939 | "type-check": "~0.3.2" 1940 | } 1941 | }, 1942 | "lie": { 1943 | "version": "3.3.0", 1944 | "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", 1945 | "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", 1946 | "requires": { 1947 | "immediate": "~3.0.5" 1948 | } 1949 | }, 1950 | "locate-path": { 1951 | "version": "5.0.0", 1952 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 1953 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 1954 | "requires": { 1955 | "p-locate": "^4.1.0" 1956 | } 1957 | }, 1958 | "mime-db": { 1959 | "version": "1.51.0", 1960 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", 1961 | "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" 1962 | }, 1963 | "mime-types": { 1964 | "version": "2.1.34", 1965 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", 1966 | "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", 1967 | "requires": { 1968 | "mime-db": "1.51.0" 1969 | } 1970 | }, 1971 | "minimatch": { 1972 | "version": "3.0.4", 1973 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1974 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1975 | "requires": { 1976 | "brace-expansion": "^1.1.7" 1977 | } 1978 | }, 1979 | "mkdirp-classic": { 1980 | "version": "0.5.3", 1981 | "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", 1982 | "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" 1983 | }, 1984 | "ms": { 1985 | "version": "2.1.2", 1986 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1987 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 1988 | }, 1989 | "node-fetch": { 1990 | "version": "2.6.5", 1991 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz", 1992 | "integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==", 1993 | "requires": { 1994 | "whatwg-url": "^5.0.0" 1995 | }, 1996 | "dependencies": { 1997 | "tr46": { 1998 | "version": "0.0.3", 1999 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 2000 | "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" 2001 | }, 2002 | "webidl-conversions": { 2003 | "version": "3.0.1", 2004 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 2005 | "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" 2006 | }, 2007 | "whatwg-url": { 2008 | "version": "5.0.0", 2009 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 2010 | "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", 2011 | "requires": { 2012 | "tr46": "~0.0.3", 2013 | "webidl-conversions": "^3.0.0" 2014 | } 2015 | } 2016 | } 2017 | }, 2018 | "nwsapi": { 2019 | "version": "2.2.0", 2020 | "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", 2021 | "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==" 2022 | }, 2023 | "once": { 2024 | "version": "1.4.0", 2025 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 2026 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 2027 | "requires": { 2028 | "wrappy": "1" 2029 | } 2030 | }, 2031 | "optionator": { 2032 | "version": "0.8.3", 2033 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", 2034 | "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", 2035 | "requires": { 2036 | "deep-is": "~0.1.3", 2037 | "fast-levenshtein": "~2.0.6", 2038 | "levn": "~0.3.0", 2039 | "prelude-ls": "~1.1.2", 2040 | "type-check": "~0.3.2", 2041 | "word-wrap": "~1.2.3" 2042 | } 2043 | }, 2044 | "p-limit": { 2045 | "version": "2.3.0", 2046 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 2047 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 2048 | "requires": { 2049 | "p-try": "^2.0.0" 2050 | } 2051 | }, 2052 | "p-locate": { 2053 | "version": "4.1.0", 2054 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 2055 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 2056 | "requires": { 2057 | "p-limit": "^2.2.0" 2058 | } 2059 | }, 2060 | "p-try": { 2061 | "version": "2.2.0", 2062 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 2063 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" 2064 | }, 2065 | "pako": { 2066 | "version": "1.0.11", 2067 | "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", 2068 | "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" 2069 | }, 2070 | "parse5": { 2071 | "version": "6.0.1", 2072 | "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", 2073 | "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" 2074 | }, 2075 | "path-exists": { 2076 | "version": "4.0.0", 2077 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 2078 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" 2079 | }, 2080 | "path-is-absolute": { 2081 | "version": "1.0.1", 2082 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 2083 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 2084 | }, 2085 | "pend": { 2086 | "version": "1.2.0", 2087 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 2088 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" 2089 | }, 2090 | "pkg-dir": { 2091 | "version": "4.2.0", 2092 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", 2093 | "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", 2094 | "requires": { 2095 | "find-up": "^4.0.0" 2096 | } 2097 | }, 2098 | "prelude-ls": { 2099 | "version": "1.1.2", 2100 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 2101 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" 2102 | }, 2103 | "process-nextick-args": { 2104 | "version": "2.0.1", 2105 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 2106 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 2107 | }, 2108 | "progress": { 2109 | "version": "2.0.3", 2110 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 2111 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" 2112 | }, 2113 | "proxy-from-env": { 2114 | "version": "1.1.0", 2115 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", 2116 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" 2117 | }, 2118 | "psl": { 2119 | "version": "1.8.0", 2120 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", 2121 | "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" 2122 | }, 2123 | "pump": { 2124 | "version": "3.0.0", 2125 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 2126 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 2127 | "requires": { 2128 | "end-of-stream": "^1.1.0", 2129 | "once": "^1.3.1" 2130 | } 2131 | }, 2132 | "punycode": { 2133 | "version": "2.1.1", 2134 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 2135 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" 2136 | }, 2137 | "puppeteer-core": { 2138 | "version": "11.0.0", 2139 | "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-11.0.0.tgz", 2140 | "integrity": "sha512-hfQ39KNP0qKplQ86iaCNXHH9zpWlV01UFdggt2qffgWeCBF9KMavwP/k/iK/JidPPWfOnKZhDLSHZVSUr73DtA==", 2141 | "requires": { 2142 | "debug": "4.3.2", 2143 | "devtools-protocol": "0.0.901419", 2144 | "extract-zip": "2.0.1", 2145 | "https-proxy-agent": "5.0.0", 2146 | "node-fetch": "2.6.5", 2147 | "pkg-dir": "4.2.0", 2148 | "progress": "2.0.3", 2149 | "proxy-from-env": "1.1.0", 2150 | "rimraf": "3.0.2", 2151 | "tar-fs": "2.1.1", 2152 | "unbzip2-stream": "1.4.3", 2153 | "ws": "8.2.3" 2154 | }, 2155 | "dependencies": { 2156 | "debug": { 2157 | "version": "4.3.2", 2158 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", 2159 | "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", 2160 | "requires": { 2161 | "ms": "2.1.2" 2162 | } 2163 | }, 2164 | "ws": { 2165 | "version": "8.2.3", 2166 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", 2167 | "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", 2168 | "requires": {} 2169 | } 2170 | } 2171 | }, 2172 | "readable-stream": { 2173 | "version": "2.3.7", 2174 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 2175 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 2176 | "requires": { 2177 | "core-util-is": "~1.0.0", 2178 | "inherits": "~2.0.3", 2179 | "isarray": "~1.0.0", 2180 | "process-nextick-args": "~2.0.0", 2181 | "safe-buffer": "~5.1.1", 2182 | "string_decoder": "~1.1.1", 2183 | "util-deprecate": "~1.0.1" 2184 | } 2185 | }, 2186 | "require-directory": { 2187 | "version": "2.1.1", 2188 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 2189 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" 2190 | }, 2191 | "rimraf": { 2192 | "version": "3.0.2", 2193 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 2194 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 2195 | "requires": { 2196 | "glob": "^7.1.3" 2197 | } 2198 | }, 2199 | "safe-buffer": { 2200 | "version": "5.1.2", 2201 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 2202 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 2203 | }, 2204 | "safer-buffer": { 2205 | "version": "2.1.2", 2206 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 2207 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 2208 | }, 2209 | "saxes": { 2210 | "version": "5.0.1", 2211 | "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", 2212 | "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", 2213 | "requires": { 2214 | "xmlchars": "^2.2.0" 2215 | } 2216 | }, 2217 | "selenium-webdriver": { 2218 | "version": "4.1.0", 2219 | "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.1.0.tgz", 2220 | "integrity": "sha512-kUDH4N8WruYprTzvug4Pl73Th+WKb5YiLz8z/anOpHyUNUdM3UzrdTOxmSNaf9AczzBeY+qXihzku8D1lMaKOg==", 2221 | "requires": { 2222 | "jszip": "^3.6.0", 2223 | "tmp": "^0.2.1", 2224 | "ws": ">=7.4.6" 2225 | } 2226 | }, 2227 | "set-immediate-shim": { 2228 | "version": "1.0.1", 2229 | "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", 2230 | "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" 2231 | }, 2232 | "single-file": { 2233 | "version": "git+ssh://git@github.com/gildas-lormeau/SingleFile.git#ce34d3f8c657acf808c5273b6b7e01413500763d", 2234 | "from": "single-file@git+https://github.com/gildas-lormeau/SingleFile.git", 2235 | "requires": { 2236 | "file-url": "^3.0.0", 2237 | "iconv-lite": "^0.6.3", 2238 | "jsdom": "^18.1.0", 2239 | "puppeteer-core": "^11.0.0", 2240 | "selenium-webdriver": "^4.0.0", 2241 | "strong-data-uri": "^1.0.6", 2242 | "yargs": "^17.2.1" 2243 | } 2244 | }, 2245 | "source-map": { 2246 | "version": "0.6.1", 2247 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 2248 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 2249 | "optional": true 2250 | }, 2251 | "string_decoder": { 2252 | "version": "1.1.1", 2253 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 2254 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 2255 | "requires": { 2256 | "safe-buffer": "~5.1.0" 2257 | } 2258 | }, 2259 | "string-width": { 2260 | "version": "4.2.3", 2261 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 2262 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 2263 | "requires": { 2264 | "emoji-regex": "^8.0.0", 2265 | "is-fullwidth-code-point": "^3.0.0", 2266 | "strip-ansi": "^6.0.1" 2267 | } 2268 | }, 2269 | "strip-ansi": { 2270 | "version": "6.0.1", 2271 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2272 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2273 | "requires": { 2274 | "ansi-regex": "^5.0.1" 2275 | } 2276 | }, 2277 | "strong-data-uri": { 2278 | "version": "1.0.6", 2279 | "resolved": "https://registry.npmjs.org/strong-data-uri/-/strong-data-uri-1.0.6.tgz", 2280 | "integrity": "sha512-zhzBZev0uhT2IrFUerenXhfaE0vFUYwAZsnG0gIKGpfM/Gi6jOUQ3cmcvyTsXeDLIPiTubHESeO7EbD6FoPmzw==", 2281 | "requires": { 2282 | "truncate": "^2.0.1" 2283 | } 2284 | }, 2285 | "symbol-tree": { 2286 | "version": "3.2.4", 2287 | "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", 2288 | "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" 2289 | }, 2290 | "tar-fs": { 2291 | "version": "2.1.1", 2292 | "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", 2293 | "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", 2294 | "requires": { 2295 | "chownr": "^1.1.1", 2296 | "mkdirp-classic": "^0.5.2", 2297 | "pump": "^3.0.0", 2298 | "tar-stream": "^2.1.4" 2299 | } 2300 | }, 2301 | "tar-stream": { 2302 | "version": "2.2.0", 2303 | "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", 2304 | "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", 2305 | "requires": { 2306 | "bl": "^4.0.3", 2307 | "end-of-stream": "^1.4.1", 2308 | "fs-constants": "^1.0.0", 2309 | "inherits": "^2.0.3", 2310 | "readable-stream": "^3.1.1" 2311 | }, 2312 | "dependencies": { 2313 | "readable-stream": { 2314 | "version": "3.6.0", 2315 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 2316 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 2317 | "requires": { 2318 | "inherits": "^2.0.3", 2319 | "string_decoder": "^1.1.1", 2320 | "util-deprecate": "^1.0.1" 2321 | } 2322 | } 2323 | } 2324 | }, 2325 | "through": { 2326 | "version": "2.3.8", 2327 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 2328 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 2329 | }, 2330 | "tmp": { 2331 | "version": "0.2.1", 2332 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", 2333 | "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", 2334 | "requires": { 2335 | "rimraf": "^3.0.0" 2336 | } 2337 | }, 2338 | "tough-cookie": { 2339 | "version": "4.0.0", 2340 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", 2341 | "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", 2342 | "requires": { 2343 | "psl": "^1.1.33", 2344 | "punycode": "^2.1.1", 2345 | "universalify": "^0.1.2" 2346 | } 2347 | }, 2348 | "tr46": { 2349 | "version": "3.0.0", 2350 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", 2351 | "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", 2352 | "requires": { 2353 | "punycode": "^2.1.1" 2354 | } 2355 | }, 2356 | "truncate": { 2357 | "version": "2.1.0", 2358 | "resolved": "https://registry.npmjs.org/truncate/-/truncate-2.1.0.tgz", 2359 | "integrity": "sha512-em3E3SUDONOjTBcZ36DTm3RvDded3IRU9rX32oHwwXNt3rJD5MVaFlJTQvs8tJoHRoeYP36OuQ1eL/Q7bNEWIQ==" 2360 | }, 2361 | "type-check": { 2362 | "version": "0.3.2", 2363 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 2364 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 2365 | "requires": { 2366 | "prelude-ls": "~1.1.2" 2367 | } 2368 | }, 2369 | "unbzip2-stream": { 2370 | "version": "1.4.3", 2371 | "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", 2372 | "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", 2373 | "requires": { 2374 | "buffer": "^5.2.1", 2375 | "through": "^2.3.8" 2376 | } 2377 | }, 2378 | "universalify": { 2379 | "version": "0.1.2", 2380 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 2381 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" 2382 | }, 2383 | "util-deprecate": { 2384 | "version": "1.0.2", 2385 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2386 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 2387 | }, 2388 | "w3c-hr-time": { 2389 | "version": "1.0.2", 2390 | "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", 2391 | "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", 2392 | "requires": { 2393 | "browser-process-hrtime": "^1.0.0" 2394 | } 2395 | }, 2396 | "w3c-xmlserializer": { 2397 | "version": "3.0.0", 2398 | "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", 2399 | "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", 2400 | "requires": { 2401 | "xml-name-validator": "^4.0.0" 2402 | } 2403 | }, 2404 | "webidl-conversions": { 2405 | "version": "7.0.0", 2406 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", 2407 | "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" 2408 | }, 2409 | "whatwg-encoding": { 2410 | "version": "2.0.0", 2411 | "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", 2412 | "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", 2413 | "requires": { 2414 | "iconv-lite": "0.6.3" 2415 | } 2416 | }, 2417 | "whatwg-mimetype": { 2418 | "version": "3.0.0", 2419 | "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", 2420 | "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==" 2421 | }, 2422 | "whatwg-url": { 2423 | "version": "10.0.0", 2424 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-10.0.0.tgz", 2425 | "integrity": "sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w==", 2426 | "requires": { 2427 | "tr46": "^3.0.0", 2428 | "webidl-conversions": "^7.0.0" 2429 | } 2430 | }, 2431 | "word-wrap": { 2432 | "version": "1.2.3", 2433 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 2434 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" 2435 | }, 2436 | "wrap-ansi": { 2437 | "version": "7.0.0", 2438 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 2439 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 2440 | "requires": { 2441 | "ansi-styles": "^4.0.0", 2442 | "string-width": "^4.1.0", 2443 | "strip-ansi": "^6.0.0" 2444 | } 2445 | }, 2446 | "wrappy": { 2447 | "version": "1.0.2", 2448 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2449 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 2450 | }, 2451 | "ws": { 2452 | "version": "8.3.0", 2453 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.3.0.tgz", 2454 | "integrity": "sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw==", 2455 | "requires": {} 2456 | }, 2457 | "xml-name-validator": { 2458 | "version": "4.0.0", 2459 | "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", 2460 | "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==" 2461 | }, 2462 | "xmlchars": { 2463 | "version": "2.2.0", 2464 | "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", 2465 | "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" 2466 | }, 2467 | "y18n": { 2468 | "version": "5.0.8", 2469 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 2470 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" 2471 | }, 2472 | "yargs": { 2473 | "version": "17.3.0", 2474 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.0.tgz", 2475 | "integrity": "sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew==", 2476 | "requires": { 2477 | "cliui": "^7.0.2", 2478 | "escalade": "^3.1.1", 2479 | "get-caller-file": "^2.0.5", 2480 | "require-directory": "^2.1.1", 2481 | "string-width": "^4.2.3", 2482 | "y18n": "^5.0.5", 2483 | "yargs-parser": "^21.0.0" 2484 | } 2485 | }, 2486 | "yargs-parser": { 2487 | "version": "21.0.0", 2488 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", 2489 | "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==" 2490 | }, 2491 | "yauzl": { 2492 | "version": "2.10.0", 2493 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", 2494 | "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", 2495 | "requires": { 2496 | "buffer-crc32": "~0.2.3", 2497 | "fd-slicer": "~1.1.0" 2498 | } 2499 | } 2500 | } 2501 | } 2502 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "single-file-cli": "github:gildas-lormeau/single-file-cli" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | jsonpickle 3 | canvasapi 4 | python-dateutil 5 | PyYAML 6 | -------------------------------------------------------------------------------- /singlefile.py: -------------------------------------------------------------------------------- 1 | from subprocess import run 2 | 3 | SINGLEFILE_BINARY_PATH = "./node_modules/single-file-cli/single-file" 4 | CHROME_PATH = "C:/Program Files/Google\ Chrome/Application/chrome.exe" #Uncomment this and set your browser exe if it can't find yours. 5 | 6 | def addQuotes(str): 7 | return "\"" + str.strip("\"") + "\"" 8 | 9 | def download_page(url, cookies_path, output_path, output_name_template = ""): 10 | args = [ 11 | addQuotes(SINGLEFILE_BINARY_PATH), 12 | #"--browser-executable-path=" + addQuotes(CHROME_PATH.strip("\"")), #Uncomment this and set your browser exe if it can't find yours. 13 | "--browser-cookies-file=" + addQuotes(cookies_path), 14 | "--output-directory=" + addQuotes(output_path), 15 | addQuotes(url) 16 | ] 17 | 18 | if(output_name_template != ""): 19 | args.append("--filename-template=" + addQuotes(output_name_template)) 20 | 21 | try: 22 | run(" ".join(args), shell=True) 23 | except Exception as e: 24 | print("Was not able to save the URL " + url + " using singlefile. The reported error was " + e.strerror) 25 | 26 | #if __name__ == "__main__": 27 | #download_page("https://www.google.com/", "", "./output/test", "test.html") 28 | --------------------------------------------------------------------------------