diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..f2f6d9b --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,7 @@ +# See here for image contents: https://github.com/microsoft/vscode-dev-containers/blob/v0.241.1/containers/debian/.devcontainer/base.Dockerfile + +# [Choice] Debian version (use bullseye on local arm64/Apple Silicon): bullseye, buster +ARG VARIANT=bullseye +FROM mcr.microsoft.com/vscode/devcontainers/base:${VARIANT} +COPY ./install_tools.sh /tmp/install_tools.sh +RUN /tmp/install_tools.sh diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..f5b5287 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,36 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: +// https://github.com/microsoft/vscode-dev-containers/blob/v0.241.1/containers/debian +{ + "name": "Debian", + "build": { + "dockerfile": "Dockerfile", + // Update 'VARIANT' to pick an Debian version: bullseye, buster + // Use bullseye on local arm64/Apple Silicon. + "args": { + "VARIANT": "bullseye" + } + }, + "runArgs": [ + // The primary reason this is here is to enable loopback devices, + // which are used for mounting disk images during builds, etc. + "--privileged" + ], + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + // + // Uncomment to use the Docker CLI from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker. + // "mounts": [ "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" ], + "features": { + "sshd": "latest" + }, + "extensions": [ + "ms-azuretools.vscode-docker", + "dbaeumer.vscode-eslint", + "eamodio.gitlens", + "ms-vscode.makefile-tools", + "ms-python.python", + "svelte.svelte-vscode", + "redhat.vscode-yaml", + "ryu1kn.partial-diff" + ] +} \ No newline at end of file diff --git a/.devcontainer/install_tools.sh b/.devcontainer/install_tools.sh new file mode 100755 index 0000000..8ffc901 --- /dev/null +++ b/.devcontainer/install_tools.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env -S bash -e + +APT_PACKAGES=( + "build-essential" + "git" + "wget" + "binfmt-support" + "qemu" + "gcc-9" + "parted" + "udev" + "zerofree" + "gcc-avr" + "avr-libc" + "avrdude" + "python3" + "python3-pip" + "python3-tornado" + "inetutils-ping" + "curl" + "unzip" + "python3-setuptools" + "gcc-arm-linux-gnueabihf" + "bc" + "vim" + "locate" + "sudo" + "sshpass" +) + +apt-get update +apt-get upgrade -y + +apt-get install -y "${APT_PACKAGES[@]}" + +update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 9 + +/usr/bin/python3 -m pip install -U yapf + +curl -fsSL https://deb.nodesource.com/setup_18.x | bash - +apt-get install -y nodejs + +mkdir -p /root/.ssh +cat > /root/.ssh/config <<- END +Host onefinity + User bbmc +END diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 0000000..5f4153c --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,107 @@ +env: + es2021: true + node: true + browser: true +extends: + - eslint:recommended + - plugin:@typescript-eslint/recommended +overrides: [] +parser: "@typescript-eslint/parser" +parserOptions: + ecmaVersion: latest + sourceType: module + tsconfigRootDir: ./src/svelte-components +plugins: + - "@typescript-eslint" +globals: + Vue: readonly + THREE: readonly + SvelteComponents: readonly + Clusterize: readonly + SockJS: readonly +ignorePatterns: + - /src/svelte-components/dist + - /src/static + - /build + - /dist + - /rpi-share + - /src/py/bbctrl/http +rules: + indent: + - off + "@typescript-eslint/indent": + - error + - 4 + linebreak-style: + - error + - unix + quotes: + - error + - double + - allowTemplateLiterals: true + avoidEscape: true + semi: + - error + - always + "@typescript-eslint/no-explicit-any": + - off + "@typescript-eslint/no-unused-vars": + - error + - argsIgnorePattern: _.* + no-unused-vars: + - error + - argsIgnorePattern: _.* + no-trailing-spaces: + - error + key-spacing: + - error + space-before-blocks: + - error + block-spacing: + - error + brace-style: + - error + curly: + - error + keyword-spacing: + - error + no-multi-spaces: + - error + "@typescript-eslint/no-var-requires": + - off + no-multiple-empty-lines: + - error + - max: 1 + func-call-spacing: + - error + - never + padding-line-between-statements: + - error + - blankLine: always + prev: function + next: function + no-var: + - error + no-unused-expressions: + - error + prefer-const: + - error + prefer-template: + - error + object-curly-spacing: + - error + - always + array-bracket-spacing: + - error + - always + template-curly-spacing: + - error + require-await: + - error + space-infix-ops: + - error + space-before-function-paren: + - error + - anonymous: never + named: never + asyncArrow: always diff --git a/.gitignore b/.gitignore index 81f1565..45e4586 100644 --- a/.gitignore +++ b/.gitignore @@ -1,27 +1,26 @@ +.DS_Store .sconf_temp/ .sconsign.dblite -/build -/dist -/crap -/pkg -/mnt -/demo -/bbctrl-* -node_modules -*~ -\#* -*.pyc -__pycache__ -*.egg-info -/upload -/*.img -*.so *.deb -*.zip -/rpi-share -/rpi-root -/src/bbserial/linux-rpi-raspberrypi-kernel* -/src/bbserial/raspberrypi-kernel* -.vscode +*.egg-info *.elf *.hex +*.img +*.img.bz2 +*.img.gzip +*.img.xz +*.pyc +*.so +*.tmp +*.zip +**/__pycache__ +*~ +\#* +build +dist +node_modules +null.d +rpi-root +rpi-share +src/bbserial/linux-rpi-raspberrypi-kernel* +src/bbserial/raspberrypi-kernel* diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..427acba --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,31 @@ +{ + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/Thumbs.db": true, + "**/node_modules": true, + "**/build": true, + "**/dist": true, + "**/rpi-share": true, + "**/rpi-root": true + }, + "search.exclude": { + "**/bower_components": true, + "**/*.code-search": true, + "**/node_modules": true, + "**/build": true, + "**/dist": true, + "**/rpi-share": true, + "**/rpi-root": true + }, + "explorer.excludeGitIgnore": true, + "git.ignoredRepositories": [ + "rpi-share/camotics", + "rpi-share/cbang" + ], + "git.autofetch": false, + "git.confirmSync": false +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index abfef30..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,466 +0,0 @@ -OneFinity CNC Controller Firmware Changelog -=========================================== - -## v1.0.8 - - Fixed chatter and lost steps issues (most commonly seen by Fusion users), re-enabled support for G61, G61.1, G64. - - Fixed 3d preview on Safari-based web browsers (MacOS & iOS) - - Made it less likely for a user to upload a non-gcode file - - Fixed problems with UI freezing when attempting to process a non-gcode file - - Simplified error popup to make it less confusing - - Improved error messages for most internal errors - -## v1.0.7 - - Cleaned up UI layout a bit on the main screen - - Enabled auto expansion of partition and file system to fill SD card on first boot - - Added probe continuity test before probing (pop-up dialog) - - Added a popup after probing, reminding the user to put away the probe - - Lowered default probe seek speed - - Fixed file drop-down menu showing old files - - Added file system watcher for uploaded files - - Improved support for large gcode files, improves performance on Raspi - - Fixed a bug where the UI could become unresponsive at boot, or when uploading the first gcode file - - Changed default max-deviation to 0.001 to reduce issues with chattering while cutting arcs and circles - - Hides ratpoison (window manager) message during boot up - - Disabled G61, G61.1, G64 gcodes until the root cause of circle chatter is identified and fixed - - Increased icon size on the main GUI - - Improved version comparison logic for handling public beta releases in the future - - Changed default max-jerk to 1000 for X/Y axes - - Changed default idle current to 1A - - Force-set some critical configuration values to help with reliability - - Metric units only for junction-accel and max-deviation - - Rewrote the homing procedure to be more consistent - - Small improvements to the stall homing procedure - - Fixed error messages in the console (webgl) - - Fixed styling bug with error dialog - - Added a setting to allow enable/disable of probing safety prompts - -## v1.0.6 - - Tweaked stall homing procedure to clear stepper stall condition before homing - - Modified motor homing parameters (8 microsteps, 1.688 m/min search velocity, 2 stall volts, 1 stall current, 1.5mm zero backoff) - - Added pop up message while loading/simulating file on upload - - Decreased max velocity in default settings for X and Y axes - - Restored jerk to 1000 on all axes - - Fixed issue with default units not displaying on Control page (thanks to Robin Goldstone) - -## v1.0.5 - - Changed the jog commands so that save/restore modal states are not used to avoid situation where spindle/loads could - turn back on if the stop button was used instead of the M5/M9 gcode commands. - - Added tool path status to control page - - Moved over/under/no-fit warnings to tool status from machine status - - Added "home machine" pop up on start if the machine is not homed - - Added confirmation for X0Y0 and Z0 buttons - -## v1.0.4 - - Fixed text sticking out of some dialog boxes - - Added changes to PWR microcontroller to support new precharge circuitry on V3 of the PCB - - Added a Shutdown button under the menu - - Added confirmation dialog to shutdown - - Fixed Reset Defaults for OneFinity settings - - Probe buttons now turn green when probe input is active - - Added defaults for both machinist and woodworker machines - - Re-activated "Upgrade" button under Admin to grab updates directly from the web - -## v1.0.3 - - Changed upgrade scripts to point at OneFinity github repository - - Upgrade function not yet fully implemented - -## v1.0.2 - - Initial release of customized OneFinity firmware - - Includes GUI customizations, stall homing - -Note: This firmware was forked from version 0.4.14 of the Buildbotics firmware - -Buildbotics CNC Controller Firmware Changelog -============================================= - -## v0.4.14 - - Handle file uploads with '#' or '?' in the name. - - Added "step mode" to Web based jogging. - - Fixed touch screen Web jogging. - -## v0.4.13 - - Support for OMRON MX2 VFD. - - Better error handling in WiFi configuration. - - Fix open WiFi access. - - Improved video camera performance. - - Allow up to 4 camera clients at once. - - Add axis bounds GCode variables ``#<_x_min>``, ``#<_x_max>``, etc. - - Expose ``junction-accel`` planning parameter. - - Fixed problem with manual firmware upload on OSX. - - Ignore cameras that do not support MJPEG format video. - -## v0.4.12 - - Segments straddle arc in linearization. - - Control max-arc-error with GCode var. - - Implemented path modes G61, G61.1 & G64 with naive CAM and basic blending. - - Log GCode messages to "Messages" tab. - - Acknowledging a message on one browser clears it for all. - - Automatically reload Web view when file changes. - - Added ``config-screen`` script. Web based screen config to come later. - - Suppress message popup with (MSG,# No popup message). - - Show latest GCode message in ``Message`` field on CONTROL page. - - Marked several GCodes supported in cheat sheet. - - Solved planner lookahead failure for most reasonable cases. - - Prevent cutting off distant parts of 3D path view. - - Raised default ``latch-backoff`` to 100mm and ``zero-backoff`` to 5mm. - - Added ``max-deviation`` option. - - Fixed problem with GCode boolean expression parsing. #232. - - Ensure 2uS step pulse width. - -## v0.4.11 - - Don't reset global offsets on M2. - - Test shunt and show error on failure. - - Report spindle status codes from Modbus. - - Save more log files in bug report. - - Fixed indicators low-side units. - - Support for YL600, YL620 & YL620-A VFDs. - - Move Modbus indicators to tool page. - - Support for Sunfar E300 VFD. - - Set GCODE_SCRIPT_PATH to support GCode file routines. - - Fix pause bug introduced in v0.4.10. - -## v0.4.10 - - Fix demo password check - - Fix bug were fast clicks could cause jog commands to arrive out of order. - - Fix bug where planner position may not sync after jog. - - Show power shutdown on indicators page. - - Show all motors in shutdown when in power shutdown. - - Improved GCode error messages. - - Put controller into estop when in power shutdown. - -## v0.4.9 - - Enforce 6A per motor channel peak current limit. - - Adjust config values above max or below min instead of resetting to default. - -## v0.4.8 - - Fixed log rotating. - - Use systemd service instead of init.d. - - Fix planner terminate. - - Changed AVR serial interrupt priorites. - - Increased AVR serial and command buffers. - - Boost HDMI signal. - - Rewrote RPi serial driver. - - Automatically scale max CPU speed to reduce RPi temp. - - Disable USB camera if RPi temperature above 80°C, back on at 75°C. - - Respect offsets in canned cycle moves. #219 - - Fixed G53 warning. - - Fixed delayed offset update after M2 or M30 end of program. - - Handle multiple consecutive config resets correctly. - - Fixed log CPU usage problem introduced in v0.4.6. - - Show RPi temp on indicators page. - - Show red thermometer if RPi temp exceeds 80°C. - -## v0.4.7 - - Fix homing switch to motor channel mapping with non-standard axis order. - - Added ``switch-debounce`` and ``switch-lockout`` config options. - - Handle corrupt GCode simulation data correctly. - - Fixes for exception logging. - - Always limit motor max-velocity. #209 - - Sync GCode and planner files to disk after write. - - Added warning about reliability in a noisy environment on WiFi config page. - - EStop on motor fault. - - Fixed ETA line wrapping on Web interface. - - Fixed zeroing with non-zero offset when unhomed. #211 - - Handle file paths uploaded from Windows correctly. #212 - - Don't retain estop state through reboot. - - Log when RPi gets hot. - - Support Modbus multi-write mode. - - Added support for Nowforever VFDs. - -## v0.4.6 - - Fixed a rare ``Negative s-curve time`` error. - - Don't allow manual axis homing when soft limits are not set. - - Right click to enable camera crosshair. - - Demo mode. - - Limit idle-current to 2A. - - Removed dangerous ``power-mode`` in favor of simpler ``enabled`` option. - - Fixed bug where motor driver could fail to disabled during estop. - - Restored estop text. - -## v0.4.5 - - Fix for random errors while running VFD. - - Fix bug where planner would not continue after optional pause (M1). - - Fix lockup on invalid no move probe G38.x. #183 - - Fix zeroing homed axis after jog. - - Fix VFD communication at higher baud rates (> 9600). #184 - -## v0.4.4 - - Write version to log file. - - Write time to log file periodically. - - Show simulation progress with or with out 3D view. - - Synchronize file list between browsers. - - Increased max simulation time to 24hrs. - - Added button to download current GCode file. - - Blink play button to indicate pause. - - Many layout tweaks/improvements. - - Don't abort simulations when system time changes. - - Only allow one camera stream at a time. - -## v0.4.2 - - Suppress ``Auto-creating missing tool`` warning. - - Prevent ``Stream is closed`` error. - - Suppress ``WebGL not supported`` warning. - - Fixed Web disconnect during simulation of large GCode. - - Disable outputs on estop. - - Improved switch debouncing for better homing. - - Handle zero length dwell correctly. - - Fixed problem with cached GCode file upload when file changed on disk. - - Run simulation at low process priority. - - Added ``Bug Report`` button to ``Admin`` -> ``General``. - - Only render 3D view as needed to save CPU. - - Prevent lockup due to browser causing out of memory condition. - - Show error message when too large GCode upload fails. - - Much faster 3D view loading. - -## v0.4.1 - - Fix toolpath view axes bug. - - Added LASER intensity view. - - Fixed reverse path planner bug. - - Video size and path view controls persistent over browser reload. - - Fixed time and progress bugs. - - Added PWM rapid auto off feature for LASER/Plasma. - - Added dynamic PWM for LASER/Plasma. - - Added motor faults table to indicators page. - - Emit error and indicate FAULT on axis for motor driver faults. - - Display axis motor FAULT on LCD. - - Fixed bug with rapid repeated unpause. - -## v0.4.0 - - Increased display precision of position and motor config. - - Added support for 256 microstepping. - - Smoother operation at 250k step rate by doubling clock as needed. - - Indicators tab improvements. - - Much improved camera support. - - Camera hotpluging. - - Move camera video to header. - - Click to switch video size. - - Automount/unmount USB drives. - - Automatically install ``buildbotics.gc`` when no other GCode exists. - - Preplan GCode and check for errors. - - Display 3D view of program tool paths in browser. - - Display accurate time remaining, ETA and progress during run. - - Automatically collapse moves in planner which are too short in time. - - Show IO status indicators on configuration pages. - - Check that axis dimensions fit path plan dimensions. - - Show machine working envelope in path plan viewer. - - Don't reload browser view on reconnect unless controller has reloaded. - - Increased max switch backoff search distance. - - Major improvements for LASER raster GCodes. - - Fixed major bug in command queuing. - - Ignore Program Number O-Codes. - - Improved planning of collinear line segments. - - Allow PWM output up to 320kHz and no slower than 8Hz. - -## v0.3.28 - - Show step rate on motor configuration page. - - Limit motor max-velocity such that step rate cannot exceed 250k. - - Fixed deceleration bug at full 250k step rate. - -## v0.3.27 - - Fixed homing in imperial mode. - -## v0.3.26 - - Removed VFD test. - - Show VFD status on configuration page. - - Show VFD commands fail counts. - - Marked some VFD types as beta. - -## v0.3.25 - - Error on home if max-soft-limit <= min-soft-limit + 1. #139 - - Decrease boot time networking delay. - - Default to US keyboard layout. #145 - - Added configuration option to show metric or imperial units in browser. #74 - - Implemented fine jogging control in Web interface. #147 - -## v0.3.24 - - Added unhome button on axis position popup. - - Ignore soft limits of max <= min. - - Fixed problem with restarting program in imperial units mode. - - Handle GCode with infinite or very long loops correctly. - - Fixed Huanyang spindle restart after stop. - -## v0.3.23 - - Fix for modbus read operation. - - Finalized AC-Tech VFD support. - - Preliminary FR-D700 VFD support. - - Ignore leading zeros in modbus messages. - - Handle older PWR firmwares. - -## v0.3.22 - - Fix position loss after program pause. #130 - - Correctly handle disabled axes. - - Fixed config checkbox not displaying defaulted enabled correctly. - - Added Custom Modbus VFD programming. - -## v0.3.21 - - Implemented M70-M73 modal state save/restore. - - Added support for modbus VFDs. - - Start Huanyang spindle with out first pressing Start button on VFD. - - Faster switching of large GCode files in Web. - - Fixed reported gcode line off by one. - - Disable MDI input while running. - - Stabilized direction pin output during slow moves. - -## v0.3.20 - - Eliminated drift caused by miscounting half microsteps. - - Fixed disappearing GCode in Web. - - More efficient GCode scrolling with very large files. - - Fully functional soft-limited jogging. - - Added client and access-point Wifi configuration. - - Fixed broken hostname Web redirect after change. - - Split admin page -> General & Network. - - Improved calculation of junction velocity limits. - -## v0.3.19 - - Fixed stopping problems. #127 - - Fixed ``Negative s-curve time`` error. - - Improved jogging with soft limits. - - Added site favicon. - - Fixed problems with offsets and imperial units. - - Fixed ``All zero s-curve times`` caused by extremely short, non-zero moves. - - Fixed position drift. - -## v0.3.18 - - Don't enable any tool by default. - -## v0.3.17 - - Fixed pausing fail near end of run bug. - - Show "Upgrading firmware" when upgrading. - - Log excessive pwr communication failures as errors. - - Ensure we can still get out of non-idle cycles when there are errors. - - Less frequent pwr variable updates. - - Stop cancels seek and subsequent estop. - - Fixed bug in AVR/Planner command synchronization. - - Consistently display HOMING state during homing operation. - - Homing zeros axis global offset. - - Added zero all button. #126 - - Separate "Auto" and "MDI" play/pause & stop buttons. #126 - - Moved home all button. #126 - - Display "Video camera not found." instead of broken image icon. - - Show offset positions not absolute on LCD. - - Don't change gcode lines while homing. - - Don't change button states while homing. - - Adding warning about power cyclying during an upgrade. - - Reset planner on AVR errors. - - Fixed pausing with short moves. - - Corrected s-curve accel increasing jogging velocities. - -## v0.3.16 - - Fixed switch debounce bug. - -## v0.3.15 - - Suppress warning missing config.json warning after config reset. - - Fixed EStop reboot loop. - - Removed AVR unexpected reboot error. - -## v0.3.14 - - Fixed: Config fails silently after web disconnect #112 - - Always reload the page after a disconnect. - - Honor soft limits #111 (but not when jogging) - - Limit switch going active while moving causes estop. #54 - - Added more links to help page. - - Fixed axis display on LCD. #122 - - Added GCode cheat sheet. - - Fixed LCD boot splash screen. #121 - - Implemented tool change procedures and pause message box. #81 - - Implemented program start and end procedures. - -## v0.3.13 - - Disable spindle and loads on stop. - - Fixed several state transition (stop, pause, estop, etc.) problems. - -## v0.3.12 - - Updated DB25 M2 breakout diagram. - - Enabled AVR watchdog. - - Fixed problem with selecting newly uploaded file. - - More thorough shutdown of stepper driver in estop. - - Fixed spindle type specific options. - - No more ``Unexpected AVR firmware reboot`` errors on estop clear. - - Downgraded ``Machine alarmed - Command not processed`` errors to warnings. - - Suppress unnecessary axis homing warnings. - - More details for axis homing errors. - - Support GCode messages e.g. (MSG, Hello World!) - - Support programmed pauses. i.e. M0 - -## v0.3.11 - - Suppressed ``firmware rebooted`` warning. - - Error on unexpected AVR reboot. - - Fixed pin fault output. - - No longer using interrupts for switch inputs. Debouncing on clock tick. - -## v0.3.10 - - Fixed "Flood" display, changed to "Load 1" and "Load 2". #108 - - Highlight loads when on. - - Fixed axis zeroing. - - Fixed bug in home position set after successful home. #109 - - Fixed ugly Web error dumps. - - Allow access to log file from Web. - - Rotate log so it does not grow too big. - - Keep same GCode file through browser reload. #20 - -## v0.3.9 - - Fixed bug in move exec that was causing bumping between moves. - - Fixed planner bug which could create negative s-curve times. - - Hide step and optional pause buttons until they are implemented. - - Fixed pausing problems. - - Limit number of console messages. - - Scrollbar on console view. - - Log debug messages to console in developer mode. - - Fixed AVR log message source. - - Fixed step correction. - - JOGGING, HOMMING and MDI states. - - Fixed position problem with rapid MDI entry. - -## v0.3.8 - - Fixed pwr flags display - - Added pwr fault flags to indicators - -## v0.3.7 - - Allow blocking error dialog for a period of time - - Show actual error message on planner errors - - Reset planner on serious error - - Fixed console clear - - Added helpful info to Video tab - - Changed "Console" tab to "Messages" - - Removed spin up/down velocity options, they don't do anything - - Allow RS485 to work when wires are swapped - - Allow setting VFD ID - - Only show relevant spindle config items - - More robust video camera reset - - Added help page - - Allow upgrade with out Internet - - Limit power fault reporting - - Added load over temp, load limiting and motor overload power faults - -## v0.3.6 - - Set max_usb_current=1 in /boot/config.txt from installer #103 - -## v0.3.5 - - Fixed dwell (G4) - - Always show limit switch indicators regardless of motor enable - - Fixed feed rate display - - Added current GCode unit display - - Fixed homed axis zeroing - - Fixed probe pin input - - Added reload button to video tab - - Don't open error dialog on repeat messages - - Handle large GCode files in browser - - Added max lookahead limit to planner - - Fixed GCode stopping/pausing where ramp down needs more than is in the queue - - Added breakout box diagram to indicators - - Initialize axes offsets to zero on startup - - Fixed conflict between ``x`` state variable and ``x`` axis variable - - Don't show ipv6 addresses on LCD. They don't fit. - -## v0.3.4 - - Added alternate units for motor parameters - - Automatic config file upgrading - - Fixed planner/jog sync - - Fixed planner limits config - - Accel units mm/min² -> m/min² - - Search and latch velocity mm/min -> m/min - - Fixed password update (broken in last version) - - Start Web server earlier in case of Python coding errors - - -Changelog not maintained in previous versions. See git commit log. diff --git a/CODE_TAG b/CODE_TAG deleted file mode 100644 index d36ffb0..0000000 --- a/CODE_TAG +++ /dev/null @@ -1,22 +0,0 @@ - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" diff --git a/MANIFEST.in b/MANIFEST.in index a1204ab..ad16711 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,6 @@ include package.json README.md requirements.txt -graft scripts -graft python-packages +graft installer +include scripts/install.sh graft src/py/bbctrl/http graft src/py/camotics include src/avr/bbctrl-avr-firmware.hex diff --git a/Makefile b/Makefile index a6a6548..ebc317f 100644 --- a/Makefile +++ b/Makefile @@ -22,12 +22,8 @@ RSYNC_OPTS := $(RSYNC_EXCLUDE) -rv --no-g --delete --force VERSION := $(shell sed -n 's/^.*"version": "\([^"]*\)",.*$$/\1/p' package.json) PKG_NAME := bbctrl-$(VERSION) -PUB_PATH := root@buildbotics.com:/var/www/buildbotics.com/bbctrl -BETA_VERSION := $(VERSION)-rc$(shell ./scripts/next-rc) -BETA_PKG_NAME := bbctrl-$(BETA_VERSION) SUBPROJECTS := avr boot pwr jig -WATCH := src/pug src/pug/templates src/stylus src/js src/resources src/svelte-components src/static Makefile ifndef HOST HOST=onefinity @@ -37,16 +33,12 @@ ifndef PASSWORD PASSWORD=onefinity endif - all: $(HTML) $(RESOURCES) @for SUB in $(SUBPROJECTS); do $(MAKE) -C src/$$SUB; done pkg: all $(AVR_FIRMWARE) bbserial ./setup.py sdist -beta-pkg: pkg - cp dist/$(PKG_NAME).tar.bz2 dist/$(BETA_PKG_NAME).tar.bz2 - bbserial: $(MAKE) -C src/bbserial @@ -57,12 +49,6 @@ $(GPLAN_TARGET): $(GPLAN_MOD) $(GPLAN_MOD): $(GPLAN_IMG) ./scripts/gplan-init-build.sh - git -C rpi-share/cbang fetch - git -C rpi-share/cbang reset --hard FETCH_HEAD - git -C rpi-share/cbang checkout 18f1e963107ef26abe750c023355a5c40dd07853 - git -C rpi-share/camotics fetch - git -C rpi-share/camotics reset --hard FETCH_HEAD - git -C rpi-share/camotics checkout ec876c80d20fc19837133087cef0c447df5a939d cp ./scripts/gplan-build.sh rpi-share/ chmod +x rpi-share/gplan-build.sh sudo ./scripts/rpi-chroot.sh $(GPLAN_IMG) /mnt/host/gplan-build.sh @@ -74,15 +60,6 @@ $(GPLAN_IMG): $(AVR_FIRMWARE): $(MAKE) -C src/avr -publish: pkg - echo -n $(VERSION) > dist/latest.txt - rsync $(RSYNC_OPTS) dist/$(PKG_NAME).tar.bz2 dist/latest.txt $(PUB_PATH)/ - -publish-beta: beta-pkg - echo -n $(BETA_VERSION) > dist/latest-beta.txt - rsync $(RSYNC_OPTS) dist/$(BETA_PKG_NAME).tar.bz2 dist/latest-beta.txt \ - $(PUB_PATH)/ - update: pkg http_proxy= curl -i -X PUT -H "Content-Type: multipart/form-data" \ -F "firmware=@dist/$(PKG_NAME).tar.bz2" -F "password=$(PASSWORD)" \ @@ -122,34 +99,8 @@ $(TARGET_DIR)/%.html: src/pug/%.pug node_modules FORCE @mkdir -p $(TARGET_DIR) $(PUG) -O pug-opts.js -P $< -o $(TARGET_DIR) || (rm -f $@; exit 1) -pylint: - pylint3 -E $(shell find src/py -name \*.py | grep -v flycheck_) - -jshint: - ./node_modules/jshint/bin/jshint --config jshint.json src/js/*.js - -lint: pylint jshint - -watch: - @clear - $(MAKE) - @while sleep 1; do \ - inotifywait -qr -e modify -e create -e delete \ - --exclude .*~ --exclude \#.* $(WATCH); \ - clear; \ - $(MAKE); \ - done - -tidy: - rm -f $(shell find "$(DIR)" -name \*~) - -clean: tidy - rm -rf build html dist - @for SUB in $(SUBPROJECTS); do \ - $(MAKE) -C src/$$SUB clean; \ - done - -dist-clean: clean - rm -rf node_modules +clean: + rm -rf rpi-share + git clean -fxd .PHONY: all install clean tidy pkg gplan lint pylint jshint bbserial diff --git a/docs/development.md b/docs/development.md index 6a82eb5..028d1b5 100644 --- a/docs/development.md +++ b/docs/development.md @@ -8,12 +8,18 @@ Debian Linux are not supported. On a Debian Linux (9.6.0 stable) system install the required packages: - sudo apt-get update - sudo apt-get install -y build-essential git wget binfmt-support qemu \ - parted gcc-avr avr-libc avrdude pylint3 python3 python3-tornado curl \ - unzip python3-setuptools gcc-arm-linux-gnueabihf bc sudo - curl -sL https://deb.nodesource.com/setup_13.x | sudo -E bash - - sudo apt-get install -y nodejs + apt update + apt upgrade -y + apt install -y \ + build-essential git wget binfmt-support qemu gcc-9 \ + parted gcc-avr avr-libc avrdude python3 python3-tornado curl \ + unzip python3-setuptools gcc-arm-linux-gnueabihf bc sudo + + update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 9 + + curl -fsSL https://deb.nodesource.com/setup_18.x | bash - + + apt install -y nodejs ## Getting the Source Code diff --git a/scripts/11-automount.rules b/installer/config/11-automount.rules similarity index 100% rename from scripts/11-automount.rules rename to installer/config/11-automount.rules diff --git a/scripts/Xresources b/installer/config/Xresources similarity index 100% rename from scripts/Xresources rename to installer/config/Xresources diff --git a/scripts/bbctrl-logrotate b/installer/config/bbctrl-logrotate similarity index 100% rename from scripts/bbctrl-logrotate rename to installer/config/bbctrl-logrotate diff --git a/installer/config/bbctrl-poweroff.service b/installer/config/bbctrl-poweroff.service new file mode 100644 index 0000000..e4a65fa --- /dev/null +++ b/installer/config/bbctrl-poweroff.service @@ -0,0 +1,15 @@ +[Unit] +Description=Turn off HDMI at powerdown +DefaultDependencies=no +Before=umount.target + +[Service] +Type=oneshot +ExecStart=/bin/sh -c ' \ + killall xinit \ + && plymouth change-mode --shutdown show-splash \ + && sleep 10s \ + && /usr/bin/vcgencmd display_power 0 ' + +[Install] +WantedBy=poweroff.target diff --git a/scripts/bbctrl.service b/installer/config/bbctrl.service similarity index 100% rename from scripts/bbctrl.service rename to installer/config/bbctrl.service diff --git a/scripts/cron_d_reboot b/installer/config/cron_d_reboot similarity index 100% rename from scripts/cron_d_reboot rename to installer/config/cron_d_reboot diff --git a/scripts/cron_reboot_logrotate b/installer/config/cron_reboot_logrotate similarity index 100% rename from scripts/cron_reboot_logrotate rename to installer/config/cron_reboot_logrotate diff --git a/scripts/ratpoisonrc b/installer/config/ratpoisonrc similarity index 100% rename from scripts/ratpoisonrc rename to installer/config/ratpoisonrc diff --git a/scripts/rc.local b/installer/config/rc.local similarity index 85% rename from scripts/rc.local rename to installer/config/rc.local index 43e549a..546e979 100644 --- a/scripts/rc.local +++ b/installer/config/rc.local @@ -23,9 +23,6 @@ fi # Reload udev /etc/init.d/udev restart -# Stop boot splash so it doesn't interfere with X if GPU enabled and to save CPU -plymouth quit - # Start X in /home/pi cd /home/pi sudo -u pi startx diff --git a/scripts/xinitrc b/installer/config/xinitrc similarity index 89% rename from scripts/xinitrc rename to installer/config/xinitrc index b93833e..13d1691 100644 --- a/scripts/xinitrc +++ b/installer/config/xinitrc @@ -15,8 +15,7 @@ while true; do xrdb /home/pi/.Xresources # Start browser - /usr/local/bin/browser --no-first-run --disable-infobars \ - --noerrdialogs --disable-3d-apis http://localhost/ + /usr/local/bin/browser --no-first-run --disable-infobars --noerrdialogs --disable-3d-apis http://localhost/ fi sleep 1 diff --git a/installer/gcode/Team Onefinity.ngc b/installer/gcode/Team Onefinity.ngc new file mode 100644 index 0000000..85cdef0 --- /dev/null +++ b/installer/gcode/Team Onefinity.ngc @@ -0,0 +1,659 @@ +% +G21 G40 G49 M6 T1 +G17 +M7 +G0Z20.320 +G0X0.000Y0.000S16000M3 +G0X26.732Y12.863Z5.080 +G1Z-3.175F1270.0 +G1X21.606Y17.989F2540.0 +G1Y12.042 +G1X25.676Y12.773 +G1X26.732Y12.863 +G1X34.154Y9.033 +G1X19.066Y24.121 +G1Y9.006 +G1X26.125Y10.273 +G2X27.247Y10.273I0.561J-3.125 +G1X34.154Y9.033 +G0Z5.080 +G0X31.766Y33.993 +G1Z-3.175F1270.0 +G1X21.606Y44.153F2540.0 +G1Y43.784 +G1X31.766Y33.624 +G1Y33.993 +G1X34.306Y35.045 +G1X19.066Y50.285 +G1Y42.732 +G1X34.306Y27.492 +G1Y35.045 +G0Z5.080 +G0X31.766Y60.159 +G1Z-3.175F1270.0 +G1X21.606Y70.318F2540.0 +G1Y69.948 +G1X31.766Y59.789 +G1Y60.159 +G1X34.306Y61.211 +G1X19.066Y76.450 +G1Y68.896 +G1X34.306Y53.657 +G1Y61.211 +G0Z5.080 +G0X31.766Y90.231 +G1Z-3.175F1270.0 +G1X27.488F2540.0 +G1X31.766Y85.954 +G1Y90.231 +G1X34.306Y92.771 +G1X21.356 +G1X34.306Y79.822 +G1Y92.771 +G0Z5.080 +G0X61.691Y55.036 +G1Z-3.175F1270.0 +G1X63.248F2540.0 +G1Y88.425 +G2X66.423Y91.600I3.175J0.000 +G1X77.157 +G1Y91.866 +G1X47.750 +G1Y91.600 +G1X58.516 +G2X61.691Y88.425I0.000J-3.175 +G1Y55.036 +G0Z5.080 +G0X88.590 +G1Z-3.175F1270.0 +G1X111.381F2540.0 +G1Y55.301 +G1X93.321 +G2X90.146Y58.476I0.000J3.175 +G1Y70.643 +G2X93.321Y73.818I3.175J0.000 +G1X107.380 +G1Y74.084 +G1X93.321 +G2X90.146Y77.259I0.000J3.175 +G1Y88.425 +G2X93.321Y91.600I3.175J0.000 +G1X110.220 +G1Y91.866 +G1X88.590 +G1Y55.036 +G0Z5.080 +G0X122.153 +G1Z-3.175F1270.0 +G1X123.719F2540.0 +G1X127.166Y64.004 +G2X130.130Y66.040I2.964J-1.139 +G1X146.391 +G2X149.354Y64.004I0.000J-3.175 +G1X152.802Y55.036 +G1X154.303 +G1X139.687Y91.866 +G1X136.769 +G1X122.153Y55.036 +G0Z5.080 +G0X132.680Y66.306 +G1Z-3.175F1270.0 +G2X129.716Y70.620I0.000J3.175F2540.0 +G1X132.098Y76.845 +G1X133.063Y79.498 +G1X134.092Y82.435 +G1X135.189Y85.669 +G2X138.196Y87.824I3.007J-1.020 +G1X138.325 +G2X141.328Y85.679I0.000J-3.175 +G1X142.433Y82.457 +G1X143.467Y79.518 +G1X144.433Y76.851 +G1X145.333Y74.451 +G1X146.805Y70.620 +G2X143.841Y66.306I-2.964J-1.138 +G1X132.680 +G0Z5.080 +G0X167.414Y55.036 +G1Z-3.175F1270.0 +G1X168.971F2540.0 +G1Y73.759 +G1X168.947Y76.349 +G1X168.876Y79.029 +G1X168.757Y81.813 +G1X168.589Y84.724 +G2X171.759Y88.082I3.170J0.183 +G1X172.049 +G2X175.085Y85.836I0.000J-3.175 +G1X175.677Y83.901 +G1X176.359Y81.760 +G1X177.102Y79.531 +G1X177.877Y77.332 +G1X182.870Y63.705 +G1X182.369Y65.444 +G1X181.521Y68.194 +G1X180.648Y70.844 +G1X179.742Y73.414 +G1X173.050Y91.866 +G1X167.414 +G1Y55.036 +G0Z5.080 +G0X186.047 +G1Z-3.175F1270.0 +G1X186.709F2540.0 +G1X189.243Y61.950 +G2X186.442Y60.271I-2.800J1.496 +G1X186.249 +G2X183.614Y61.675I0.000J3.175 +G1X186.047Y55.036 +G0Z5.080 +G0X203.785 +G1Z-3.175F1270.0 +G1X205.342F2540.0 +G1Y91.866 +G1X199.644 +G1X192.952Y73.323 +G1X191.959Y70.488 +G1X191.055Y67.759 +G1X190.236Y65.128 +G1X189.586Y62.886 +G1X194.879Y77.332 +G1X195.654Y79.531 +G1X196.397Y81.760 +G1X197.079Y83.901 +G1X197.670Y85.836 +G2X200.707Y88.082I3.036J-0.928 +G1X200.997 +G2X204.167Y84.733I0.000J-3.175 +G1X203.999Y81.672 +G1X203.880Y78.828 +G1X203.809Y76.184 +G1X203.785Y73.726 +G1Y55.036 +G0Z5.080 +G0X186.055Y18.115 +G1Z-3.175F1270.0 +G1X186.009Y18.105F2540.0 +G1X186.055Y17.999 +G1Y18.115 +G1X185.846Y20.662 +G2X183.925Y20.635I-1.003J3.012 +G1X183.850Y20.658 +G2X182.792Y21.213I0.918J3.039 +G1X182.707Y21.280 +G1X182.260Y21.714 +G1X182.051Y21.961 +G1X181.761Y22.394 +G1X181.394Y23.076 +G1X181.055Y23.830 +G1X173.477Y41.419 +G1X172.282 +G1Y8.016 +G1X172.558 +G1Y24.599 +G1X172.580Y25.408 +G1X172.663Y26.179 +G1X172.774Y26.696 +G1X172.878Y27.007 +G1X173.108Y27.530 +G1X173.164Y27.632 +G2X173.748Y28.390I2.780J-1.535 +G1X173.813Y28.452 +G2X175.480Y29.290I2.196J-2.293 +G1X175.555Y29.303 +G2X177.475Y29.026I0.528J-3.131 +G1X177.562Y28.984 +G2X178.399Y28.391I-1.391J-2.854 +G1X178.498Y28.294 +G1X178.838Y27.899 +G1X179.037Y27.625 +G1X179.285Y27.206 +G1X179.505Y26.777 +G1X187.630Y8.016 +G1X188.570 +G1Y41.419 +G1X188.294 +G1Y25.010 +G1X188.271Y24.216 +G1X188.177Y23.433 +G1X188.086Y23.078 +G1X187.917Y22.590 +G1X187.870Y22.482 +G2X187.362Y21.681I-2.906J1.279 +G1X187.306Y21.616 +G2X185.911Y20.684I-2.399J2.080 +G1X185.846Y20.662 +G0Z5.080 +G0X174.797Y31.718 +G1Z-3.175F1270.0 +G1X174.912Y31.742F2540.0 +G1X174.797Y32.011 +G1Y31.718 +G0Z5.080 +G0X201.208Y8.016 +G1Z-3.175F1270.0 +G1X201.483F2540.0 +G1Y41.419 +G1X201.208 +G1Y8.016 +G0Z5.080 +G0X221.852 +G1Z-3.175F1270.0 +G1X222.128F2540.0 +G1Y35.585 +G1X222.152Y36.556 +G1X222.239Y37.441 +G1X222.338Y37.967 +G1X222.494Y38.513 +G1X222.648Y38.864 +G1X222.990Y39.459 +G1X223.068Y39.565 +G2X223.987Y40.409I2.564J-1.872 +G1X224.094Y40.473 +G1X224.660Y40.744 +G1X224.991Y40.863 +G1X225.495Y40.981 +G1X225.981Y41.055 +G1X226.840Y41.124 +G1X227.808Y41.143 +G1X229.857 +G1Y41.419 +G1X214.122 +G1Y41.143 +G1X217.128Y41.132 +G1X217.865Y41.093 +G1X218.540Y41.009 +G1X219.037Y40.895 +G1X219.329Y40.787 +G1X219.958Y40.472 +G1X220.109Y40.375 +G1X220.711Y39.869 +G1X220.827Y39.744 +G1X221.305Y39.070 +G1X221.385Y38.918 +G1X221.658Y38.205 +G1X221.703Y38.027 +G1X221.790Y37.485 +G1X221.837Y36.840 +G1X221.852Y35.846 +G1Y8.016 +G0Z5.080 +G0X250.225 +G1Z-3.175F1270.0 +G1X250.501F2540.0 +G1Y16.797 +G1X250.516Y17.761 +G1X250.567Y18.756 +G1X250.681Y19.487 +G1X250.826Y20.159 +G1X251.009Y20.832 +G1X257.512Y41.419 +G1X257.222 +G1X253.849Y30.875 +G1X253.398Y29.763 +G1X253.228Y29.421 +G1X252.892Y28.886 +G1X252.817Y28.790 +G2X250.547Y27.571I-2.508J1.947 +G1X250.489Y27.567 +G2X248.506Y28.080I-0.238J3.166 +G1X248.444Y28.121 +G2X247.655Y28.861I1.745J2.653 +G1X247.590Y28.947 +G1X247.304Y29.401 +G1X247.150Y29.698 +G1X246.888Y30.394 +G1X246.668Y31.132 +G1X243.420Y41.419 +G1X243.133 +G1X249.500Y21.400 +G1X249.680Y20.918 +G1X249.880Y20.269 +G1X250.036Y19.612 +G1X250.149Y18.936 +G1X250.190Y18.463 +G1X250.211Y17.912 +G1X250.225Y16.513 +G1Y8.016 +G0Z5.080 +G0X159.368 +G1Z-3.175F1270.0 +G1X159.644F2540.0 +G1Y41.419 +G1X159.368 +G1Y8.016 +G0Z5.080 +G0X133.203 +G1Z-3.175F1270.0 +G1X133.478F2540.0 +G1Y19.288 +G1X133.495Y20.123 +G1X133.556Y20.925 +G1X133.697Y21.712 +G1X133.822Y22.074 +G1X134.078Y22.633 +G1X134.130Y22.723 +G2X135.032Y23.713I2.746J-1.594 +G1X135.122Y23.778 +G1X135.738Y24.121 +G1X136.070Y24.260 +G1X136.588Y24.399 +G1X137.076Y24.485 +G1X137.885Y24.559 +G1X138.771Y24.580 +G1X145.626 +G1Y24.855 +G1X139.094 +G1X138.075Y24.883 +G1X137.539Y24.929 +G1X137.029Y24.999 +G1X136.489Y25.115 +G1X136.122Y25.236 +G1X135.630Y25.447 +G1X135.480Y25.527 +G1X134.777Y26.035 +G1X134.681Y26.127 +G1X134.136Y26.817 +G1X134.084Y26.906 +G1X133.828Y27.457 +G1X133.702Y27.818 +G1X133.557Y28.600 +G1X133.495Y29.391 +G1X133.478Y30.207 +G1Y35.748 +G1X133.502Y36.665 +G1X133.541Y37.153 +G1X133.601Y37.619 +G1X133.699Y38.112 +G1X133.873Y38.681 +G1X134.045Y39.039 +G1X134.470Y39.698 +G1X134.548Y39.791 +G2X135.430Y40.523I2.436J-2.037 +G1X135.520Y40.574 +G1X136.072Y40.818 +G1X136.429Y40.936 +G1X137.204Y41.070 +G1X137.999Y41.128 +G1X138.833Y41.143 +G1X146.730 +G1Y41.419 +G1X133.203 +G1Y8.016 +G0Z5.080 +G0X107.038 +G1Z-3.175F1270.0 +G1X120.565F2540.0 +G1Y8.291 +G1X112.934 +G1X111.953Y8.315 +G1X111.446Y8.353 +G1X110.966Y8.412 +G1X110.462Y8.507 +G1X109.883Y8.676 +G1X109.516Y8.848 +G1X108.829Y9.284 +G1X108.734Y9.363 +G2X108.068Y10.127I2.031J2.441 +G1X108.003Y10.231 +G1X107.733Y10.777 +G1X107.609Y11.102 +G1X107.485Y11.599 +G1X107.405Y12.080 +G1X107.334Y12.901 +G1X107.313Y13.808 +G1Y19.288 +G1X107.330Y20.123 +G1X107.391Y20.925 +G1X107.532Y21.712 +G1X107.657Y22.074 +G1X107.913Y22.633 +G1X107.965Y22.723 +G2X108.867Y23.713I2.746J-1.594 +G1X108.957Y23.778 +G1X109.573Y24.121 +G1X109.905Y24.260 +G1X110.423Y24.399 +G1X110.911Y24.485 +G1X111.720Y24.559 +G1X112.606Y24.580 +G1X119.461 +G1Y24.855 +G1X112.929 +G1X111.910Y24.883 +G1X111.374Y24.929 +G1X110.863Y24.999 +G1X110.323Y25.115 +G1X109.957Y25.236 +G1X109.464Y25.447 +G1X109.315Y25.527 +G1X108.612Y26.035 +G1X108.516Y26.127 +G1X107.971Y26.817 +G1X107.919Y26.906 +G1X107.663Y27.457 +G1X107.536Y27.818 +G1X107.392Y28.600 +G1X107.330Y29.391 +G1X107.313Y30.207 +G1Y35.748 +G1X107.337Y36.665 +G1X107.376Y37.153 +G1X107.436Y37.619 +G1X107.534Y38.112 +G1X107.708Y38.681 +G1X107.880Y39.039 +G1X108.305Y39.698 +G1X108.383Y39.791 +G2X109.265Y40.523I2.436J-2.037 +G1X109.355Y40.573 +G1X109.907Y40.817 +G1X110.263Y40.936 +G1X111.039Y41.070 +G1X111.834Y41.128 +G1X112.668Y41.143 +G1X120.565 +G1Y41.419 +G1X107.038 +G1Y8.016 +G0Z5.080 +G0X91.885Y18.115 +G1Z-3.175F1270.0 +G1X91.839Y18.105F2540.0 +G1X91.885Y17.998 +G1Y18.115 +G1X91.677Y20.662 +G2X89.754Y20.635I-1.004J3.012 +G1X89.680Y20.658 +G2X88.622Y21.213I0.918J3.039 +G1X88.537Y21.280 +G1X88.090Y21.713 +G1X87.881Y21.961 +G1X87.591Y22.393 +G1X87.224Y23.076 +G1X86.885Y23.829 +G1X79.307Y41.419 +G1X78.112 +G1Y8.016 +G1X78.388 +G1Y24.599 +G1X78.409Y25.408 +G1X78.493Y26.180 +G1X78.604Y26.697 +G1X78.709Y27.008 +G1X78.939Y27.531 +G1X78.995Y27.633 +G2X79.578Y28.391I2.779J-1.535 +G1X79.643Y28.453 +G2X81.310Y29.290I2.196J-2.293 +G1X81.385Y29.302 +G2X83.305Y29.026I0.529J-3.131 +G1X83.392Y28.983 +G2X84.229Y28.391I-1.392J-2.854 +G1X84.328Y28.294 +G1X84.668Y27.899 +G1X84.867Y27.625 +G1X85.115Y27.206 +G1X85.335Y26.777 +G1X93.460Y8.016 +G1X94.400 +G1Y41.419 +G1X94.124 +G1Y25.009 +G1X94.101Y24.216 +G1X94.007Y23.432 +G1X93.916Y23.078 +G1X93.747Y22.590 +G1X93.700Y22.482 +G2X93.193Y21.681I-2.906J1.279 +G1X93.137Y21.617 +G2X91.742Y20.684I-2.399J2.079 +G1X91.677Y20.662 +G0Z5.080 +G0X80.627Y31.718 +G1Z-3.175F1270.0 +G1X80.742Y31.742F2540.0 +G1X80.627Y32.010 +G1Y31.718 +G0Z5.080 +G0X56.689Y8.295 +G1Z-3.175F1270.0 +G1X57.314Y8.143F2540.0 +G1X57.985Y8.049 +G1X58.710Y8.016 +G1X59.435Y8.049 +G1X60.106Y8.143 +G1X60.731Y8.295 +G1X61.320Y8.505 +G1X61.883Y8.775 +G1X62.429Y9.109 +G1X62.964Y9.516 +G1X63.493Y10.004 +G1X63.980Y10.541 +G1X64.387Y11.085 +G1X64.721Y11.636 +G1X64.989Y12.201 +G1X65.197Y12.788 +G1X65.348Y13.407 +G1X65.441Y14.069 +G1X65.474Y14.815 +G1X65.465Y35.027 +G1X65.401Y35.727 +G1X65.278Y36.377 +G1X65.098Y36.986 +G1X64.861Y37.562 +G1X64.563Y38.116 +G1X64.197Y38.656 +G1X63.755Y39.187 +G1X63.241Y39.701 +G1X62.710Y40.142 +G1X62.170Y40.508 +G1X61.616Y40.807 +G1X61.040Y41.044 +G1X60.431Y41.224 +G1X59.781Y41.347 +G1X59.081Y41.410 +G1X58.339 +G1X57.639Y41.347 +G1X56.989Y41.224 +G1X56.381Y41.044 +G1X55.804Y40.807 +G1X55.250Y40.508 +G1X54.710Y40.142 +G1X54.179Y39.701 +G1X53.665Y39.187 +G1X53.224Y38.656 +G1X52.858Y38.116 +G1X52.559Y37.562 +G1X52.322Y36.986 +G1X52.142Y36.377 +G1X52.019Y35.727 +G1X51.956Y35.027 +G1X51.956Y14.417 +G1X52.018Y13.732 +G1X52.140Y13.093 +G1X52.320Y12.491 +G1X52.558Y11.916 +G1X52.858Y11.359 +G1X53.228Y10.812 +G1X53.674Y10.272 +G1X54.191Y9.750 +G1X54.722Y9.303 +G1X55.262Y8.933 +G1X55.816Y8.632 +G1X56.391Y8.393 +G1X56.689Y8.295 +G0Z5.080 +G0X56.804Y8.566 +G1Z-3.175F1270.0 +G1X56.190Y8.789F2540.0 +G1X55.603Y9.076 +G1X55.053Y9.420 +G1X54.545Y9.814 +G1X54.085Y10.247 +G1X53.673Y10.711 +G1X53.303Y11.209 +G1X52.978Y11.746 +G1X52.705Y12.317 +G1X52.490Y12.915 +G1X52.338Y13.530 +G1X52.248Y14.154 +G1X52.222Y14.705 +G1Y34.727 +G1X52.247Y35.285 +G1X52.335Y35.913 +G1X52.485Y36.536 +G1X52.699Y37.143 +G1X52.975Y37.726 +G1X53.308Y38.275 +G1X53.691Y38.784 +G1X54.116Y39.250 +G1X54.583Y39.676 +G1X55.091Y40.058 +G1X55.640Y40.391 +G1X56.223Y40.667 +G1X56.831Y40.881 +G1X57.453Y41.031 +G1X58.082Y41.119 +G1X58.710Y41.147 +G1X59.339Y41.119 +G1X59.967Y41.031 +G1X60.590Y40.881 +G1X61.197Y40.667 +G1X61.780Y40.391 +G1X62.329Y40.058 +G1X62.837Y39.676 +G1X63.304Y39.250 +G1X63.730Y38.784 +G1X64.112Y38.275 +G1X64.445Y37.726 +G1X64.721Y37.143 +G1X64.935Y36.536 +G1X65.086Y35.913 +G1X65.173Y35.285 +G1X65.198Y34.727 +G1Y14.705 +G1X65.172Y14.154 +G1X65.083Y13.530 +G1X64.930Y12.915 +G1X64.716Y12.317 +G1X64.443Y11.746 +G1X64.118Y11.209 +G1X63.748Y10.711 +G1X63.335Y10.247 +G1X62.875Y9.814 +G1X62.367Y9.420 +G1X61.817Y9.076 +G1X61.230Y8.789 +G1X60.616Y8.566 +G1X59.985Y8.409 +G1X59.348Y8.317 +G1X58.710Y8.288 +G1X58.072Y8.317 +G1X57.435Y8.409 +G1X56.804Y8.566 +G0Z5.080 +G0Z20.320 +G0X0.000Y0.000 +M2 +% diff --git a/installer/linux-packages/virtualKeyboard.zip b/installer/linux-packages/virtualKeyboard.zip new file mode 100644 index 0000000..beed383 Binary files /dev/null and b/installer/linux-packages/virtualKeyboard.zip differ diff --git a/installer/linux-packages/zram-config-main.zip b/installer/linux-packages/zram-config-main.zip new file mode 100644 index 0000000..b976d7d Binary files /dev/null and b/installer/linux-packages/zram-config-main.zip differ diff --git a/installer/python-packages/evdev-1.6.0.tar.gz b/installer/python-packages/evdev-1.6.0.tar.gz new file mode 100644 index 0000000..84ccc2f Binary files /dev/null and b/installer/python-packages/evdev-1.6.0.tar.gz differ diff --git a/python-packages/pathtools-0.1.2-py3-none-any.whl b/installer/python-packages/pathtools-0.1.2-py3-none-any.whl similarity index 100% rename from python-packages/pathtools-0.1.2-py3-none-any.whl rename to installer/python-packages/pathtools-0.1.2-py3-none-any.whl diff --git a/python-packages/watchdog-0.10.6-py3-none-any.whl b/installer/python-packages/watchdog-0.10.6-py3-none-any.whl similarity index 100% rename from python-packages/watchdog-0.10.6-py3-none-any.whl rename to installer/python-packages/watchdog-0.10.6-py3-none-any.whl diff --git a/scripts/avr109-flash.py b/installer/scripts/avr109-flash.py similarity index 100% rename from scripts/avr109-flash.py rename to installer/scripts/avr109-flash.py diff --git a/scripts/browser b/installer/scripts/browser similarity index 100% rename from scripts/browser rename to installer/scripts/browser diff --git a/installer/scripts/config-wifi b/installer/scripts/config-wifi new file mode 100644 index 0000000..e80b444 --- /dev/null +++ b/installer/scripts/config-wifi @@ -0,0 +1,151 @@ +#!/bin/bash -e + +DISABLE=false +SSID= +PASS= +REBOOT=false + +WLAN0_CFG=/etc/network/interfaces.d/wlan0 +DHCPCD_CFG=/etc/dhcpcd.conf +WPA_CFG=/etc/wpa_supplicant/wpa_supplicant.conf + + +function query_config() { + SSID=$(grep wpa-ssid $WLAN0_CFG | + sed 's/^[[:space:]]*wpa-ssid "\([^"]*\)"/\1/') + echo "{\"ssid\": \"$SSID\"}" +} + + +function disable_wifi() { + rm -f $WLAN0_CFG +} + + +function configure_wlan0() { + echo "auto wlan0" + echo "allow-hotplug wlan0" + echo "iface wlan0 inet dhcp" + echo " wpa-scan-ssid 1" + echo " wpa-ap-scan 1" + echo " wpa-key-mgmt WPA-PSK" + echo " wpa-proto RSN WPA" + echo " wpa-pairwise CCMP TKIP" + echo " wpa-group CCMP TKIP" + echo " wpa-ssid \"$SSID\"" + + if [ ${#PASS} -ne 0 ]; then + echo " wpa-psk \"$PASS\"" + fi +} + + +function configure_wpa() { + echo "country=US" + echo "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev" + echo "update_config=1" + + if [ ${#PASS} -eq 0 ]; then + echo "network={" + echo " ssid=\"$SSID\"" + echo " key_mgmt=NONE" + echo "}" + fi +} + + +function configure_dhcpcd() { + echo "hostname" + echo "clientid" + echo "persistent" + echo "option rapid_commit" + echo "option domain_name_servers, domain_name, domain_search, host_name" + echo "option classless_static_routes" + echo "option ntp_servers" + echo "option interface_mtu" + echo "require dhcp_server_identifier" + echo "slaac private" +} + + +function configure_wifi() { + disable_wifi + echo "source-directory /etc/network/interfaces.d" > /etc/network/interfaces + configure_wlan0 > $WLAN0_CFG + configure_wpa > $WPA_CFG + configure_dhcpcd > $DHCPCD_CFG +} + + +function usage() { + echo "Usage: config-wifi [OPTIONS]" + echo + echo "Configure wifi as either a client or access point." + echo + echo "OPTIONS:" + echo + echo " -d Disable wifi." + echo " -r Reboot when done." + echo " -s Set SSID." + echo " -p Set password." + echo " -j Report wifi config as JSON data." + echo +} + + +# Parse args +while [ $# -ne 0 ]; do + case "$1" in + -d) DISABLE=true ;; + -r) REBOOT=true; ;; + -s) SSID="$2"; shift ;; + -p) PASS="$2"; shift ;; + -j) query_config; exit 0 ;; + + -h) + usage + exit 0 + ;; + + *) + usage + echo "Unknown argument '$1'" + exit 1 + esac + + shift +done + + +if $DISABLE; then + disable_wifi +else + # Check args + function clean_str() { + echo "$1" | tr -d '\n\r"' + } + + SSID=$(clean_str "$SSID") + PASS=$(clean_str "$PASS") + + LANG=C LC_ALL=C # For correct string byte length + + if [ ${#SSID} -eq 0 -o 32 -lt ${#SSID} ]; then + echo "Invalid or missing SSID '$SSID'" + exit 1 + fi + + if [ ${#PASS} -ne 0 ]; then + if [ ${#PASS} -lt 8 -o 128 -lt ${#PASS} ]; then + echo "Invalid passsword" + exit 1 + fi + fi + + # Execute + echo "Configuring Wifi" + configure_wifi +fi + + +if $REBOOT; then nohup reboot & fi diff --git a/scripts/delete-cookies.py b/installer/scripts/delete-cookies.py similarity index 100% rename from scripts/delete-cookies.py rename to installer/scripts/delete-cookies.py diff --git a/scripts/edit-boot-config b/installer/scripts/edit-boot-config similarity index 100% rename from scripts/edit-boot-config rename to installer/scripts/edit-boot-config diff --git a/scripts/edit-config b/installer/scripts/edit-config similarity index 100% rename from scripts/edit-config rename to installer/scripts/edit-config diff --git a/scripts/resize_root_fs.sh b/installer/scripts/resize_root_fs.sh similarity index 82% rename from scripts/resize_root_fs.sh rename to installer/scripts/resize_root_fs.sh index 16a4619..51fe535 100755 --- a/scripts/resize_root_fs.sh +++ b/installer/scripts/resize_root_fs.sh @@ -37,7 +37,6 @@ should_resize_root_partition() { if [ "$ROOT_PART_END" -gt "$TARGET_END" ]; then FAIL_REASON="Root partition runs past the end of device" - echo $FAIL_REASON return 1 fi @@ -60,18 +59,9 @@ if should_resize_root_partition; then # Remove itself from /boot/cmdline.txt # Reboot the machine sudo mount /boot -o rw,remount - sed -i 's/\(.*\)/\1 init=\/usr\/lib\/raspi-config\/init_resize.sh/' /boot/cmdline.txt + sed -i -E 's|(.*)|\1 init=/usr/lib/raspi-config/init_resize.sh|' /boot/cmdline.txt fi - # On the first boot after init_resize, resize2fs_once will: - # Resize the root fs to fill its partition - # Remove itself from the registered systemd services - # Delete itself from the filesystem - # Therefore, never run again - cp scripts/resize2fs_once /etc/init.d/resize2fs_once - chmod +x /etc/init.d/resize2fs_once - systemctl enable resize2fs_once - exit 0 else echo "Not resizing root partition: $FAIL_REASON" diff --git a/scripts/sethostname b/installer/scripts/sethostname similarity index 100% rename from scripts/sethostname rename to installer/scripts/sethostname diff --git a/scripts/update-bbctrl b/installer/scripts/update-bbctrl similarity index 100% rename from scripts/update-bbctrl rename to installer/scripts/update-bbctrl diff --git a/scripts/upgrade-bbctrl b/installer/scripts/upgrade-bbctrl similarity index 100% rename from scripts/upgrade-bbctrl rename to installer/scripts/upgrade-bbctrl diff --git a/installer/splash/boot.png b/installer/splash/boot.png new file mode 100644 index 0000000..2008ca2 Binary files /dev/null and b/installer/splash/boot.png differ diff --git a/installer/splash/onefinity.plymouth b/installer/splash/onefinity.plymouth new file mode 100644 index 0000000..e3c4b9f --- /dev/null +++ b/installer/splash/onefinity.plymouth @@ -0,0 +1,8 @@ +[Plymouth Theme] +Name=onefinity +Description=Onefinity +ModuleName=script + +[script] +ImageDir=/usr/share/plymouth/themes/onefinity +ScriptFile=/usr/share/plymouth/themes/onefinity/onefinity.script diff --git a/src/splash/buildbotics.script b/installer/splash/onefinity.script similarity index 87% rename from src/splash/buildbotics.script rename to installer/splash/onefinity.script index 51fb51d..7e41057 100644 --- a/src/splash/buildbotics.script +++ b/installer/splash/onefinity.script @@ -1,7 +1,12 @@ screenW = Window.GetWidth(); screenH = Window.GetHeight(); -image = Image("splash.png"); +image = Image("boot.png"); + +if (Plymouth.GetMode() == "shutdown") { + image = Image("shutdown.png"); +} + imageW = image.GetWidth(); imageH = image.GetHeight(); diff --git a/installer/splash/shutdown.png b/installer/splash/shutdown.png new file mode 100644 index 0000000..1800389 Binary files /dev/null and b/installer/splash/shutdown.png differ diff --git a/package-lock.json b/package-lock.json index 79d0427..7585cb7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5580 +1,10677 @@ { - "name": "bbctrl", - "version": "1.0.10b1", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "bbctrl", - "version": "1.0.10b1", - "license": "GPL-3.0+", - "dependencies": { - "browserify": "^17.0.0", - "jshint": "^2.13.4", - "jstransformer-escape-html": "^1.1.0", - "jstransformer-scss": "^2.0.0", - "jstransformer-stylus": "^1.5.0", - "lodash.merge": "4.6.2", - "lodash.omit": "^4.5.0", - "pug-cli": "^1.0.0-alpha6" - } - }, - "node_modules/@types/babel-types": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.11.tgz", - "integrity": "sha512-pkPtJUUY+Vwv6B1inAz55rQvivClHJxc9aVEPPmaq2cbyeMLCiDpbKpcKyX4LAwpNGi+SHBv0tHv6+0gXv0P2A==" - }, - "node_modules/@types/babylon": { - "version": "6.16.6", - "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.6.tgz", - "integrity": "sha512-G4yqdVlhr6YhzLXFKy5F7HtRBU8Y23+iWy7UKthMq/OSQnL1hbsoeXESQ2LY8zEDlknipDG3nRGhUC9tkwvy/w==", - "dependencies": { - "@types/babel-types": "*" - } - }, - "node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-globals": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", - "integrity": "sha512-uWttZCk96+7itPxK8xCzY86PnxKTMrReKDqrHzv42VQY0K30PUO8WY13WMOuI+cOdX4EIdzdvQ8k6jkuGRFMYw==", - "dependencies": { - "acorn": "^4.0.4" - } - }, - "node_modules/acorn-globals/node_modules/acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "dependencies": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - } - }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==", - "dependencies": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" - }, - "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "dependencies": { - "object-assign": "^4.1.1", - "util": "0.10.3" - } - }, - "node_modules/assert/node_modules/inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==" - }, - "node_modules/assert/node_modules/util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==", - "dependencies": { - "inherits": "2.0.1" - } - }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", - "dependencies": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "node_modules/babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==", - "dependencies": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } - }, - "node_modules/babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "bin": { - "babylon": "bin/babylon.js" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" + "name": "bbctrl", + "version": "1.1.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "bbctrl", + "version": "1.1.0", + "hasInstallScript": true, + "license": "GPL-3.0+", + "devDependencies": { + "@typescript-eslint/eslint-plugin": "^5.36.1", + "@typescript-eslint/parser": "^5.36.1", + "browserify": "^17.0.0", + "eslint": "^8.23.0", + "eslint-config-standard-with-typescript": "^22.0.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-n": "^15.2.5", + "eslint-plugin-promise": "^6.0.1", + "glob": "^8.0.3", + "inquirer": "^8.2.4", + "jshint": "^2.13.4", + "jstransformer-escape-html": "^1.1.0", + "jstransformer-scss": "^2.0.0", + "jstransformer-stylus": "^1.5.0", + "lodash.merge": "4.6.2", + "pug-cli": "^1.0.0-alpha6" + } }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "node_modules/@eslint/eslintrc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.1.tgz", + "integrity": "sha512-OhSY22oQQdw3zgPOOwdoj01l/Dzl1Z+xyUP33tkSN+aqyEhymJCcPHyXt+ylW8FSe0TfRC2VG+ROQOapD0aZSQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } }, - { - "type": "consulting", - "url": "https://feross.org/support" + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", + "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@humanwhocodes/gitignore-to-minimatch": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", + "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@types/babel-types": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.11.tgz", + "integrity": "sha512-pkPtJUUY+Vwv6B1inAz55rQvivClHJxc9aVEPPmaq2cbyeMLCiDpbKpcKyX4LAwpNGi+SHBv0tHv6+0gXv0P2A==", + "dev": true + }, + "node_modules/@types/babylon": { + "version": "6.16.6", + "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.6.tgz", + "integrity": "sha512-G4yqdVlhr6YhzLXFKy5F7HtRBU8Y23+iWy7UKthMq/OSQnL1hbsoeXESQ2LY8zEDlknipDG3nRGhUC9tkwvy/w==", + "dev": true, + "dependencies": { + "@types/babel-types": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.36.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.36.1.tgz", + "integrity": "sha512-iC40UK8q1tMepSDwiLbTbMXKDxzNy+4TfPWgIL661Ym0sD42vRcQU93IsZIrmi+x292DBr60UI/gSwfdVYexCA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.36.1", + "@typescript-eslint/type-utils": "5.36.1", + "@typescript-eslint/utils": "5.36.1", + "debug": "^4.3.4", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.2.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.36.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.36.1.tgz", + "integrity": "sha512-/IsgNGOkBi7CuDfUbwt1eOqUXF9WGVBW9dwEe1pi+L32XrTsZIgmDFIi2RxjzsvB/8i+MIf5JIoTEH8LOZ368A==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.36.1", + "@typescript-eslint/types": "5.36.1", + "@typescript-eslint/typescript-estree": "5.36.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.36.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.36.1.tgz", + "integrity": "sha512-pGC2SH3/tXdu9IH3ItoqciD3f3RRGCh7hb9zPdN2Drsr341zgd6VbhP5OHQO/reUqihNltfPpMpTNihFMarP2w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.36.1", + "@typescript-eslint/visitor-keys": "5.36.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.36.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.36.1.tgz", + "integrity": "sha512-xfZhfmoQT6m3lmlqDvDzv9TiCYdw22cdj06xY0obSznBsT///GK5IEZQdGliXpAOaRL34o8phEvXzEo/VJx13Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.36.1", + "@typescript-eslint/utils": "5.36.1", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/types": { + "version": "5.36.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.36.1.tgz", + "integrity": "sha512-jd93ShpsIk1KgBTx9E+hCSEuLCUFwi9V/urhjOWnOaksGZFbTOxAT47OH2d4NLJnLhkVD+wDbB48BuaycZPLBg==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.36.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.36.1.tgz", + "integrity": "sha512-ih7V52zvHdiX6WcPjsOdmADhYMDN15SylWRZrT2OMy80wzKbc79n8wFW0xpWpU0x3VpBz/oDgTm2xwDAnFTl+g==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.36.1", + "@typescript-eslint/visitor-keys": "5.36.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.36.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.36.1.tgz", + "integrity": "sha512-lNj4FtTiXm5c+u0pUehozaUWhh7UYKnwryku0nxJlYUEWetyG92uw2pr+2Iy4M/u0ONMKzfrx7AsGBTCzORmIg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.36.1", + "@typescript-eslint/types": "5.36.1", + "@typescript-eslint/typescript-estree": "5.36.1", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.36.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.36.1.tgz", + "integrity": "sha512-ojB9aRyRFzVMN3b5joSYni6FAS10BBSCAfKJhjJAV08t/a95aM6tAhz+O1jF+EtgxktuSO3wJysp2R+Def/IWQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.36.1", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", + "integrity": "sha512-uWttZCk96+7itPxK8xCzY86PnxKTMrReKDqrHzv42VQY0K30PUO8WY13WMOuI+cOdX4EIdzdvQ8k6jkuGRFMYw==", + "dev": true, + "dependencies": { + "acorn": "^4.0.4" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-includes": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", + "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", + "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "dependencies": { + "object-assign": "^4.1.1", + "util": "0.10.3" + } + }, + "node_modules/assert/node_modules/inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==", + "dev": true + }, + "node_modules/assert/node_modules/util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==", + "dev": true, + "dependencies": { + "inherits": "2.0.1" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "dev": true, + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "node_modules/babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true, + "bin": { + "babylon": "bin/babylon.js" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true + }, + "node_modules/browser-pack": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", + "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", + "dev": true, + "dependencies": { + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "JSONStream": "^1.0.3", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" + }, + "bin": { + "browser-pack": "bin/cmd.js" + } + }, + "node_modules/browser-resolve": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", + "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", + "dev": true, + "dependencies": { + "resolve": "^1.17.0" + } + }, + "node_modules/browserify": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz", + "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==", + "dev": true, + "dependencies": { + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^2.0.0", + "browserify-zlib": "~0.2.0", + "buffer": "~5.2.1", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.1", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^3.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.2.1", + "JSONStream": "^1.0.3", + "labeled-stream-splicer": "^2.0.0", + "mkdirp-classic": "^0.5.2", + "module-deps": "^6.2.3", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "^1.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum-object": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^3.0.0", + "stream-http": "^3.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.12.0", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + }, + "bin": { + "browserify": "bin/cmd.js" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/browserify/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "dev": true, + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", + "dev": true + }, + "node_modules/builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/builtins/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cached-path-relative": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.1.0.tgz", + "integrity": "sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==", + "dev": true + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==", + "dev": true, + "dependencies": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/character-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", + "integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==", + "dev": true, + "dependencies": { + "is-regex": "^1.0.3" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/clean-css": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", + "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha512-41U72MB56TfUMGndAKK8vJ78eooOD4Z5NOL4xEfjc0c23s+6EYKXlXsmACBVclLP1yOfWCgEganVzddVrSNoTg==", + "dev": true, + "dependencies": { + "exit": "0.1.2", + "glob": "^7.1.1" + }, + "engines": { + "node": ">=0.2.5" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", + "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cli/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==", + "dev": true, + "dependencies": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha512-UlxQ9Vw0b/Bt/KYwCFqdEwsQ1eL8d1gibiFb7lxQJFdvTgc2hIZi6ugsg+kyhzhPV+QEpUiEIwInIAIrgoEkrg==", + "dev": true, + "dependencies": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "node_modules/constantinople": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.2.tgz", + "integrity": "sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw==", + "dev": true, + "dependencies": { + "@types/babel-types": "^7.0.0", + "@types/babylon": "^6.16.2", + "babel-types": "^6.26.0", + "babylon": "^6.18.0" + } + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha512-Y8L5rp6jo+g9VEPgvqNfEopjTR4OTYct8lXlS8iVQdmnjDvbdbzYe9rjtFCB9egC86JoNCU61WRY+ScjkZpnIg==", + "dev": true + }, + "node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "dev": true, + "hasInstallScript": true + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + } + }, + "node_modules/css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha512-UNIFik2RgSbiTwIW1IsFwXWn6vs+bYdq83LKTSOsx7NJR7WII9dxewkHLltfTLVppoUApHV0118a4RZRI9FLwA==", + "dev": true, + "dependencies": { + "css": "^2.0.0" + } + }, + "node_modules/css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dash-ast": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", + "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==", + "dev": true + }, + "node_modules/date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha512-AsElvov3LoNB7tf5k37H2jYSB+ZZPMT5sG2QjJCcdlV5chIv6htBUBUui2IKRjgtKAKtCBN7Zbwa+MtwLjSeNw==", + "dev": true + }, + "node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + } + }, + "node_modules/defaults/node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==", + "dev": true + }, + "node_modules/deps-sort": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz", + "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==", + "dev": true, + "dependencies": { + "JSONStream": "^1.0.3", + "shasum-object": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" + }, + "bin": { + "deps-sort": "bin/cmd.js" + } + }, + "node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", + "dev": true, + "dependencies": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + }, + "bin": { + "detective": "bin/detective.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/doctypes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", + "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==", + "dev": true + }, + "node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/dom-serializer/node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true, + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "node_modules/domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha512-q9bUwjfp7Eif8jWxxxPSykdRZAb6GkguBGSgvvCrhI9wB71W2K/Kvv4E61CF/mcCfnVJDeDWx/Vb/uAqbDj6UQ==", + "dev": true, + "dependencies": { + "domelementtype": "1" + } + }, + "node_modules/domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", + "dev": true, + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ==", + "dev": true + }, + "node_modules/es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.0.tgz", + "integrity": "sha512-pBG/XOn0MsJcKcTRLr27S5HpzQo4kLr+HjLQIyK4EiCsijDl/TB+h5uEuJU6bQ8Edvwz1XWOjpaP2qgnXGpTcA==", + "dev": true, + "dependencies": { + "@eslint/eslintrc": "^1.3.1", + "@humanwhocodes/config-array": "^0.10.4", + "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", + "@humanwhocodes/module-importer": "^1.0.1", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "globby": "^11.1.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-standard": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz", + "integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peerDependencies": { + "eslint": "^8.0.1", + "eslint-plugin-import": "^2.25.2", + "eslint-plugin-n": "^15.0.0", + "eslint-plugin-promise": "^6.0.0" + } + }, + "node_modules/eslint-config-standard-with-typescript": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-22.0.0.tgz", + "integrity": "sha512-VA36U7UlFpwULvkdnh6MQj5GAV2Q+tT68ALLAwJP0ZuNXU2m0wX07uxX4qyLRdHgSzH4QJ73CveKBuSOYvh7vQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint-config-standard": "17.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^5.0.0", + "eslint": "^8.0.1", + "eslint-plugin-import": "^2.25.2", + "eslint-plugin-n": "^15.0.0", + "eslint-plugin-promise": "^6.0.0", + "typescript": "*" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "resolve": "^1.20.0" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/eslint-module-utils": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", + "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/eslint-plugin-es": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", + "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", + "dev": true, + "dependencies": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/eslint-plugin-es/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", + "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.3", + "has": "^1.0.3", + "is-core-module": "^2.8.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.5", + "resolve": "^1.22.0", + "tsconfig-paths": "^3.14.1" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-n": { + "version": "15.2.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.2.5.tgz", + "integrity": "sha512-8+BYsqiyZfpu6NXmdLOXVUfk8IocpCjpd8nMRRH0A9ulrcemhb2VI9RSJMEy5udx++A/YcVPD11zT8hpFq368g==", + "dev": true, + "dependencies": { + "builtins": "^5.0.1", + "eslint-plugin-es": "^4.1.0", + "eslint-utils": "^3.0.0", + "ignore": "^5.1.1", + "is-core-module": "^2.10.0", + "minimatch": "^3.1.2", + "resolve": "^1.22.1", + "semver": "^7.3.7" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-n/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-promise": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.0.1.tgz", + "integrity": "sha512-uM4Tgo5u3UWQiroOyDEsYcVMOo7re3zmno0IZmB5auxoaQNIceAbXEkSt8RNrKtaYehARHG06pYK6K1JhtP0Zw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", + "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-assigned-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==", + "dev": true + }, + "node_modules/get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globals": { + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-base/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha512-eVcrzgbR4tim7c7soKQKtxa/kQM4TzjnlU83rcZ9bHU6t31ehfV7SktN6McWgwPWg+JYMA/O3qpGxBvFq1z2Jg==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q==", + "dev": true, + "dependencies": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + } + }, + "node_modules/htmlparser2/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true + }, + "node_modules/htmlparser2/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/htmlparser2/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "dev": true + }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", + "dev": true + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immutable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", + "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha512-0mVWSSbNDvedDWIN4wxLsdPM4a7cIPcpyMxj3QZ406QRwQ6ePGB1YIHxVPjqpcUGbWQ5C+nHTwGNWAGvt7ggVA==", + "dev": true, + "dependencies": { + "source-map": "~0.5.3" + } + }, + "node_modules/inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/inquirer/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/insert-module-globals": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz", + "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==", + "dev": true, + "dependencies": { + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "JSONStream": "^1.0.3", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + }, + "bin": { + "insert-module-globals": "bin/cmd.js" + } + }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-expression": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz", + "integrity": "sha512-vyMeQMq+AiH5uUnoBfMTwf18tO3bM6k1QXBE9D6ueAAquEfCZe3AJPtud9g6qS0+4X8xA7ndpZiDyeb2l2qOBw==", + "dev": true, + "dependencies": { + "acorn": "~4.0.2", + "object-assign": "^4.0.1" + } + }, + "node_modules/is-expression/node_modules/acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", + "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/js-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", + "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jshint": { + "version": "2.13.4", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.4.tgz", + "integrity": "sha512-HO3bosL84b2qWqI0q+kpT/OpRJwo0R4ivgmxaO848+bo10rc50SkPnrtwSFXttW0ym4np8jbJvLwk5NziB7jIw==", + "dev": true, + "dependencies": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.21", + "minimatch": "~3.0.2", + "strip-json-comments": "1.0.x" + }, + "bin": { + "jshint": "bin/jshint" + } + }, + "node_modules/jshint/node_modules/console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha512-duS7VP5pvfsNLDvL1O4VOEbw37AI3A4ZUQYemvDlnpGrNu9tprR7BYWpDYwC0Xia0Zxz5ZupdiIrUp0GH1aXfg==", + "dev": true, + "dependencies": { + "date-now": "^0.1.4" + } + }, + "node_modules/jshint/node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jstransformer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", + "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==", + "dev": true, + "dependencies": { + "is-promise": "^2.0.0", + "promise": "^7.0.1" + } + }, + "node_modules/jstransformer-escape-html": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jstransformer-escape-html/-/jstransformer-escape-html-1.1.0.tgz", + "integrity": "sha512-G5wRIKQD9RoOsqvuK7yyIje/ZojoZlq3lt4IPnK2tcxYK4VKNZ1TNitrvCExkAGe/RO0sEU+bscyFUyvcYKiNg==", + "dev": true, + "dependencies": { + "escape-html": "^1.0.3" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jstransformer-scss": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jstransformer-scss/-/jstransformer-scss-2.0.0.tgz", + "integrity": "sha512-dFavLkKkc1J0KT0UpbUue11qGlv0+pcS5AWvH5LZlxq70bIuXJ+tGvVC9jEL2oI3p4kvNvlULuzFeo/qrmnvnQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.2", + "sass": "~1.53.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jstransformer-stylus": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/jstransformer-stylus/-/jstransformer-stylus-1.5.0.tgz", + "integrity": "sha512-j3A5dryGjFECzNHO0F4hmosOwXobLpEb+mo2+q2mywctzm1UnIISzvBUvq9zPpvx9vDEh9ln8SraEwrFnke+tA==", + "dev": true, + "dependencies": { + "clone": "^2.0.0", + "stylus": "~0.54.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/labeled-stream-splicer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", + "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "stream-splicer": "^2.0.0" + } + }, + "node_modules/lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha512-eDn9kqrAmVUC1wmZvlQ6Uhde44n+tXpqPrN8olQJbttgh0oKclk+SF54P47VEGE9CEiMeRwAP8BaM7UHvBkz2A==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "node_modules/module-deps": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz", + "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==", + "dev": true, + "dependencies": { + "browser-resolve": "^2.0.0", + "cached-path-relative": "^1.0.2", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.2.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "JSONStream": "^1.0.3", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + }, + "bin": { + "module-deps": "bin/cmd.js" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", + "dev": true + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha512-mXKF3xkoUt5td2DoxpLmtOmZvko9VfFpwRwkKDHSNvgmpLAeBo18YDhcPbBzJq+QLCHMbGOfzia2cX4U+0v9Mg==", + "dev": true, + "dependencies": { + "path-platform": "~0.11.15" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha512-Y30dB6rab1A/nfEKsZxmr01nUotHX0c/ZiIAsCTatEe1CmS5Pm5He7fZ195bPT7RdquoaL8lLxFCMQi/bS7IJg==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dev": true, + "dependencies": { + "asap": "~2.0.3" + } + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/pug": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.4.tgz", + "integrity": "sha512-XhoaDlvi6NIzL49nu094R2NA6P37ijtgMDuWE+ofekDChvfKnzFal60bhSdiy8y2PBO6fmz3oMEIcfpBVRUdvw==", + "dev": true, + "dependencies": { + "pug-code-gen": "^2.0.2", + "pug-filters": "^3.1.1", + "pug-lexer": "^4.1.0", + "pug-linker": "^3.0.6", + "pug-load": "^2.0.12", + "pug-parser": "^5.0.1", + "pug-runtime": "^2.0.5", + "pug-strip-comments": "^1.0.4" + } + }, + "node_modules/pug-attrs": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.4.tgz", + "integrity": "sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ==", + "dev": true, + "dependencies": { + "constantinople": "^3.0.1", + "js-stringify": "^1.0.1", + "pug-runtime": "^2.0.5" + } + }, + "node_modules/pug-cli": { + "version": "1.0.0-alpha6", + "resolved": "https://registry.npmjs.org/pug-cli/-/pug-cli-1.0.0-alpha6.tgz", + "integrity": "sha512-ogaf7h4cT174NFSHNqAMdrZpGFCZSvsht41IYZZgP7ERZ1OxSc5fmPpojo1w9UntVreeChQP3BJ5r+Fey0a9zg==", + "dev": true, + "dependencies": { + "chalk": "^1.0.0", + "commander": "^2.8.1", + "mkdirp": "^0.5.1", + "pug": "^2.0.0-alpha7" + }, + "bin": { + "pug": "index.js" + } + }, + "node_modules/pug-code-gen": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.3.tgz", + "integrity": "sha512-r9sezXdDuZJfW9J91TN/2LFbiqDhmltTFmGpHTsGdrNGp3p4SxAjjXEfnuK2e4ywYsRIVP0NeLbSAMHUcaX1EA==", + "dev": true, + "dependencies": { + "constantinople": "^3.1.2", + "doctypes": "^1.1.0", + "js-stringify": "^1.0.1", + "pug-attrs": "^2.0.4", + "pug-error": "^1.3.3", + "pug-runtime": "^2.0.5", + "void-elements": "^2.0.1", + "with": "^5.0.0" + } + }, + "node_modules/pug-error": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.3.tgz", + "integrity": "sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ==", + "dev": true + }, + "node_modules/pug-filters": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-3.1.1.tgz", + "integrity": "sha512-lFfjNyGEyVWC4BwX0WyvkoWLapI5xHSM3xZJFUhx4JM4XyyRdO8Aucc6pCygnqV2uSgJFaJWW3Ft1wCWSoQkQg==", + "dev": true, + "dependencies": { + "clean-css": "^4.1.11", + "constantinople": "^3.0.1", + "jstransformer": "1.0.0", + "pug-error": "^1.3.3", + "pug-walk": "^1.1.8", + "resolve": "^1.1.6", + "uglify-js": "^2.6.1" + } + }, + "node_modules/pug-lexer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-4.1.0.tgz", + "integrity": "sha512-i55yzEBtjm0mlplW4LoANq7k3S8gDdfC6+LThGEvsK4FuobcKfDAwt6V4jKPH9RtiE3a2Akfg5UpafZ1OksaPA==", + "dev": true, + "dependencies": { + "character-parser": "^2.1.1", + "is-expression": "^3.0.0", + "pug-error": "^1.3.3" + } + }, + "node_modules/pug-linker": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.6.tgz", + "integrity": "sha512-bagfuHttfQOpANGy1Y6NJ+0mNb7dD2MswFG2ZKj22s8g0wVsojpRlqveEQHmgXXcfROB2RT6oqbPYr9EN2ZWzg==", + "dev": true, + "dependencies": { + "pug-error": "^1.3.3", + "pug-walk": "^1.1.8" + } + }, + "node_modules/pug-load": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.12.tgz", + "integrity": "sha512-UqpgGpyyXRYgJs/X60sE6SIf8UBsmcHYKNaOccyVLEuT6OPBIMo6xMPhoJnqtB3Q3BbO4Z3Bjz5qDsUWh4rXsg==", + "dev": true, + "dependencies": { + "object-assign": "^4.1.0", + "pug-walk": "^1.1.8" + } + }, + "node_modules/pug-parser": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-5.0.1.tgz", + "integrity": "sha512-nGHqK+w07p5/PsPIyzkTQfzlYfuqoiGjaoqHv1LjOv2ZLXmGX1O+4Vcvps+P4LhxZ3drYSljjq4b+Naid126wA==", + "dev": true, + "dependencies": { + "pug-error": "^1.3.3", + "token-stream": "0.0.1" + } + }, + "node_modules/pug-runtime": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.5.tgz", + "integrity": "sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw==", + "dev": true + }, + "node_modules/pug-strip-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.4.tgz", + "integrity": "sha512-i5j/9CS4yFhSxHp5iKPHwigaig/VV9g+FgReLJWWHEHbvKsbqL0oP/K5ubuLco6Wu3Kan5p7u7qk8A4oLLh6vw==", + "dev": true, + "dependencies": { + "pug-error": "^1.3.3" + } + }, + "node_modules/pug-walk": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.8.tgz", + "integrity": "sha512-GMu3M5nUL3fju4/egXwZO0XLi6fW/K3T3VTgFQ14GxNi8btlxgT5qZL//JwZFm/2Fa64J/PNS8AZeys3wiMkVA==", + "dev": true + }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha512-3ALe0bjBVZtkdWKIcThYpQCLbBMd/+Tbh2CDSrAIDO3UsZ4Xs+tnyjv2MjCOMMgBG+AsUOeuP1cgtY1INISc8w==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/readable-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", + "dev": true + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==", + "dev": true, + "dependencies": { + "align-text": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", + "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/rxjs/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sass": { + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.53.0.tgz", + "integrity": "sha512-zb/oMirbKhUgRQ0/GFz8TSAwRq2IlR29vOUJZOx0l8sV+CkHUfHa4u5nqrG+1VceZp7Jfj59SVW9ogdhTvJDcQ==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shasum-object": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz", + "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==", + "dev": true, + "dependencies": { + "fast-safe-stringify": "^2.0.7" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", + "dev": true + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated", + "dev": true + }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/stream-browserify/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", + "dev": true, + "dependencies": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "dev": true, + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + } + }, + "node_modules/stream-http/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-splicer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", + "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha512-AOPG8EBc5wAikaG1/7uFCNFJwnKOuQwFTpYBdTW6OvWHeZBQBrAA/amefHGrEiOnCPcLFZK6FUPtWVKpQVIRgg==", + "dev": true, + "bin": { + "strip-json-comments": "cli.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/stylus": { + "version": "0.54.8", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.8.tgz", + "integrity": "sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg==", + "dev": true, + "dependencies": { + "css-parse": "~2.0.0", + "debug": "~3.1.0", + "glob": "^7.1.6", + "mkdirp": "~1.0.4", + "safer-buffer": "^2.1.2", + "sax": "~1.2.4", + "semver": "^6.3.0", + "source-map": "^0.7.3" + }, + "bin": { + "stylus": "bin/stylus" + }, + "engines": { + "node": "*" + } + }, + "node_modules/stylus/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/stylus/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stylus/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha512-RIrIdRY0X1xojthNcVtgT9sjpOGagEUKpZdgBUi054OEPFo282yg+zE+t1Rj3+RqKq2xStL7uUHhY+AjbC4BXg==", + "dev": true, + "dependencies": { + "minimist": "^1.1.0" + } + }, + "node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dev": true, + "dependencies": { + "acorn-node": "^1.2.0" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha512-PIxwAupJZiYU4JmVZYwXp9FKsHMXb5h0ZEFyuXTAn8WLHOlcij+FEcbrvDsom1o5dr1YggEtFbECvGCW2sT53Q==", + "dev": true, + "dependencies": { + "process": "~0.11.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/token-stream": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz", + "integrity": "sha512-nfjOAu/zAWmX9tgwi5NRp7O7zTDUD1miHiB40klUnAh9qnL1iXdgzcz/i5dMaL5jahcBAaSfmNOBBJBLJW8TEg==", + "dev": true + }, + "node_modules/tsconfig-paths": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", + "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true + }, + "node_modules/typescript": { + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", + "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==", + "dev": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w==", + "dev": true, + "dependencies": { + "source-map": "~0.5.1", + "yargs": "~3.10.0" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + }, + "optionalDependencies": { + "uglify-to-browserify": "~1.0.0" + } + }, + "node_modules/uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==", + "dev": true, + "optional": true + }, + "node_modules/umd": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", + "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", + "dev": true, + "bin": { + "umd": "bin/cli.js" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undeclared-identifiers": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", + "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", + "dev": true, + "dependencies": { + "acorn-node": "^1.3.0", + "dash-ast": "^1.0.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" + }, + "bin": { + "undeclared-identifiers": "bin.js" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", + "deprecated": "Please see https://github.com/lydell/urix#deprecated", + "dev": true + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", + "dev": true, + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", + "dev": true + }, + "node_modules/util": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", + "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "node_modules/void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", + "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/with": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz", + "integrity": "sha512-uAnSsFGfSpF6DNhBXStvlZILfHJfJu4eUkfbRGk94kGO1Ta7bg6FwfvoOhhyHAJuFbCw+0xk4uJ3u57jLvlCJg==", + "dev": true, + "dependencies": { + "acorn": "^3.1.0", + "acorn-globals": "^3.0.0" + } + }, + "node_modules/with/node_modules/acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha512-OLUyIIZ7mF5oaAUT1w0TFqQS81q3saT46x8t7ukpPjMNk+nbs4ZHhs7ToV8EWnLYLepjETXd4XaCE4uxkMeqUw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A==", + "dev": true, + "dependencies": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } - ] }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" - }, - "node_modules/browser-pack": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", - "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", - "dependencies": { - "combine-source-map": "~0.8.0", - "defined": "^1.0.0", - "JSONStream": "^1.0.3", - "safe-buffer": "^5.1.1", - "through2": "^2.0.0", - "umd": "^3.0.0" - }, - "bin": { - "browser-pack": "bin/cmd.js" - } - }, - "node_modules/browser-resolve": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", - "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", - "dependencies": { - "resolve": "^1.17.0" - } - }, - "node_modules/browserify": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz", - "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==", - "dependencies": { - "assert": "^1.4.0", - "browser-pack": "^6.0.1", - "browser-resolve": "^2.0.0", - "browserify-zlib": "~0.2.0", - "buffer": "~5.2.1", - "cached-path-relative": "^1.0.0", - "concat-stream": "^1.6.0", - "console-browserify": "^1.1.0", - "constants-browserify": "~1.0.0", - "crypto-browserify": "^3.0.0", - "defined": "^1.0.0", - "deps-sort": "^2.0.1", - "domain-browser": "^1.2.0", - "duplexer2": "~0.1.2", - "events": "^3.0.0", - "glob": "^7.1.0", - "has": "^1.0.0", - "htmlescape": "^1.1.0", - "https-browserify": "^1.0.0", - "inherits": "~2.0.1", - "insert-module-globals": "^7.2.1", - "JSONStream": "^1.0.3", - "labeled-stream-splicer": "^2.0.0", - "mkdirp-classic": "^0.5.2", - "module-deps": "^6.2.3", - "os-browserify": "~0.3.0", - "parents": "^1.0.1", - "path-browserify": "^1.0.0", - "process": "~0.11.0", - "punycode": "^1.3.2", - "querystring-es3": "~0.2.0", - "read-only-stream": "^2.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.1.4", - "shasum-object": "^1.0.0", - "shell-quote": "^1.6.1", - "stream-browserify": "^3.0.0", - "stream-http": "^3.0.0", - "string_decoder": "^1.1.1", - "subarg": "^1.0.0", - "syntax-error": "^1.1.1", - "through2": "^2.0.0", - "timers-browserify": "^1.0.1", - "tty-browserify": "0.0.1", - "url": "~0.11.0", - "util": "~0.12.0", - "vm-browserify": "^1.0.0", - "xtend": "^4.0.0" - }, - "bin": { - "browserify": "bin/cmd.js" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dependencies": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dependencies": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "node_modules/browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dependencies": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", - "dependencies": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" - } - }, - "node_modules/browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "dependencies": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - } - }, - "node_modules/browserify-sign/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dependencies": { - "pako": "~1.0.5" - } - }, - "node_modules/buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" - }, - "node_modules/builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==" - }, - "node_modules/cached-path-relative": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.1.0.tgz", - "integrity": "sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==" - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==", - "dependencies": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/character-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", - "integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==", - "dependencies": { - "is-regex": "^1.0.3" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/clean-css": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", - "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/clean-css/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", - "integrity": "sha512-41U72MB56TfUMGndAKK8vJ78eooOD4Z5NOL4xEfjc0c23s+6EYKXlXsmACBVclLP1yOfWCgEganVzddVrSNoTg==", - "dependencies": { - "exit": "0.1.2", - "glob": "^7.1.1" - }, - "engines": { - "node": ">=0.2.5" - } - }, - "node_modules/cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==", - "dependencies": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } - }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/combine-source-map": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", - "integrity": "sha512-UlxQ9Vw0b/Bt/KYwCFqdEwsQ1eL8d1gibiFb7lxQJFdvTgc2hIZi6ugsg+kyhzhPV+QEpUiEIwInIAIrgoEkrg==", - "dependencies": { - "convert-source-map": "~1.1.0", - "inline-source-map": "~0.6.0", - "lodash.memoize": "~3.0.3", - "source-map": "~0.5.3" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" - }, - "node_modules/constantinople": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.2.tgz", - "integrity": "sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw==", - "dependencies": { - "@types/babel-types": "^7.0.0", - "@types/babylon": "^6.16.2", - "babel-types": "^6.26.0", - "babylon": "^6.18.0" - } - }, - "node_modules/constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==" - }, - "node_modules/convert-source-map": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", - "integrity": "sha512-Y8L5rp6jo+g9VEPgvqNfEopjTR4OTYct8lXlS8iVQdmnjDvbdbzYe9rjtFCB9egC86JoNCU61WRY+ScjkZpnIg==" - }, - "node_modules/core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "hasInstallScript": true - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dependencies": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - } - }, - "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - }, - "engines": { - "node": "*" - } - }, - "node_modules/css": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", - "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", - "dependencies": { - "inherits": "^2.0.3", - "source-map": "^0.6.1", - "source-map-resolve": "^0.5.2", - "urix": "^0.1.0" - } - }, - "node_modules/css-parse": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", - "integrity": "sha512-UNIFik2RgSbiTwIW1IsFwXWn6vs+bYdq83LKTSOsx7NJR7WII9dxewkHLltfTLVppoUApHV0118a4RZRI9FLwA==", - "dependencies": { - "css": "^2.0.0" - } - }, - "node_modules/css/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dash-ast": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", - "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==" - }, - "node_modules/date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha512-AsElvov3LoNB7tf5k37H2jYSB+ZZPMT5sG2QjJCcdlV5chIv6htBUBUui2IKRjgtKAKtCBN7Zbwa+MtwLjSeNw==" - }, - "node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==" - }, - "node_modules/deps-sort": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz", - "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==", - "dependencies": { - "JSONStream": "^1.0.3", - "shasum-object": "^1.0.0", - "subarg": "^1.0.0", - "through2": "^2.0.0" - }, - "bin": { - "deps-sort": "bin/cmd.js" - } - }, - "node_modules/des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "dependencies": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/detective": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", - "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", - "dependencies": { - "acorn-node": "^1.8.2", - "defined": "^1.0.0", - "minimist": "^1.2.6" - }, - "bin": { - "detective": "bin/detective.js" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dependencies": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/doctypes": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", - "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==" - }, - "node_modules/dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "dependencies": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - } - }, - "node_modules/dom-serializer/node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "engines": { - "node": ">=0.4", - "npm": ">=1.2" - } - }, - "node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "node_modules/domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha512-q9bUwjfp7Eif8jWxxxPSykdRZAb6GkguBGSgvvCrhI9wB71W2K/Kvv4E61CF/mcCfnVJDeDWx/Vb/uAqbDj6UQ==", - "dependencies": { - "domelementtype": "1" - } - }, - "node_modules/domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", - "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ==" - }, - "node_modules/es-abstract": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", - "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "regexp.prototype.flags": "^1.4.3", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-assigned-identifiers": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", - "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==" - }, - "node_modules/get-intrinsic": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", - "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash-base/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/htmlescape": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", - "integrity": "sha512-eVcrzgbR4tim7c7soKQKtxa/kQM4TzjnlU83rcZ9bHU6t31ehfV7SktN6McWgwPWg+JYMA/O3qpGxBvFq1z2Jg==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q==", - "dependencies": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" - } - }, - "node_modules/htmlparser2/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, - "node_modules/htmlparser2/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/htmlparser2/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" - }, - "node_modules/https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==" - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" + "dependencies": { + "@eslint/eslintrc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.1.tgz", + "integrity": "sha512-OhSY22oQQdw3zgPOOwdoj01l/Dzl1Z+xyUP33tkSN+aqyEhymJCcPHyXt+ylW8FSe0TfRC2VG+ROQOapD0aZSQ==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "@humanwhocodes/config-array": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", + "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/immutable": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", - "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==" - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/inline-source-map": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", - "integrity": "sha512-0mVWSSbNDvedDWIN4wxLsdPM4a7cIPcpyMxj3QZ406QRwQ6ePGB1YIHxVPjqpcUGbWQ5C+nHTwGNWAGvt7ggVA==", - "dependencies": { - "source-map": "~0.5.3" - } - }, - "node_modules/insert-module-globals": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz", - "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==", - "dependencies": { - "acorn-node": "^1.5.2", - "combine-source-map": "^0.8.0", - "concat-stream": "^1.6.1", - "is-buffer": "^1.1.0", - "JSONStream": "^1.0.3", - "path-is-absolute": "^1.0.1", - "process": "~0.11.0", - "through2": "^2.0.0", - "undeclared-identifiers": "^1.1.2", - "xtend": "^4.0.0" - }, - "bin": { - "insert-module-globals": "bin/cmd.js" - } - }, - "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "node_modules/is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", - "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-expression": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz", - "integrity": "sha512-vyMeQMq+AiH5uUnoBfMTwf18tO3bM6k1QXBE9D6ueAAquEfCZe3AJPtud9g6qS0+4X8xA7ndpZiDyeb2l2qOBw==", - "dependencies": { - "acorn": "~4.0.2", - "object-assign": "^4.0.1" - } - }, - "node_modules/is-expression/node_modules/acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", - "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", - "for-each": "^0.3.3", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/js-stringify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", - "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==" - }, - "node_modules/jshint": { - "version": "2.13.4", - "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.4.tgz", - "integrity": "sha512-HO3bosL84b2qWqI0q+kpT/OpRJwo0R4ivgmxaO848+bo10rc50SkPnrtwSFXttW0ym4np8jbJvLwk5NziB7jIw==", - "dependencies": { - "cli": "~1.0.0", - "console-browserify": "1.1.x", - "exit": "0.1.x", - "htmlparser2": "3.8.x", - "lodash": "~4.17.21", - "minimatch": "~3.0.2", - "strip-json-comments": "1.0.x" - }, - "bin": { - "jshint": "bin/jshint" - } - }, - "node_modules/jshint/node_modules/console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha512-duS7VP5pvfsNLDvL1O4VOEbw37AI3A4ZUQYemvDlnpGrNu9tprR7BYWpDYwC0Xia0Zxz5ZupdiIrUp0GH1aXfg==", - "dependencies": { - "date-now": "^0.1.4" - } - }, - "node_modules/jshint/node_modules/minimatch": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "engines": [ - "node >= 0.2.0" - ] - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/jstransformer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", - "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==", - "dependencies": { - "is-promise": "^2.0.0", - "promise": "^7.0.1" - } - }, - "node_modules/jstransformer-escape-html": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jstransformer-escape-html/-/jstransformer-escape-html-1.1.0.tgz", - "integrity": "sha512-G5wRIKQD9RoOsqvuK7yyIje/ZojoZlq3lt4IPnK2tcxYK4VKNZ1TNitrvCExkAGe/RO0sEU+bscyFUyvcYKiNg==", - "dependencies": { - "escape-html": "^1.0.3" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jstransformer-scss": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jstransformer-scss/-/jstransformer-scss-2.0.0.tgz", - "integrity": "sha512-dFavLkKkc1J0KT0UpbUue11qGlv0+pcS5AWvH5LZlxq70bIuXJ+tGvVC9jEL2oI3p4kvNvlULuzFeo/qrmnvnQ==", - "dependencies": { - "extend-shallow": "^3.0.2", - "sass": "~1.53.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jstransformer-stylus": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/jstransformer-stylus/-/jstransformer-stylus-1.5.0.tgz", - "integrity": "sha512-j3A5dryGjFECzNHO0F4hmosOwXobLpEb+mo2+q2mywctzm1UnIISzvBUvq9zPpvx9vDEh9ln8SraEwrFnke+tA==", - "dependencies": { - "clone": "^2.0.0", - "stylus": "~0.54.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/labeled-stream-splicer": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", - "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", - "dependencies": { - "inherits": "^2.0.1", - "stream-splicer": "^2.0.0" - } - }, - "node_modules/lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.memoize": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", - "integrity": "sha512-eDn9kqrAmVUC1wmZvlQ6Uhde44n+tXpqPrN8olQJbttgh0oKclk+SF54P47VEGE9CEiMeRwAP8BaM7UHvBkz2A==" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "node_modules/lodash.omit": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", - "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==" - }, - "node_modules/longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "bin": { - "miller-rabin": "bin/miller-rabin" - } - }, - "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" - }, - "node_modules/module-deps": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz", - "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==", - "dependencies": { - "browser-resolve": "^2.0.0", - "cached-path-relative": "^1.0.2", - "concat-stream": "~1.6.0", - "defined": "^1.0.0", - "detective": "^5.2.0", - "duplexer2": "^0.1.2", - "inherits": "^2.0.1", - "JSONStream": "^1.0.3", - "parents": "^1.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.4.0", - "stream-combiner2": "^1.1.1", - "subarg": "^1.0.0", - "through2": "^2.0.0", - "xtend": "^4.0.0" - }, - "bin": { - "module-deps": "bin/cmd.js" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==" - }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "node_modules/parents": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", - "integrity": "sha512-mXKF3xkoUt5td2DoxpLmtOmZvko9VfFpwRwkKDHSNvgmpLAeBo18YDhcPbBzJq+QLCHMbGOfzia2cX4U+0v9Mg==", - "dependencies": { - "path-platform": "~0.11.15" - } - }, - "node_modules/parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dependencies": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/path-platform": { - "version": "0.11.15", - "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", - "integrity": "sha512-Y30dB6rab1A/nfEKsZxmr01nUotHX0c/ZiIAsCTatEe1CmS5Pm5He7fZ195bPT7RdquoaL8lLxFCMQi/bS7IJg==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "dependencies": { - "asap": "~2.0.3" - } - }, - "node_modules/public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/pug": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.4.tgz", - "integrity": "sha512-XhoaDlvi6NIzL49nu094R2NA6P37ijtgMDuWE+ofekDChvfKnzFal60bhSdiy8y2PBO6fmz3oMEIcfpBVRUdvw==", - "dependencies": { - "pug-code-gen": "^2.0.2", - "pug-filters": "^3.1.1", - "pug-lexer": "^4.1.0", - "pug-linker": "^3.0.6", - "pug-load": "^2.0.12", - "pug-parser": "^5.0.1", - "pug-runtime": "^2.0.5", - "pug-strip-comments": "^1.0.4" - } - }, - "node_modules/pug-attrs": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.4.tgz", - "integrity": "sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ==", - "dependencies": { - "constantinople": "^3.0.1", - "js-stringify": "^1.0.1", - "pug-runtime": "^2.0.5" - } - }, - "node_modules/pug-cli": { - "version": "1.0.0-alpha6", - "resolved": "https://registry.npmjs.org/pug-cli/-/pug-cli-1.0.0-alpha6.tgz", - "integrity": "sha512-ogaf7h4cT174NFSHNqAMdrZpGFCZSvsht41IYZZgP7ERZ1OxSc5fmPpojo1w9UntVreeChQP3BJ5r+Fey0a9zg==", - "dependencies": { - "chalk": "^1.0.0", - "commander": "^2.8.1", - "mkdirp": "^0.5.1", - "pug": "^2.0.0-alpha7" - }, - "bin": { - "pug": "index.js" - } - }, - "node_modules/pug-code-gen": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.3.tgz", - "integrity": "sha512-r9sezXdDuZJfW9J91TN/2LFbiqDhmltTFmGpHTsGdrNGp3p4SxAjjXEfnuK2e4ywYsRIVP0NeLbSAMHUcaX1EA==", - "dependencies": { - "constantinople": "^3.1.2", - "doctypes": "^1.1.0", - "js-stringify": "^1.0.1", - "pug-attrs": "^2.0.4", - "pug-error": "^1.3.3", - "pug-runtime": "^2.0.5", - "void-elements": "^2.0.1", - "with": "^5.0.0" - } - }, - "node_modules/pug-error": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.3.tgz", - "integrity": "sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ==" - }, - "node_modules/pug-filters": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-3.1.1.tgz", - "integrity": "sha512-lFfjNyGEyVWC4BwX0WyvkoWLapI5xHSM3xZJFUhx4JM4XyyRdO8Aucc6pCygnqV2uSgJFaJWW3Ft1wCWSoQkQg==", - "dependencies": { - "clean-css": "^4.1.11", - "constantinople": "^3.0.1", - "jstransformer": "1.0.0", - "pug-error": "^1.3.3", - "pug-walk": "^1.1.8", - "resolve": "^1.1.6", - "uglify-js": "^2.6.1" - } - }, - "node_modules/pug-lexer": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-4.1.0.tgz", - "integrity": "sha512-i55yzEBtjm0mlplW4LoANq7k3S8gDdfC6+LThGEvsK4FuobcKfDAwt6V4jKPH9RtiE3a2Akfg5UpafZ1OksaPA==", - "dependencies": { - "character-parser": "^2.1.1", - "is-expression": "^3.0.0", - "pug-error": "^1.3.3" - } - }, - "node_modules/pug-linker": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.6.tgz", - "integrity": "sha512-bagfuHttfQOpANGy1Y6NJ+0mNb7dD2MswFG2ZKj22s8g0wVsojpRlqveEQHmgXXcfROB2RT6oqbPYr9EN2ZWzg==", - "dependencies": { - "pug-error": "^1.3.3", - "pug-walk": "^1.1.8" - } - }, - "node_modules/pug-load": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.12.tgz", - "integrity": "sha512-UqpgGpyyXRYgJs/X60sE6SIf8UBsmcHYKNaOccyVLEuT6OPBIMo6xMPhoJnqtB3Q3BbO4Z3Bjz5qDsUWh4rXsg==", - "dependencies": { - "object-assign": "^4.1.0", - "pug-walk": "^1.1.8" - } - }, - "node_modules/pug-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-5.0.1.tgz", - "integrity": "sha512-nGHqK+w07p5/PsPIyzkTQfzlYfuqoiGjaoqHv1LjOv2ZLXmGX1O+4Vcvps+P4LhxZ3drYSljjq4b+Naid126wA==", - "dependencies": { - "pug-error": "^1.3.3", - "token-stream": "0.0.1" - } - }, - "node_modules/pug-runtime": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.5.tgz", - "integrity": "sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw==" - }, - "node_modules/pug-strip-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.4.tgz", - "integrity": "sha512-i5j/9CS4yFhSxHp5iKPHwigaig/VV9g+FgReLJWWHEHbvKsbqL0oP/K5ubuLco6Wu3Kan5p7u7qk8A4oLLh6vw==", - "dependencies": { - "pug-error": "^1.3.3" - } - }, - "node_modules/pug-walk": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.8.tgz", - "integrity": "sha512-GMu3M5nUL3fju4/egXwZO0XLi6fW/K3T3VTgFQ14GxNi8btlxgT5qZL//JwZFm/2Fa64J/PNS8AZeys3wiMkVA==" - }, - "node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "node_modules/read-only-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", - "integrity": "sha512-3ALe0bjBVZtkdWKIcThYpQCLbBMd/+Tbh2CDSrAIDO3UsZ4Xs+tnyjv2MjCOMMgBG+AsUOeuP1cgtY1INISc8w==", - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/readable-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" - }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", - "deprecated": "https://github.com/lydell/resolve-url#deprecated" - }, - "node_modules/right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==", - "dependencies": { - "align-text": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" + "@humanwhocodes/gitignore-to-minimatch": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", + "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", + "dev": true }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sass": { - "version": "1.53.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.53.0.tgz", - "integrity": "sha512-zb/oMirbKhUgRQ0/GFz8TSAwRq2IlR29vOUJZOx0l8sV+CkHUfHa4u5nqrG+1VceZp7Jfj59SVW9ogdhTvJDcQ==", - "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/shasum-object": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz", - "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==", - "dependencies": { - "fast-safe-stringify": "^2.0.7" - } - }, - "node_modules/shell-quote": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", - "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@types/babel-types": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.11.tgz", + "integrity": "sha512-pkPtJUUY+Vwv6B1inAz55rQvivClHJxc9aVEPPmaq2cbyeMLCiDpbKpcKyX4LAwpNGi+SHBv0tHv6+0gXv0P2A==", + "dev": true + }, + "@types/babylon": { + "version": "6.16.6", + "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.6.tgz", + "integrity": "sha512-G4yqdVlhr6YhzLXFKy5F7HtRBU8Y23+iWy7UKthMq/OSQnL1hbsoeXESQ2LY8zEDlknipDG3nRGhUC9tkwvy/w==", + "dev": true, + "requires": { + "@types/babel-types": "*" + } + }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.36.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.36.1.tgz", + "integrity": "sha512-iC40UK8q1tMepSDwiLbTbMXKDxzNy+4TfPWgIL661Ym0sD42vRcQU93IsZIrmi+x292DBr60UI/gSwfdVYexCA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.36.1", + "@typescript-eslint/type-utils": "5.36.1", + "@typescript-eslint/utils": "5.36.1", + "debug": "^4.3.4", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.2.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "5.36.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.36.1.tgz", + "integrity": "sha512-/IsgNGOkBi7CuDfUbwt1eOqUXF9WGVBW9dwEe1pi+L32XrTsZIgmDFIi2RxjzsvB/8i+MIf5JIoTEH8LOZ368A==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.36.1", + "@typescript-eslint/types": "5.36.1", + "@typescript-eslint/typescript-estree": "5.36.1", + "debug": "^4.3.4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.36.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.36.1.tgz", + "integrity": "sha512-pGC2SH3/tXdu9IH3ItoqciD3f3RRGCh7hb9zPdN2Drsr341zgd6VbhP5OHQO/reUqihNltfPpMpTNihFMarP2w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.36.1", + "@typescript-eslint/visitor-keys": "5.36.1" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.36.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.36.1.tgz", + "integrity": "sha512-xfZhfmoQT6m3lmlqDvDzv9TiCYdw22cdj06xY0obSznBsT///GK5IEZQdGliXpAOaRL34o8phEvXzEo/VJx13Q==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "5.36.1", + "@typescript-eslint/utils": "5.36.1", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@typescript-eslint/types": { + "version": "5.36.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.36.1.tgz", + "integrity": "sha512-jd93ShpsIk1KgBTx9E+hCSEuLCUFwi9V/urhjOWnOaksGZFbTOxAT47OH2d4NLJnLhkVD+wDbB48BuaycZPLBg==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.36.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.36.1.tgz", + "integrity": "sha512-ih7V52zvHdiX6WcPjsOdmADhYMDN15SylWRZrT2OMy80wzKbc79n8wFW0xpWpU0x3VpBz/oDgTm2xwDAnFTl+g==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.36.1", + "@typescript-eslint/visitor-keys": "5.36.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/utils": { + "version": "5.36.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.36.1.tgz", + "integrity": "sha512-lNj4FtTiXm5c+u0pUehozaUWhh7UYKnwryku0nxJlYUEWetyG92uw2pr+2Iy4M/u0ONMKzfrx7AsGBTCzORmIg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.36.1", + "@typescript-eslint/types": "5.36.1", + "@typescript-eslint/typescript-estree": "5.36.1", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.36.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.36.1.tgz", + "integrity": "sha512-ojB9aRyRFzVMN3b5joSYni6FAS10BBSCAfKJhjJAV08t/a95aM6tAhz+O1jF+EtgxktuSO3wJysp2R+Def/IWQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.36.1", + "eslint-visitor-keys": "^3.3.0" + } }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "node_modules/source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "deprecated": "See https://github.com/lydell/source-map-url#deprecated" - }, - "node_modules/stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "dependencies": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - } - }, - "node_modules/stream-browserify/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", - "dependencies": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" - } - }, - "node_modules/stream-http": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", - "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", - "dependencies": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "xtend": "^4.0.2" - } - }, - "node_modules/stream-http/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/stream-splicer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", - "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", - "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.2" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", - "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", - "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha512-AOPG8EBc5wAikaG1/7uFCNFJwnKOuQwFTpYBdTW6OvWHeZBQBrAA/amefHGrEiOnCPcLFZK6FUPtWVKpQVIRgg==", - "bin": { - "strip-json-comments": "cli.js" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/stylus": { - "version": "0.54.8", - "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.8.tgz", - "integrity": "sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg==", - "dependencies": { - "css-parse": "~2.0.0", - "debug": "~3.1.0", - "glob": "^7.1.6", - "mkdirp": "~1.0.4", - "safer-buffer": "^2.1.2", - "sax": "~1.2.4", - "semver": "^6.3.0", - "source-map": "^0.7.3" - }, - "bin": { - "stylus": "bin/stylus" - }, - "engines": { - "node": "*" - } - }, - "node_modules/stylus/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stylus/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/subarg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "integrity": "sha512-RIrIdRY0X1xojthNcVtgT9sjpOGagEUKpZdgBUi054OEPFo282yg+zE+t1Rj3+RqKq2xStL7uUHhY+AjbC4BXg==", - "dependencies": { - "minimist": "^1.1.0" - } - }, - "node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/syntax-error": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", - "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", - "dependencies": { - "acorn-node": "^1.2.0" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/timers-browserify": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", - "integrity": "sha512-PIxwAupJZiYU4JmVZYwXp9FKsHMXb5h0ZEFyuXTAn8WLHOlcij+FEcbrvDsom1o5dr1YggEtFbECvGCW2sT53Q==", - "dependencies": { - "process": "~0.11.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/token-stream": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz", - "integrity": "sha512-nfjOAu/zAWmX9tgwi5NRp7O7zTDUD1miHiB40klUnAh9qnL1iXdgzcz/i5dMaL5jahcBAaSfmNOBBJBLJW8TEg==" - }, - "node_modules/tty-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", - "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" - }, - "node_modules/uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w==", - "dependencies": { - "source-map": "~0.5.1", - "yargs": "~3.10.0" - }, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - }, - "optionalDependencies": { - "uglify-to-browserify": "~1.0.0" - } - }, - "node_modules/uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==", - "optional": true - }, - "node_modules/umd": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", - "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", - "bin": { - "umd": "bin/cli.js" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undeclared-identifiers": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", - "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", - "dependencies": { - "acorn-node": "^1.3.0", - "dash-ast": "^1.0.0", - "get-assigned-identifiers": "^1.2.0", - "simple-concat": "^1.0.0", - "xtend": "^4.0.1" - }, - "bin": { - "undeclared-identifiers": "bin.js" - } - }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", - "deprecated": "Please see https://github.com/lydell/urix#deprecated" - }, - "node_modules/url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" - }, - "node_modules/util": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", - "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.2" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" - }, - "node_modules/void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", - "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", - "for-each": "^0.3.3", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/with": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz", - "integrity": "sha512-uAnSsFGfSpF6DNhBXStvlZILfHJfJu4eUkfbRGk94kGO1Ta7bg6FwfvoOhhyHAJuFbCw+0xk4uJ3u57jLvlCJg==", - "dependencies": { - "acorn": "^3.1.0", - "acorn-globals": "^3.0.0" - } - }, - "node_modules/with/node_modules/acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha512-OLUyIIZ7mF5oaAUT1w0TFqQS81q3saT46x8t7ukpPjMNk+nbs4ZHhs7ToV8EWnLYLepjETXd4XaCE4uxkMeqUw==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A==", - "dependencies": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - } - } - }, - "dependencies": { - "@types/babel-types": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.11.tgz", - "integrity": "sha512-pkPtJUUY+Vwv6B1inAz55rQvivClHJxc9aVEPPmaq2cbyeMLCiDpbKpcKyX4LAwpNGi+SHBv0tHv6+0gXv0P2A==" - }, - "@types/babylon": { - "version": "6.16.6", - "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.6.tgz", - "integrity": "sha512-G4yqdVlhr6YhzLXFKy5F7HtRBU8Y23+iWy7UKthMq/OSQnL1hbsoeXESQ2LY8zEDlknipDG3nRGhUC9tkwvy/w==", - "requires": { - "@types/babel-types": "*" - } - }, - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" - }, - "acorn-globals": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", - "integrity": "sha512-uWttZCk96+7itPxK8xCzY86PnxKTMrReKDqrHzv42VQY0K30PUO8WY13WMOuI+cOdX4EIdzdvQ8k6jkuGRFMYw==", - "requires": { - "acorn": "^4.0.4" - }, - "dependencies": { "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug==" - } - } - }, - "acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "requires": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - } - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==", - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==" - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" - }, - "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - } - } - }, - "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==" + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-globals": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", + "integrity": "sha512-uWttZCk96+7itPxK8xCzY86PnxKTMrReKDqrHzv42VQY0K30PUO8WY13WMOuI+cOdX4EIdzdvQ8k6jkuGRFMYw==", + "dev": true, + "requires": { + "acorn": "^4.0.4" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug==", + "dev": true + } + } + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + } + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "array-includes": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", + "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "array.prototype.flat": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", + "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-shim-unscopables": "^1.0.0" + } + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==", - "requires": { - "inherits": "2.0.1" - } - } - } - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" - }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==", - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" - }, - "bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" - }, - "browser-pack": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", - "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", - "requires": { - "combine-source-map": "~0.8.0", - "defined": "^1.0.0", - "JSONStream": "^1.0.3", - "safe-buffer": "^5.1.1", - "through2": "^2.0.0", - "umd": "^3.0.0" - } - }, - "browser-resolve": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", - "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", - "requires": { - "resolve": "^1.17.0" - } - }, - "browserify": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz", - "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==", - "requires": { - "assert": "^1.4.0", - "browser-pack": "^6.0.1", - "browser-resolve": "^2.0.0", - "browserify-zlib": "~0.2.0", - "buffer": "~5.2.1", - "cached-path-relative": "^1.0.0", - "concat-stream": "^1.6.0", - "console-browserify": "^1.1.0", - "constants-browserify": "~1.0.0", - "crypto-browserify": "^3.0.0", - "defined": "^1.0.0", - "deps-sort": "^2.0.1", - "domain-browser": "^1.2.0", - "duplexer2": "~0.1.2", - "events": "^3.0.0", - "glob": "^7.1.0", - "has": "^1.0.0", - "htmlescape": "^1.1.0", - "https-browserify": "^1.0.0", - "inherits": "~2.0.1", - "insert-module-globals": "^7.2.1", - "JSONStream": "^1.0.3", - "labeled-stream-splicer": "^2.0.0", - "mkdirp-classic": "^0.5.2", - "module-deps": "^6.2.3", - "os-browserify": "~0.3.0", - "parents": "^1.0.1", - "path-browserify": "^1.0.0", - "process": "~0.11.0", - "punycode": "^1.3.2", - "querystring-es3": "~0.2.0", - "read-only-stream": "^2.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.1.4", - "shasum-object": "^1.0.0", - "shell-quote": "^1.6.1", - "stream-browserify": "^3.0.0", - "stream-http": "^3.0.0", - "string_decoder": "^1.1.1", - "subarg": "^1.0.0", - "syntax-error": "^1.1.1", - "through2": "^2.0.0", - "timers-browserify": "^1.0.1", - "tty-browserify": "0.0.1", - "url": "~0.11.0", - "util": "~0.12.0", - "vm-browserify": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", - "requires": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" - } - }, - "browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "requires": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "requires": { - "pako": "~1.0.5" - } - }, - "buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==" - }, - "cached-path-relative": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.1.0.tgz", - "integrity": "sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==" - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==" - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==", - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "character-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", - "integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==", - "requires": { - "is-regex": "^1.0.3" - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "clean-css": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", - "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", - "requires": { - "source-map": "~0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "cli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", - "integrity": "sha512-41U72MB56TfUMGndAKK8vJ78eooOD4Z5NOL4xEfjc0c23s+6EYKXlXsmACBVclLP1yOfWCgEganVzddVrSNoTg==", - "requires": { - "exit": "0.1.2", - "glob": "^7.1.1" - } - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==", - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } - }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" - }, - "combine-source-map": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", - "integrity": "sha512-UlxQ9Vw0b/Bt/KYwCFqdEwsQ1eL8d1gibiFb7lxQJFdvTgc2hIZi6ugsg+kyhzhPV+QEpUiEIwInIAIrgoEkrg==", - "requires": { - "convert-source-map": "~1.1.0", - "inline-source-map": "~0.6.0", - "lodash.memoize": "~3.0.3", - "source-map": "~0.5.3" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" - }, - "constantinople": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.2.tgz", - "integrity": "sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw==", - "requires": { - "@types/babel-types": "^7.0.0", - "@types/babylon": "^6.16.2", - "babel-types": "^6.26.0", - "babylon": "^6.18.0" - } - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==" - }, - "convert-source-map": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", - "integrity": "sha512-Y8L5rp6jo+g9VEPgvqNfEopjTR4OTYct8lXlS8iVQdmnjDvbdbzYe9rjtFCB9egC86JoNCU61WRY+ScjkZpnIg==" - }, - "core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - }, - "dependencies": { "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - } - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, - "css": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", - "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", - "requires": { - "inherits": "^2.0.3", - "source-map": "^0.6.1", - "source-map-resolve": "^0.5.2", - "urix": "^0.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "css-parse": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", - "integrity": "sha512-UNIFik2RgSbiTwIW1IsFwXWn6vs+bYdq83LKTSOsx7NJR7WII9dxewkHLltfTLVppoUApHV0118a4RZRI9FLwA==", - "requires": { - "css": "^2.0.0" - } - }, - "dash-ast": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", - "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==" - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha512-AsElvov3LoNB7tf5k37H2jYSB+ZZPMT5sG2QjJCcdlV5chIv6htBUBUui2IKRjgtKAKtCBN7Zbwa+MtwLjSeNw==" - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==" - }, - "define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==" - }, - "deps-sort": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz", - "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==", - "requires": { - "JSONStream": "^1.0.3", - "shasum-object": "^1.0.0", - "subarg": "^1.0.0", - "through2": "^2.0.0" - } - }, - "des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "detective": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", - "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", - "requires": { - "acorn-node": "^1.8.2", - "defined": "^1.0.0", - "minimist": "^1.2.6" - } - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - } - } - }, - "doctypes": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", - "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==" - }, - "dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "requires": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - }, - "dependencies": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true + }, + "browser-pack": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", + "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", + "dev": true, + "requires": { + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "JSONStream": "^1.0.3", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" + } + }, + "browser-resolve": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", + "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", + "dev": true, + "requires": { + "resolve": "^1.17.0" + } + }, + "browserify": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz", + "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==", + "dev": true, + "requires": { + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^2.0.0", + "browserify-zlib": "~0.2.0", + "buffer": "~5.2.1", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.1", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^3.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.2.1", + "JSONStream": "^1.0.3", + "labeled-stream-splicer": "^2.0.0", + "mkdirp-classic": "^0.5.2", + "module-deps": "^6.2.3", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "^1.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum-object": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^3.0.0", + "stream-http": "^3.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.12.0", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "requires": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", + "dev": true + }, + "builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, + "requires": { + "semver": "^7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "cached-path-relative": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.1.0.tgz", + "integrity": "sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==", + "dev": true + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==", + "dev": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "character-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", + "integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==", + "dev": true, + "requires": { + "is-regex": "^1.0.3" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "clean-css": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", + "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha512-41U72MB56TfUMGndAKK8vJ78eooOD4Z5NOL4xEfjc0c23s+6EYKXlXsmACBVclLP1yOfWCgEganVzddVrSNoTg==", + "dev": true, + "requires": { + "exit": "0.1.2", + "glob": "^7.1.1" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", + "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", + "dev": true + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==", + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha512-UlxQ9Vw0b/Bt/KYwCFqdEwsQ1eL8d1gibiFb7lxQJFdvTgc2hIZi6ugsg+kyhzhPV+QEpUiEIwInIAIrgoEkrg==", + "dev": true, + "requires": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "constantinople": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.2.tgz", + "integrity": "sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw==", + "dev": true, + "requires": { + "@types/babel-types": "^7.0.0", + "@types/babylon": "^6.16.2", + "babel-types": "^6.26.0", + "babylon": "^6.18.0" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true + }, + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha512-Y8L5rp6jo+g9VEPgvqNfEopjTR4OTYct8lXlS8iVQdmnjDvbdbzYe9rjtFCB9egC86JoNCU61WRY+ScjkZpnIg==", + "dev": true + }, + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha512-UNIFik2RgSbiTwIW1IsFwXWn6vs+bYdq83LKTSOsx7NJR7WII9dxewkHLltfTLVppoUApHV0118a4RZRI9FLwA==", + "dev": true, + "requires": { + "css": "^2.0.0" + } + }, + "dash-ast": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", + "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==", + "dev": true + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha512-AsElvov3LoNB7tf5k37H2jYSB+ZZPMT5sG2QjJCcdlV5chIv6htBUBUui2IKRjgtKAKtCBN7Zbwa+MtwLjSeNw==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==", + "dev": true + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", + "dev": true, + "requires": { + "clone": "^1.0.2" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true + } + } + }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==", + "dev": true + }, + "deps-sort": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz", + "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "shasum-object": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" + } + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", + "dev": true, + "requires": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + } + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "doctypes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", + "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==", + "dev": true + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + } + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha512-q9bUwjfp7Eif8jWxxxPSykdRZAb6GkguBGSgvvCrhI9wB71W2K/Kvv4E61CF/mcCfnVJDeDWx/Vb/uAqbDj6UQ==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" - } - } - }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" - }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha512-q9bUwjfp7Eif8jWxxxPSykdRZAb6GkguBGSgvvCrhI9wB71W2K/Kvv4E61CF/mcCfnVJDeDWx/Vb/uAqbDj6UQ==", - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", - "requires": { - "readable-stream": "^2.0.2" - } - }, - "elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "requires": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - } - } - }, - "entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ==" - }, - "es-abstract": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", - "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "regexp.prototype.flags": "^1.4.3", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==" - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "requires": { - "is-callable": "^1.1.3" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - } - }, - "functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" - }, - "get-assigned-identifiers": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", - "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==" - }, - "get-intrinsic": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", - "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - } - }, - "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "requires": { - "is-glob": "^4.0.1" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" - }, - "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "requires": { - "get-intrinsic": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "requires": { - "has-symbols": "^1.0.2" - } - }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "htmlescape": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", - "integrity": "sha512-eVcrzgbR4tim7c7soKQKtxa/kQM4TzjnlU83rcZ9bHU6t31ehfV7SktN6McWgwPWg+JYMA/O3qpGxBvFq1z2Jg==" - }, - "htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q==", - "requires": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" - }, - "dependencies": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ==", + "dev": true + }, + "es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + } + }, + "es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "eslint": { + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.0.tgz", + "integrity": "sha512-pBG/XOn0MsJcKcTRLr27S5HpzQo4kLr+HjLQIyK4EiCsijDl/TB+h5uEuJU6bQ8Edvwz1XWOjpaP2qgnXGpTcA==", + "dev": true, + "requires": { + "@eslint/eslintrc": "^1.3.1", + "@humanwhocodes/config-array": "^0.10.4", + "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", + "@humanwhocodes/module-importer": "^1.0.1", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "globby": "^11.1.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "eslint-config-standard": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz", + "integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==", + "dev": true, + "requires": {} + }, + "eslint-config-standard-with-typescript": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-22.0.0.tgz", + "integrity": "sha512-VA36U7UlFpwULvkdnh6MQj5GAV2Q+tT68ALLAwJP0ZuNXU2m0wX07uxX4qyLRdHgSzH4QJ73CveKBuSOYvh7vQ==", + "dev": true, + "requires": { + "@typescript-eslint/parser": "^5.0.0", + "eslint-config-standard": "17.0.0" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "dev": true, + "requires": { + "debug": "^3.2.7", + "resolve": "^1.20.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", + "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", + "dev": true, + "requires": { + "debug": "^3.2.7" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "eslint-plugin-es": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", + "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", + "dev": true, + "requires": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "dependencies": { + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "eslint-plugin-import": { + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", + "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", + "dev": true, + "requires": { + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.3", + "has": "^1.0.3", + "is-core-module": "^2.8.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.5", + "resolve": "^1.22.0", + "tsconfig-paths": "^3.14.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + } + } + }, + "eslint-plugin-n": { + "version": "15.2.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.2.5.tgz", + "integrity": "sha512-8+BYsqiyZfpu6NXmdLOXVUfk8IocpCjpd8nMRRH0A9ulrcemhb2VI9RSJMEy5udx++A/YcVPD11zT8hpFq368g==", + "dev": true, + "requires": { + "builtins": "^5.0.1", + "eslint-plugin-es": "^4.1.0", + "eslint-utils": "^3.0.0", + "ignore": "^5.1.1", + "is-core-module": "^2.10.0", + "minimatch": "^3.1.2", + "resolve": "^1.22.1", + "semver": "^7.3.7" + }, + "dependencies": { + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "eslint-plugin-promise": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.0.1.tgz", + "integrity": "sha512-uM4Tgo5u3UWQiroOyDEsYcVMOo7re3zmno0IZmB5auxoaQNIceAbXEkSt8RNrKtaYehARHG06pYK6K1JhtP0Zw==", + "dev": true, + "requires": {} + }, + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true + }, + "espree": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", + "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", + "dev": true, + "requires": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "dependencies": { + "acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "dev": true + } + } + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true + }, + "get-assigned-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha512-eVcrzgbR4tim7c7soKQKtxa/kQM4TzjnlU83rcZ9bHU6t31ehfV7SktN6McWgwPWg+JYMA/O3qpGxBvFq1z2Jg==", + "dev": true + }, + "htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q==", + "dev": true, + "requires": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "dev": true + } + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "immutable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", + "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha512-0mVWSSbNDvedDWIN4wxLsdPM4a7cIPcpyMxj3QZ406QRwQ6ePGB1YIHxVPjqpcUGbWQ5C+nHTwGNWAGvt7ggVA==", + "dev": true, + "requires": { + "source-map": "~0.5.3" + } + }, + "inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "insert-module-globals": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz", + "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==", + "dev": true, + "requires": { + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "JSONStream": "^1.0.3", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + } + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true + }, + "is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-expression": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz", + "integrity": "sha512-vyMeQMq+AiH5uUnoBfMTwf18tO3bM6k1QXBE9D6ueAAquEfCZe3AJPtud9g6qS0+4X8xA7ndpZiDyeb2l2qOBw==", + "dev": true, + "requires": { + "acorn": "~4.0.2", + "object-assign": "^4.0.1" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug==", + "dev": true + } + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true + }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", + "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0" + } + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" - } - } - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==" - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "immutable": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", - "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "inline-source-map": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", - "integrity": "sha512-0mVWSSbNDvedDWIN4wxLsdPM4a7cIPcpyMxj3QZ406QRwQ6ePGB1YIHxVPjqpcUGbWQ5C+nHTwGNWAGvt7ggVA==", - "requires": { - "source-map": "~0.5.3" - } - }, - "insert-module-globals": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz", - "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==", - "requires": { - "acorn-node": "^1.5.2", - "combine-source-map": "^0.8.0", - "concat-stream": "^1.6.1", - "is-buffer": "^1.1.0", - "JSONStream": "^1.0.3", - "path-is-absolute": "^1.0.1", - "process": "~0.11.0", - "through2": "^2.0.0", - "undeclared-identifiers": "^1.1.2", - "xtend": "^4.0.0" - } - }, - "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" - }, - "is-core-module": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", - "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", - "requires": { - "has": "^1.0.3" - } - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-expression": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz", - "integrity": "sha512-vyMeQMq+AiH5uUnoBfMTwf18tO3bM6k1QXBE9D6ueAAquEfCZe3AJPtud9g6qS0+4X8xA7ndpZiDyeb2l2qOBw==", - "requires": { - "acorn": "~4.0.2", - "object-assign": "^4.0.1" - }, - "dependencies": { - "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug==" - } - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" - }, - "is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "requires": { - "isobject": "^3.0.1" - } - }, - "is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", - "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", - "for-each": "^0.3.3", - "has-tostringtag": "^1.0.0" - } - }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "requires": { - "call-bind": "^1.0.2" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" - }, - "js-stringify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", - "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==" - }, - "jshint": { - "version": "2.13.4", - "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.4.tgz", - "integrity": "sha512-HO3bosL84b2qWqI0q+kpT/OpRJwo0R4ivgmxaO848+bo10rc50SkPnrtwSFXttW0ym4np8jbJvLwk5NziB7jIw==", - "requires": { - "cli": "~1.0.0", - "console-browserify": "1.1.x", - "exit": "0.1.x", - "htmlparser2": "3.8.x", - "lodash": "~4.17.21", - "minimatch": "~3.0.2", - "strip-json-comments": "1.0.x" - }, - "dependencies": { - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha512-duS7VP5pvfsNLDvL1O4VOEbw37AI3A4ZUQYemvDlnpGrNu9tprR7BYWpDYwC0Xia0Zxz5ZupdiIrUp0GH1aXfg==", - "requires": { - "date-now": "^0.1.4" - } + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true + }, + "js-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", + "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "jshint": { + "version": "2.13.4", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.4.tgz", + "integrity": "sha512-HO3bosL84b2qWqI0q+kpT/OpRJwo0R4ivgmxaO848+bo10rc50SkPnrtwSFXttW0ym4np8jbJvLwk5NziB7jIw==", + "dev": true, + "requires": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.21", + "minimatch": "~3.0.2", + "strip-json-comments": "1.0.x" + }, + "dependencies": { + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha512-duS7VP5pvfsNLDvL1O4VOEbw37AI3A4ZUQYemvDlnpGrNu9tprR7BYWpDYwC0Xia0Zxz5ZupdiIrUp0GH1aXfg==", + "dev": true, + "requires": { + "date-now": "^0.1.4" + } + }, + "minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "jstransformer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", + "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==", + "dev": true, + "requires": { + "is-promise": "^2.0.0", + "promise": "^7.0.1" + } + }, + "jstransformer-escape-html": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jstransformer-escape-html/-/jstransformer-escape-html-1.1.0.tgz", + "integrity": "sha512-G5wRIKQD9RoOsqvuK7yyIje/ZojoZlq3lt4IPnK2tcxYK4VKNZ1TNitrvCExkAGe/RO0sEU+bscyFUyvcYKiNg==", + "dev": true, + "requires": { + "escape-html": "^1.0.3" + } + }, + "jstransformer-scss": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jstransformer-scss/-/jstransformer-scss-2.0.0.tgz", + "integrity": "sha512-dFavLkKkc1J0KT0UpbUue11qGlv0+pcS5AWvH5LZlxq70bIuXJ+tGvVC9jEL2oI3p4kvNvlULuzFeo/qrmnvnQ==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "sass": "~1.53.0" + } + }, + "jstransformer-stylus": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/jstransformer-stylus/-/jstransformer-stylus-1.5.0.tgz", + "integrity": "sha512-j3A5dryGjFECzNHO0F4hmosOwXobLpEb+mo2+q2mywctzm1UnIISzvBUvq9zPpvx9vDEh9ln8SraEwrFnke+tA==", + "dev": true, + "requires": { + "clone": "^2.0.0", + "stylus": "~0.54.5" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "labeled-stream-splicer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", + "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "stream-splicer": "^2.0.0" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha512-eDn9kqrAmVUC1wmZvlQ6Uhde44n+tXpqPrN8olQJbttgh0oKclk+SF54P47VEGE9CEiMeRwAP8BaM7UHvBkz2A==", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true }, "minimatch": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==" - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "jstransformer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", - "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==", - "requires": { - "is-promise": "^2.0.0", - "promise": "^7.0.1" - } - }, - "jstransformer-escape-html": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jstransformer-escape-html/-/jstransformer-escape-html-1.1.0.tgz", - "integrity": "sha512-G5wRIKQD9RoOsqvuK7yyIje/ZojoZlq3lt4IPnK2tcxYK4VKNZ1TNitrvCExkAGe/RO0sEU+bscyFUyvcYKiNg==", - "requires": { - "escape-html": "^1.0.3" - } - }, - "jstransformer-scss": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jstransformer-scss/-/jstransformer-scss-2.0.0.tgz", - "integrity": "sha512-dFavLkKkc1J0KT0UpbUue11qGlv0+pcS5AWvH5LZlxq70bIuXJ+tGvVC9jEL2oI3p4kvNvlULuzFeo/qrmnvnQ==", - "requires": { - "extend-shallow": "^3.0.2", - "sass": "~1.53.0" - } - }, - "jstransformer-stylus": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/jstransformer-stylus/-/jstransformer-stylus-1.5.0.tgz", - "integrity": "sha512-j3A5dryGjFECzNHO0F4hmosOwXobLpEb+mo2+q2mywctzm1UnIISzvBUvq9zPpvx9vDEh9ln8SraEwrFnke+tA==", - "requires": { - "clone": "^2.0.0", - "stylus": "~0.54.5" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "requires": { - "is-buffer": "^1.1.5" - } - }, - "labeled-stream-splicer": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", - "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", - "requires": { - "inherits": "^2.0.1", - "stream-splicer": "^2.0.0" - } - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==" - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.memoize": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", - "integrity": "sha512-eDn9kqrAmVUC1wmZvlQ6Uhde44n+tXpqPrN8olQJbttgh0oKclk+SF54P47VEGE9CEiMeRwAP8BaM7UHvBkz2A==" - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "lodash.omit": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", - "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==" - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==" - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - } - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "requires": { - "minimist": "^1.2.6" - } - }, - "mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" - }, - "module-deps": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz", - "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==", - "requires": { - "browser-resolve": "^2.0.0", - "cached-path-relative": "^1.0.2", - "concat-stream": "~1.6.0", - "defined": "^1.0.0", - "detective": "^5.2.0", - "duplexer2": "^0.1.2", - "inherits": "^2.0.1", - "JSONStream": "^1.0.3", - "parents": "^1.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.4.0", - "stream-combiner2": "^1.1.1", - "subarg": "^1.0.0", - "through2": "^2.0.0", - "xtend": "^4.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==" - }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "parents": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", - "integrity": "sha512-mXKF3xkoUt5td2DoxpLmtOmZvko9VfFpwRwkKDHSNvgmpLAeBo18YDhcPbBzJq+QLCHMbGOfzia2cX4U+0v9Mg==", - "requires": { - "path-platform": "~0.11.15" - } - }, - "parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "requires": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "path-platform": { - "version": "0.11.15", - "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", - "integrity": "sha512-Y30dB6rab1A/nfEKsZxmr01nUotHX0c/ZiIAsCTatEe1CmS5Pm5He7fZ195bPT7RdquoaL8lLxFCMQi/bS7IJg==" - }, - "pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "requires": { - "asap": "~2.0.3" - } - }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - } - } - }, - "pug": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.4.tgz", - "integrity": "sha512-XhoaDlvi6NIzL49nu094R2NA6P37ijtgMDuWE+ofekDChvfKnzFal60bhSdiy8y2PBO6fmz3oMEIcfpBVRUdvw==", - "requires": { - "pug-code-gen": "^2.0.2", - "pug-filters": "^3.1.1", - "pug-lexer": "^4.1.0", - "pug-linker": "^3.0.6", - "pug-load": "^2.0.12", - "pug-parser": "^5.0.1", - "pug-runtime": "^2.0.5", - "pug-strip-comments": "^1.0.4" - } - }, - "pug-attrs": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.4.tgz", - "integrity": "sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ==", - "requires": { - "constantinople": "^3.0.1", - "js-stringify": "^1.0.1", - "pug-runtime": "^2.0.5" - } - }, - "pug-cli": { - "version": "1.0.0-alpha6", - "resolved": "https://registry.npmjs.org/pug-cli/-/pug-cli-1.0.0-alpha6.tgz", - "integrity": "sha512-ogaf7h4cT174NFSHNqAMdrZpGFCZSvsht41IYZZgP7ERZ1OxSc5fmPpojo1w9UntVreeChQP3BJ5r+Fey0a9zg==", - "requires": { - "chalk": "^1.0.0", - "commander": "^2.8.1", - "mkdirp": "^0.5.1", - "pug": "^2.0.0-alpha7" - } - }, - "pug-code-gen": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.3.tgz", - "integrity": "sha512-r9sezXdDuZJfW9J91TN/2LFbiqDhmltTFmGpHTsGdrNGp3p4SxAjjXEfnuK2e4ywYsRIVP0NeLbSAMHUcaX1EA==", - "requires": { - "constantinople": "^3.1.2", - "doctypes": "^1.1.0", - "js-stringify": "^1.0.1", - "pug-attrs": "^2.0.4", - "pug-error": "^1.3.3", - "pug-runtime": "^2.0.5", - "void-elements": "^2.0.1", - "with": "^5.0.0" - } - }, - "pug-error": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.3.tgz", - "integrity": "sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ==" - }, - "pug-filters": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-3.1.1.tgz", - "integrity": "sha512-lFfjNyGEyVWC4BwX0WyvkoWLapI5xHSM3xZJFUhx4JM4XyyRdO8Aucc6pCygnqV2uSgJFaJWW3Ft1wCWSoQkQg==", - "requires": { - "clean-css": "^4.1.11", - "constantinople": "^3.0.1", - "jstransformer": "1.0.0", - "pug-error": "^1.3.3", - "pug-walk": "^1.1.8", - "resolve": "^1.1.6", - "uglify-js": "^2.6.1" - } - }, - "pug-lexer": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-4.1.0.tgz", - "integrity": "sha512-i55yzEBtjm0mlplW4LoANq7k3S8gDdfC6+LThGEvsK4FuobcKfDAwt6V4jKPH9RtiE3a2Akfg5UpafZ1OksaPA==", - "requires": { - "character-parser": "^2.1.1", - "is-expression": "^3.0.0", - "pug-error": "^1.3.3" - } - }, - "pug-linker": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.6.tgz", - "integrity": "sha512-bagfuHttfQOpANGy1Y6NJ+0mNb7dD2MswFG2ZKj22s8g0wVsojpRlqveEQHmgXXcfROB2RT6oqbPYr9EN2ZWzg==", - "requires": { - "pug-error": "^1.3.3", - "pug-walk": "^1.1.8" - } - }, - "pug-load": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.12.tgz", - "integrity": "sha512-UqpgGpyyXRYgJs/X60sE6SIf8UBsmcHYKNaOccyVLEuT6OPBIMo6xMPhoJnqtB3Q3BbO4Z3Bjz5qDsUWh4rXsg==", - "requires": { - "object-assign": "^4.1.0", - "pug-walk": "^1.1.8" - } - }, - "pug-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-5.0.1.tgz", - "integrity": "sha512-nGHqK+w07p5/PsPIyzkTQfzlYfuqoiGjaoqHv1LjOv2ZLXmGX1O+4Vcvps+P4LhxZ3drYSljjq4b+Naid126wA==", - "requires": { - "pug-error": "^1.3.3", - "token-stream": "0.0.1" - } - }, - "pug-runtime": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.5.tgz", - "integrity": "sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw==" - }, - "pug-strip-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.4.tgz", - "integrity": "sha512-i5j/9CS4yFhSxHp5iKPHwigaig/VV9g+FgReLJWWHEHbvKsbqL0oP/K5ubuLco6Wu3Kan5p7u7qk8A4oLLh6vw==", - "requires": { - "pug-error": "^1.3.3" - } - }, - "pug-walk": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.8.tgz", - "integrity": "sha512-GMu3M5nUL3fju4/egXwZO0XLi6fW/K3T3VTgFQ14GxNi8btlxgT5qZL//JwZFm/2Fa64J/PNS8AZeys3wiMkVA==" - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==" - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==" - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "read-only-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", - "integrity": "sha512-3ALe0bjBVZtkdWKIcThYpQCLbBMd/+Tbh2CDSrAIDO3UsZ4Xs+tnyjv2MjCOMMgBG+AsUOeuP1cgtY1INISc8w==", - "requires": { - "readable-stream": "^2.0.2" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "requires": { - "picomatch": "^2.2.1" - } - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" - }, - "regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - } - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==" - }, - "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==" - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==", - "requires": { - "align-text": "^0.1.1" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sass": { - "version": "1.53.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.53.0.tgz", - "integrity": "sha512-zb/oMirbKhUgRQ0/GFz8TSAwRq2IlR29vOUJZOx0l8sV+CkHUfHa4u5nqrG+1VceZp7Jfj59SVW9ogdhTvJDcQ==", - "requires": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - } - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shasum-object": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz", - "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==", - "requires": { - "fast-safe-stringify": "^2.0.7" - } - }, - "shell-quote": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", - "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" - }, - "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==" - }, - "stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "requires": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", - "requires": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" - } - }, - "stream-http": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", - "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "xtend": "^4.0.2" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "stream-splicer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", - "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.2" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string.prototype.trimend": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", - "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - } - }, - "string.prototype.trimstart": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", - "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha512-AOPG8EBc5wAikaG1/7uFCNFJwnKOuQwFTpYBdTW6OvWHeZBQBrAA/amefHGrEiOnCPcLFZK6FUPtWVKpQVIRgg==" - }, - "stylus": { - "version": "0.54.8", - "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.8.tgz", - "integrity": "sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg==", - "requires": { - "css-parse": "~2.0.0", - "debug": "~3.1.0", - "glob": "^7.1.6", - "mkdirp": "~1.0.4", - "safer-buffer": "^2.1.2", - "sax": "~1.2.4", - "semver": "^6.3.0", - "source-map": "^0.7.3" - }, - "dependencies": { "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "module-deps": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz", + "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==", + "dev": true, + "requires": { + "browser-resolve": "^2.0.0", + "cached-path-relative": "^1.0.2", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.2.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "JSONStream": "^1.0.3", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha512-mXKF3xkoUt5td2DoxpLmtOmZvko9VfFpwRwkKDHSNvgmpLAeBo18YDhcPbBzJq+QLCHMbGOfzia2cX4U+0v9Mg==", + "dev": true, + "requires": { + "path-platform": "~0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha512-Y30dB6rab1A/nfEKsZxmr01nUotHX0c/ZiIAsCTatEe1CmS5Pm5He7fZ195bPT7RdquoaL8lLxFCMQi/bS7IJg==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dev": true, + "requires": { + "asap": "~2.0.3" + } + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "pug": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.4.tgz", + "integrity": "sha512-XhoaDlvi6NIzL49nu094R2NA6P37ijtgMDuWE+ofekDChvfKnzFal60bhSdiy8y2PBO6fmz3oMEIcfpBVRUdvw==", + "dev": true, + "requires": { + "pug-code-gen": "^2.0.2", + "pug-filters": "^3.1.1", + "pug-lexer": "^4.1.0", + "pug-linker": "^3.0.6", + "pug-load": "^2.0.12", + "pug-parser": "^5.0.1", + "pug-runtime": "^2.0.5", + "pug-strip-comments": "^1.0.4" + } + }, + "pug-attrs": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.4.tgz", + "integrity": "sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ==", + "dev": true, + "requires": { + "constantinople": "^3.0.1", + "js-stringify": "^1.0.1", + "pug-runtime": "^2.0.5" + } + }, + "pug-cli": { + "version": "1.0.0-alpha6", + "resolved": "https://registry.npmjs.org/pug-cli/-/pug-cli-1.0.0-alpha6.tgz", + "integrity": "sha512-ogaf7h4cT174NFSHNqAMdrZpGFCZSvsht41IYZZgP7ERZ1OxSc5fmPpojo1w9UntVreeChQP3BJ5r+Fey0a9zg==", + "dev": true, + "requires": { + "chalk": "^1.0.0", + "commander": "^2.8.1", + "mkdirp": "^0.5.1", + "pug": "^2.0.0-alpha7" + } + }, + "pug-code-gen": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.3.tgz", + "integrity": "sha512-r9sezXdDuZJfW9J91TN/2LFbiqDhmltTFmGpHTsGdrNGp3p4SxAjjXEfnuK2e4ywYsRIVP0NeLbSAMHUcaX1EA==", + "dev": true, + "requires": { + "constantinople": "^3.1.2", + "doctypes": "^1.1.0", + "js-stringify": "^1.0.1", + "pug-attrs": "^2.0.4", + "pug-error": "^1.3.3", + "pug-runtime": "^2.0.5", + "void-elements": "^2.0.1", + "with": "^5.0.0" + } + }, + "pug-error": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.3.tgz", + "integrity": "sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ==", + "dev": true + }, + "pug-filters": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-3.1.1.tgz", + "integrity": "sha512-lFfjNyGEyVWC4BwX0WyvkoWLapI5xHSM3xZJFUhx4JM4XyyRdO8Aucc6pCygnqV2uSgJFaJWW3Ft1wCWSoQkQg==", + "dev": true, + "requires": { + "clean-css": "^4.1.11", + "constantinople": "^3.0.1", + "jstransformer": "1.0.0", + "pug-error": "^1.3.3", + "pug-walk": "^1.1.8", + "resolve": "^1.1.6", + "uglify-js": "^2.6.1" + } + }, + "pug-lexer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-4.1.0.tgz", + "integrity": "sha512-i55yzEBtjm0mlplW4LoANq7k3S8gDdfC6+LThGEvsK4FuobcKfDAwt6V4jKPH9RtiE3a2Akfg5UpafZ1OksaPA==", + "dev": true, + "requires": { + "character-parser": "^2.1.1", + "is-expression": "^3.0.0", + "pug-error": "^1.3.3" + } + }, + "pug-linker": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.6.tgz", + "integrity": "sha512-bagfuHttfQOpANGy1Y6NJ+0mNb7dD2MswFG2ZKj22s8g0wVsojpRlqveEQHmgXXcfROB2RT6oqbPYr9EN2ZWzg==", + "dev": true, + "requires": { + "pug-error": "^1.3.3", + "pug-walk": "^1.1.8" + } + }, + "pug-load": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.12.tgz", + "integrity": "sha512-UqpgGpyyXRYgJs/X60sE6SIf8UBsmcHYKNaOccyVLEuT6OPBIMo6xMPhoJnqtB3Q3BbO4Z3Bjz5qDsUWh4rXsg==", + "dev": true, + "requires": { + "object-assign": "^4.1.0", + "pug-walk": "^1.1.8" + } + }, + "pug-parser": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-5.0.1.tgz", + "integrity": "sha512-nGHqK+w07p5/PsPIyzkTQfzlYfuqoiGjaoqHv1LjOv2ZLXmGX1O+4Vcvps+P4LhxZ3drYSljjq4b+Naid126wA==", + "dev": true, + "requires": { + "pug-error": "^1.3.3", + "token-stream": "0.0.1" + } + }, + "pug-runtime": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.5.tgz", + "integrity": "sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw==", + "dev": true + }, + "pug-strip-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.4.tgz", + "integrity": "sha512-i5j/9CS4yFhSxHp5iKPHwigaig/VV9g+FgReLJWWHEHbvKsbqL0oP/K5ubuLco6Wu3Kan5p7u7qk8A4oLLh6vw==", + "dev": true, + "requires": { + "pug-error": "^1.3.3" + } + }, + "pug-walk": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.8.tgz", + "integrity": "sha512-GMu3M5nUL3fju4/egXwZO0XLi6fW/K3T3VTgFQ14GxNi8btlxgT5qZL//JwZFm/2Fa64J/PNS8AZeys3wiMkVA==", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha512-3ALe0bjBVZtkdWKIcThYpQCLbBMd/+Tbh2CDSrAIDO3UsZ4Xs+tnyjv2MjCOMMgBG+AsUOeuP1cgtY1INISc8w==", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "dev": true + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==", + "dev": true, + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "rxjs": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", + "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + } + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sass": { + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.53.0.tgz", + "integrity": "sha512-zb/oMirbKhUgRQ0/GFz8TSAwRq2IlR29vOUJZOx0l8sV+CkHUfHa4u5nqrG+1VceZp7Jfj59SVW9ogdhTvJDcQ==", + "dev": true, + "requires": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shasum-object": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz", + "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==", + "dev": true, + "requires": { + "fast-safe-stringify": "^2.0.7" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "shell-quote": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true }, "source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "dev": true + }, + "stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "requires": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", + "dev": true, + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-splicer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", + "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true + }, + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha512-AOPG8EBc5wAikaG1/7uFCNFJwnKOuQwFTpYBdTW6OvWHeZBQBrAA/amefHGrEiOnCPcLFZK6FUPtWVKpQVIRgg==", + "dev": true + }, + "stylus": { + "version": "0.54.8", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.8.tgz", + "integrity": "sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg==", + "dev": true, + "requires": { + "css-parse": "~2.0.0", + "debug": "~3.1.0", + "glob": "^7.1.6", + "mkdirp": "~1.0.4", + "safer-buffer": "^2.1.2", + "sax": "~1.2.4", + "semver": "^6.3.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true + } + } + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha512-RIrIdRY0X1xojthNcVtgT9sjpOGagEUKpZdgBUi054OEPFo282yg+zE+t1Rj3+RqKq2xStL7uUHhY+AjbC4BXg==", + "dev": true, + "requires": { + "minimist": "^1.1.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dev": true, + "requires": { + "acorn-node": "^1.2.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha512-PIxwAupJZiYU4JmVZYwXp9FKsHMXb5h0ZEFyuXTAn8WLHOlcij+FEcbrvDsom1o5dr1YggEtFbECvGCW2sT53Q==", + "dev": true, + "requires": { + "process": "~0.11.0" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "token-stream": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz", + "integrity": "sha512-nfjOAu/zAWmX9tgwi5NRp7O7zTDUD1miHiB40klUnAh9qnL1iXdgzcz/i5dMaL5jahcBAaSfmNOBBJBLJW8TEg==", + "dev": true + }, + "tsconfig-paths": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", + "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true + }, + "typescript": { + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", + "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==", + "dev": true, + "peer": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w==", + "dev": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==", + "dev": true, + "optional": true + }, + "umd": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", + "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", + "dev": true + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "undeclared-identifiers": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", + "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", + "dev": true, + "requires": { + "acorn-node": "^1.3.0", + "dash-ast": "^1.0.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", + "dev": true + } + } + }, + "util": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", + "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", + "dev": true + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-typed-array": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", + "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.9" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg==", + "dev": true + }, + "with": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz", + "integrity": "sha512-uAnSsFGfSpF6DNhBXStvlZILfHJfJu4eUkfbRGk94kGO1Ta7bg6FwfvoOhhyHAJuFbCw+0xk4uJ3u57jLvlCJg==", + "dev": true, + "requires": { + "acorn": "^3.1.0", + "acorn-globals": "^3.0.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha512-OLUyIIZ7mF5oaAUT1w0TFqQS81q3saT46x8t7ukpPjMNk+nbs4ZHhs7ToV8EWnLYLepjETXd4XaCE4uxkMeqUw==", + "dev": true + } + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A==", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } - } - }, - "subarg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "integrity": "sha512-RIrIdRY0X1xojthNcVtgT9sjpOGagEUKpZdgBUi054OEPFo282yg+zE+t1Rj3+RqKq2xStL7uUHhY+AjbC4BXg==", - "requires": { - "minimist": "^1.1.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==" - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" - }, - "syntax-error": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", - "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", - "requires": { - "acorn-node": "^1.2.0" - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "timers-browserify": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", - "integrity": "sha512-PIxwAupJZiYU4JmVZYwXp9FKsHMXb5h0ZEFyuXTAn8WLHOlcij+FEcbrvDsom1o5dr1YggEtFbECvGCW2sT53Q==", - "requires": { - "process": "~0.11.0" - } - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==" - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - }, - "token-stream": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz", - "integrity": "sha512-nfjOAu/zAWmX9tgwi5NRp7O7zTDUD1miHiB40klUnAh9qnL1iXdgzcz/i5dMaL5jahcBAaSfmNOBBJBLJW8TEg==" - }, - "tty-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", - "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w==", - "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - } - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==", - "optional": true - }, - "umd": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", - "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==" - }, - "unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "requires": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - } - }, - "undeclared-identifiers": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", - "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", - "requires": { - "acorn-node": "^1.3.0", - "dash-ast": "^1.0.0", - "get-assigned-identifiers": "^1.2.0", - "simple-concat": "^1.0.0", - "xtend": "^4.0.1" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==" - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" - } - } - }, - "util": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", - "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", - "requires": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" - }, - "void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==" - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-typed-array": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", - "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", - "for-each": "^0.3.3", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.9" - } - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg==" - }, - "with": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz", - "integrity": "sha512-uAnSsFGfSpF6DNhBXStvlZILfHJfJu4eUkfbRGk94kGO1Ta7bg6FwfvoOhhyHAJuFbCw+0xk4uJ3u57jLvlCJg==", - "requires": { - "acorn": "^3.1.0", - "acorn-globals": "^3.0.0" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha512-OLUyIIZ7mF5oaAUT1w0TFqQS81q3saT46x8t7ukpPjMNk+nbs4ZHhs7ToV8EWnLYLepjETXd4XaCE4uxkMeqUw==" - } - } - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A==", - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - } } - } } diff --git a/package.json b/package.json index f16e20b..92c287a 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,28 @@ { - "name": "bbctrl", - "version": "1.0.10b1", - "homepage": "https://onefinitycnc.com/", - "repository": "https://github.com/OneFinityCNC/onefinity", - "license": "GPL-3.0+", - "dependencies": { - "browserify": "^17.0.0", - "jshint": "^2.13.4", - "jstransformer-escape-html": "^1.1.0", - "jstransformer-scss": "^2.0.0", - "jstransformer-stylus": "^1.5.0", - "lodash.merge": "4.6.2", - "lodash.omit": "^4.5.0", - "pug-cli": "^1.0.0-alpha6" - } -} + "name": "bbctrl", + "version": "1.1.0", + "homepage": "https://onefinitycnc.com/", + "repository": "https://github.com/OneFinityCNC/onefinity", + "license": "GPL-3.0+", + "scripts": { + "postinstall": "cd src/svelte-components && npm i" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "^5.36.1", + "@typescript-eslint/parser": "^5.36.1", + "browserify": "^17.0.0", + "eslint": "^8.23.0", + "eslint-config-standard-with-typescript": "^22.0.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-n": "^15.2.5", + "eslint-plugin-promise": "^6.0.1", + "glob": "^8.0.3", + "inquirer": "^8.2.4", + "jshint": "^2.13.4", + "jstransformer-escape-html": "^1.1.0", + "jstransformer-scss": "^2.0.0", + "jstransformer-stylus": "^1.5.0", + "lodash.merge": "4.6.2", + "pug-cli": "^1.0.0-alpha6" + } +} \ No newline at end of file diff --git a/pug-opts.js b/pug-opts.js index 177616e..30a110a 100644 --- a/pug-opts.js +++ b/pug-opts.js @@ -1,11 +1,11 @@ -{ - pretty: true, - filters: { - browserify: function (text, options) { - return require('child_process').execSync( - `./node_modules/.bin/browserify - --basedir src/js`, - {input: text} - ).toString() +module.exports = { + pretty: true, + filters: { + browserify: function(text, _options) { + return require("child_process").execSync( + `./node_modules/.bin/browserify - --basedir src/js`, + { input: text } + ).toString(); + } } - } -} +}; diff --git a/requirements.txt b/requirements.txt index 677fb41..05123ae 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ -watchdog==0.10.6 \ No newline at end of file +watchdog==0.10.6 +evdev==1.6.0 \ No newline at end of file diff --git a/scripts/check-config-vars.py b/scripts/check-config-vars.py deleted file mode 100644 index 6fd567a..0000000 --- a/scripts/check-config-vars.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 - -'''Check that the configuration variable template used on the RPi matches the -variables used in the AVR''' - -import sys -import json - -templ = json.load(open('src/resources/config-template.json', 'r')) -vars = json.load(open('avr/build/vars.json', 'r')) - - -def check(section): - errors = 0 - - for name, entry in section.items(): - if 'type' in entry: - ok = False - - # TODO check that defaults are valid - # TODO check that types match - - if 'code' in entry and not entry['code'] in vars: - print('"%s" with code "%s" not found' % (name, entry['code'])) - - else: ok = True - - if not ok: errors += 1 - - else: errors += check(entry) - - return errors - - -errors = check(templ) -print('\n%d errors' % errors) -sys.exit(errors != 0) diff --git a/scripts/config-screen b/scripts/config-screen deleted file mode 100644 index 364c150..0000000 --- a/scripts/config-screen +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -if [ $# != 3 ]; then - echo "Usage: $0 " - exit 1 -fi - -WIDTH="$1" -HEIGHT="$2" -ROTATION="$3" - -if [[ ! "$WIDTH" =~ ^[0-9]+$ ]]; then - echo "Invalid width '$WIDTH'." - exit 1 -fi - -if [[ ! "$HEIGHT" =~ ^[0-9]+$ ]]; then - echo "Invalid height '$HEIGHT'." - exit 1 -fi - -if [[ ! "$ROTATION" =~ ^[0-3]$ ]]; then - echo "Invalid rotation '$ROTATION'." - exit 1 -fi - - -OPTIONS="framebuffer_width=$WIDTH " -OPTIONS+="framebuffer_height=$HEIGHT " -OPTIONS+="display_rotate=$ROTATION" - -edit-boot-config $OPTIONS diff --git a/scripts/config-wifi b/scripts/config-wifi deleted file mode 100644 index 16f7ed1..0000000 --- a/scripts/config-wifi +++ /dev/null @@ -1,262 +0,0 @@ -#!/bin/bash -e - -AP=false -DISABLE=false -SSID= -PASS= -CHANNEL=7 -REBOOT=false - -WLAN0_CFG=/etc/network/interfaces.d/wlan0 -HOSTAPD_CFG=/etc/hostapd/hostapd.conf -DNSMASQ_CFG=/etc/dnsmasq.conf -DHCPCD_CFG=/etc/dhcpcd.conf -WPA_CFG=/etc/wpa_supplicant/wpa_supplicant.conf - - -function query_config() { - if [ -e $WLAN0_CFG ]; then - SSID=$(grep wpa-ssid $WLAN0_CFG | - sed 's/^[[:space:]]*wpa-ssid "\([^"]*\)"/\1/') - # echo "{\"ssid\": \"$SSID\", \"mode\": \"client\"}" - echo "{\"ssid\": \"$SSID\"}" - - else - # if [ -e $HOSTAPD_CFG -a -e /etc/default/hostapd ]; then - # SSID=$(grep ^ssid= $HOSTAPD_CFG | sed 's/^ssid=\(.*\)$/\1/') - # CHANNEL=$(grep ^channel= $HOSTAPD_CFG | - # sed 's/^channel=\(.*\)$/\1/') - - # echo -n "{\"ssid\": \"$SSID\", " - # echo "\"channel\": $CHANNEL, \"mode\": \"ap\"}" - - # else - # echo "{\"mode\": \"disabled\"}" - # fi - - echo "{}" - fi - -} - - -function disable_wifi() { - rm -f $WLAN0_CFG $HOSTAPD_CFG /etc/default/hostapd -} - - -function configure_wlan0() { - echo "auto wlan0" - echo "allow-hotplug wlan0" - echo "iface wlan0 inet dhcp" - echo " wpa-scan-ssid 1" - echo " wpa-ap-scan 1" - echo " wpa-key-mgmt WPA-PSK" - echo " wpa-proto RSN WPA" - echo " wpa-pairwise CCMP TKIP" - echo " wpa-group CCMP TKIP" - echo " wpa-ssid \"$SSID\"" - - if [ ${#PASS} -ne 0 ]; then - echo " wpa-psk \"$PASS\"" - fi -} - - -function configure_wpa() { - echo "country=US" - echo "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev" - echo "update_config=1" - - if [ ${#PASS} -eq 0 ]; then - echo "network={" - echo " ssid=\"$SSID\"" - echo " key_mgmt=NONE" - echo "}" - fi -} - - -function configure_dhcpcd() { - echo "hostname" - echo "clientid" - echo "persistent" - echo "option rapid_commit" - echo "option domain_name_servers, domain_name, domain_search, host_name" - echo "option classless_static_routes" - echo "option ntp_servers" - echo "option interface_mtu" - echo "require dhcp_server_identifier" - echo "slaac private" - - if $AP; then - echo - echo "interface wlan0" - echo " static ip_address=192.168.43.1/24" - fi -} - - -function configure_wifi() { - disable_wifi - echo "source-directory /etc/network/interfaces.d" > /etc/network/interfaces - configure_wlan0 > $WLAN0_CFG - configure_wpa > $WPA_CFG - configure_dhcpcd > $DHCPCD_CFG -} - - -function configure_dnsmasq() { - echo "interface=wlan0" - echo "domain-needed" - echo "bogus-priv" - echo "dhcp-range=192.168.43.2,192.168.43.20,255.255.255.0,12h" -} - - -function configure_hostapd() { - echo "interface=wlan0" - echo "driver=nl80211" - echo "ssid=$SSID" - echo "hw_mode=g" - echo "channel=$CHANNEL" - echo "wmm_enabled=0" - echo "macaddr_acl=0" - echo "auth_algs=1" - echo "ignore_broadcast_ssid=0" - echo "wpa=2" - echo "wpa_passphrase=$PASS" - echo "wpa_key_mgmt=WPA-PSK" - echo "wpa_pairwise=TKIP" - echo "rsn_pairwise=CCMP" -} - - -function is_installed() { - dpkg-query -W --showformat='${Status}' $1 | - grep "install ok installed" >/dev/null - if [ $? -eq 0 ]; then echo true; else echo false; fi -} - - -function configure_ap() { - disable_wifi - - # Install packages - ( - $(is_installed dnsmasq) && - $(is_installed hostapd) && - $(is_installed iptables-persistent) - - ) || ( - export DEBIAN_FRONTEND=noninteractive - apt-get update - apt-get install -yq dnsmasq hostapd iptables-persistent - ) - - configure_dhcpcd > $DHCPCD_CFG - configure_dnsmasq > $DNSMASQ_CFG - configure_hostapd > $HOSTAPD_CFG - - echo "DAEMON_CONF=\"/etc/hostapd/hostapd.conf\"" > /etc/default/hostapd - - # Enable IP forwarding - sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf - echo 1 > /proc/sys/net/ipv4/ip_forward - - # Enable IP masquerading - iptables -t nat -F - iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE - iptables-save > /etc/iptables/rules.v4 -} - - -function usage() { - echo "Usage: config-wifi [OPTIONS]" - echo - echo "Configure wifi as either a client or access point." - echo - echo "OPTIONS:" - echo - echo " -a Configure access point." - echo " -d Disable wifi." - echo " -r Reboot when done." - echo " -s Set SSID." - echo " -p Set password." - echo " -c Set wifi channel." - echo " -j Report wifi config as JSON data." - echo -} - - -# Parse args -while [ $# -ne 0 ]; do - case "$1" in - -a) AP=true ;; - -d) DISABLE=true ;; - -r) REBOOT=true; ;; - -s) SSID="$2"; shift ;; - -p) PASS="$2"; shift ;; - -c) CHANNEL="$2"; shift ;; - -j) query_config; exit 0 ;; - - -h) - usage - exit 0 - ;; - - *) - usage - echo "Unknown argument '$1'" - exit 1 - esac - - shift -done - - -if $DISABLE; then - disable_wifi - -else - # Check args - function clean_str() { - echo "$1" | tr -d '\n\r"' - } - - SSID=$(clean_str "$SSID") - PASS=$(clean_str "$PASS") - - LANG=C LC_ALL=C # For correct string byte length - - if [ ${#SSID} -eq 0 -o 32 -lt ${#SSID} ]; then - echo "Invalid or missing SSID '$SSID'" - exit 1 - fi - - if [ ${#PASS} -ne 0 ]; then - if [ ${#PASS} -lt 8 -o 128 -lt ${#PASS} ]; then - echo "Invalid passsword" - exit 1 - fi - fi - - echo "$CHANNEL" | grep '^[0-9]\{1,2\}' > /dev/null - if [ $? -ne 0 ]; then - echo "Invalid channel '$CHANNEL'" - exit 1 - fi - - # Execute - if $AP; then - echo "Configuring Wifi access point" - configure_ap - - else - echo "Configuring Wifi" - configure_wifi - fi -fi - - -if $REBOOT; then nohup reboot & fi diff --git a/scripts/config-wifi-external b/scripts/config-wifi-external deleted file mode 100644 index 018c676..0000000 --- a/scripts/config-wifi-external +++ /dev/null @@ -1,259 +0,0 @@ -#!/bin/bash -e - -AP=false -DISABLE=false -SSID= -PASS= -CHANNEL=7 -REBOOT=false - -WLAN0_CFG=/etc/network/interfaces.d/wlan0 -HOSTAPD_CFG=/etc/hostapd/hostapd.conf -DNSMASQ_CFG=/etc/dnsmasq.conf -DHCPCD_CFG=/etc/dhcpcd.conf -WPA_CFG=/etc/wpa_supplicant/wpa_supplicant.conf - - -function query_config() { - if [ -e $WLAN0_CFG ]; then - SSID=$(grep wpa-ssid $WLAN0_CFG | - sed 's/^[[:space:]]*wpa-ssid "\([^"]*\)"/\1/') - echo "{\"ssid\": \"$SSID\", \"mode\": \"client\"}" - - else - if [ -e $HOSTAPD_CFG -a -e /etc/default/hostapd ]; then - SSID=$(grep ^ssid= $HOSTAPD_CFG | sed 's/^ssid=\(.*\)$/\1/') - CHANNEL=$(grep ^channel= $HOSTAPD_CFG | - sed 's/^channel=\(.*\)$/\1/') - - echo -n "{\"ssid\": \"$SSID\", " - echo "\"channel\": $CHANNEL, \"mode\": \"ap\"}" - - else - echo "{\"mode\": \"disabled\"}" - fi - fi - -} - - -function disable_wifi() { - rm -f $WLAN0_CFG $HOSTAPD_CFG /etc/default/hostapd -} - - -function configure_wlan0() { - echo "auto wlan0" - echo "allow-hotplug wlan0" - echo "iface wlan0 inet dhcp" - echo " wpa-scan-ssid 1" - echo " wpa-ap-scan 1" - echo " wpa-key-mgmt WPA-PSK" - echo " wpa-proto RSN WPA" - echo " wpa-pairwise CCMP TKIP" - echo " wpa-group CCMP TKIP" - echo " wpa-ssid \"$SSID\"" - - if [ ${#PASS} -ne 0 ]; then - echo " wpa-psk \"$PASS\"" - fi -} - - -function configure_wpa() { - echo "country=US" - echo "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev" - echo "update_config=1" - - if [ ${#PASS} -eq 0 ]; then - echo "network={" - echo " ssid=\"$SSID\"" - echo " key_mgmt=NONE" - echo "}" - fi -} - - -function configure_dhcpcd() { - echo "hostname" - echo "clientid" - echo "persistent" - echo "option rapid_commit" - echo "option domain_name_servers, domain_name, domain_search, host_name" - echo "option classless_static_routes" - echo "option ntp_servers" - echo "option interface_mtu" - echo "require dhcp_server_identifier" - echo "slaac private" - - if $AP; then - echo - echo "interface wlan0" - echo " static ip_address=192.168.43.1/24" - fi -} - - -function configure_wifi() { - disable_wifi - echo "source-directory /etc/network/interfaces.d" > /etc/network/interfaces - configure_wlan0 > $WLAN0_CFG - configure_wpa > $WPA_CFG - configure_dhcpcd > $DHCPCD_CFG -} - - -function configure_dnsmasq() { - echo "interface=wlan0" - echo "domain-needed" - echo "bogus-priv" - echo "dhcp-range=192.168.43.2,192.168.43.20,255.255.255.0,12h" -} - - -function configure_hostapd() { - echo "interface=wlan0" - echo "driver=nl80211" - echo "ssid=$SSID" - echo "hw_mode=g" - echo "channel=$CHANNEL" - echo "wmm_enabled=0" - echo "macaddr_acl=0" - echo "auth_algs=1" - echo "ignore_broadcast_ssid=0" - echo "wpa=2" - echo "wpa_passphrase=$PASS" - echo "wpa_key_mgmt=WPA-PSK" - echo "wpa_pairwise=TKIP" - echo "rsn_pairwise=CCMP" -} - - -function is_installed() { - dpkg-query -W --showformat='${Status}' $1 | - grep "install ok installed" >/dev/null - if [ $? -eq 0 ]; then echo true; else echo false; fi -} - - -function configure_ap() { - disable_wifi - - # Install packages - ( - $(is_installed dnsmasq) && - $(is_installed hostapd) && - $(is_installed iptables-persistent) - - ) || ( - export DEBIAN_FRONTEND=noninteractive - apt-get update - apt-get install -yq dnsmasq hostapd iptables-persistent - ) - - configure_dhcpcd > $DHCPCD_CFG - configure_dnsmasq > $DNSMASQ_CFG - configure_hostapd > $HOSTAPD_CFG - - echo "DAEMON_CONF=\"/etc/hostapd/hostapd.conf\"" > /etc/default/hostapd - - # Enable IP forwarding - sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf - echo 1 > /proc/sys/net/ipv4/ip_forward - - # Enable IP masquerading - iptables -t nat -F - iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE - iptables-save > /etc/iptables/rules.v4 -} - - -function usage() { - echo "Usage: config-wifi [OPTIONS]" - echo - echo "Configure wifi as either a client or access point." - echo - echo "OPTIONS:" - echo - echo " -a Configure access point." - echo " -d Disable wifi." - echo " -r Reboot when done." - echo " -s Set SSID." - echo " -p Set password." - echo " -c Set wifi channel." - echo " -j Report wifi config as JSON data." - echo -} - - -# Parse args -while [ $# -ne 0 ]; do - case "$1" in - -a) AP=true ;; - -d) DISABLE=true ;; - -r) REBOOT=true; ;; - -s) SSID="$2"; shift ;; - -p) PASS="$2"; shift ;; - -c) CHANNEL="$2"; shift ;; - -j) query_config; exit 0 ;; - - -h) - usage - exit 0 - ;; - - *) - usage - echo "Unknown argument '$1'" - exit 1 - esac - - shift -done - - -if $DISABLE; then - disable_wifi - -else - # Check args - function clean_str() { - echo "$1" | tr -d '\n\r"' - } - - SSID=$(clean_str "$SSID") - PASS=$(clean_str "$PASS") - - LANG=C LC_ALL=C # For correct string byte length - - if [ ${#SSID} -eq 0 -o 32 -lt ${#SSID} ]; then - echo "Invalid or missing SSID '$SSID'" - exit 1 - fi - - if [ ${#PASS} -ne 0 ]; then - if [ ${#PASS} -lt 8 -o 128 -lt ${#PASS} ]; then - echo "Invalid passsword" - exit 1 - fi - fi - - echo "$CHANNEL" | grep '^[0-9]\{1,2\}' > /dev/null - if [ $? -ne 0 ]; then - echo "Invalid channel '$CHANNEL'" - exit 1 - fi - - # Execute - if $AP; then - echo "Configuring Wifi access point" - configure_ap - - else - echo "Configuring Wifi" - configure_wifi - fi -fi - - -if $REBOOT; then nohup reboot & fi diff --git a/scripts/create-sdcard-image.js b/scripts/create-sdcard-image.js new file mode 100755 index 0000000..88fdc10 --- /dev/null +++ b/scripts/create-sdcard-image.js @@ -0,0 +1,42 @@ +#!/usr/bin/env node + +const inquirer = require("inquirer"); +const { statSync } = require("fs"); +const { runCommand, initSignalHandlers, assertEffectiveRoot } = require("./util"); + +const IMAGE_FILENAME = "onefinity-controller.img"; + +initSignalHandlers(); +main(); + +async function main() { + assertEffectiveRoot(); + + const { uid } = statSync("."); + + const devices = runCommand("df -T msdos") + .split("\n") + .map(line => { + const [ disk ] = line.split(/\s+/); + return { + name: line, + value: { + disk: disk, + device: disk.replace(/s\d$/, "") + } + }; + }); + + const { disk: { disk, device } } = await inquirer.prompt({ + type: "list", + name: "disk", + choices: devices, + message: `Which device is the sdcard?` + }); + + runCommand(`diskutil unmount ${disk}`); + runCommand(`dd if=${device} of=${IMAGE_FILENAME} status=progress`, { + stdio: "inherit" + }); + runCommand(`chown ${uid} 1f.img`); +} diff --git a/scripts/demo-chroot b/scripts/demo-chroot deleted file mode 100644 index 75e7578..0000000 --- a/scripts/demo-chroot +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -ex - -ROOT="$PWD/demo" - -# Clean up on EXIT -function cleanup { - umount "$ROOT"/{dev/pts,dev,sys,proc} 2>/dev/null || true -} -trap cleanup EXIT - -# mount binds -mount --bind /dev "$ROOT/dev/" -mount --bind /sys "$ROOT/sys/" -mount --bind /proc "$ROOT/proc/" -mount --bind /dev/pts "$ROOT/dev/pts" - -chroot "$ROOT" "$@" diff --git a/scripts/download-dependencies.sh b/scripts/download-dependencies.sh index 1237d3d..dfde7ff 100755 --- a/scripts/download-dependencies.sh +++ b/scripts/download-dependencies.sh @@ -1,3 +1,6 @@ #!/bin/bash -ex -pip3 download -d python-packages -r requirements.txt +# To use, copy this file, and requirements.txt into a folder on the controller, and run this script. +# Then, copy the contents of ./installer/python-packages back to your development environment + +pip3 download -d installer/python-packages -r requirements.txt diff --git a/scripts/gplan-init-build.sh b/scripts/gplan-init-build.sh index 6ac69df..b154758 100755 --- a/scripts/gplan-init-build.sh +++ b/scripts/gplan-init-build.sh @@ -31,30 +31,20 @@ if [ ! -e $GPLAN_IMG ]; then mv $GPLAN_IMG.tmp $GPLAN_IMG fi -# Get repos -function fetch_local_repo() { - mkdir -p $1 - git -C $1 init - git -C $1 fetch -t "$2" $3 - git -C $1 reset --hard FETCH_HEAD -} - mkdir -p rpi-share || true if [ ! -e rpi-share/cbang ]; then - if [ "$CBANG_HOME" != "" ]; then - fetch_local_repo rpi-share/cbang "$CBANG_HOME" master - else - git clone https://github.com/CauldronDevelopmentLLC/cbang \ - rpi-share/cbang - fi + mkdir -p rpi-share/cbang + git -C rpi-share/cbang init + git -C rpi-share/cbang remote add origin https://github.com/CauldronDevelopmentLLC/cbang + git -C rpi-share/cbang fetch --depth 1 origin 18f1e963107ef26abe750c023355a5c40dd07853 + git -C rpi-share/cbang reset --hard FETCH_HEAD fi if [ ! -e rpi-share/camotics ]; then - if [ "$CAMOTICS_HOME" != "" ]; then - fetch_local_repo rpi-share/camotics "$CAMOTICS_HOME" master - else - git clone https://github.com/CauldronDevelopmentLLC/camotics \ - rpi-share/camotics - fi + mkdir -p rpi-share/camotics + git -C rpi-share/camotics init + git -C rpi-share/camotics remote add origin https://github.com/CauldronDevelopmentLLC/camotics + git -C rpi-share/camotics fetch --depth 1 origin ec876c80d20fc19837133087cef0c447df5a939d + git -C rpi-share/camotics reset --hard FETCH_HEAD fi diff --git a/scripts/install.sh b/scripts/install.sh index 2f565b2..d9eaa1e 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -12,45 +12,46 @@ while [ $# -gt 0 ]; do shift 1 done - if $UPDATE_PY; then systemctl stop bbctrl # Update service rm -f /etc/init.d/bbctrl - cp scripts/bbctrl.service /etc/systemd/system/ + cp ./installer/config/bbctrl.service /etc/systemd/system/ systemctl daemon-reload systemctl enable bbctrl fi if $UPDATE_AVR; then - chmod +x ./scripts/avr109-flash.py - ./scripts/avr109-flash.py src/avr/bbctrl-avr-firmware.hex + chmod +x ./installer/scripts/avr109-flash.py + ./installer/scripts/avr109-flash.py src/avr/bbctrl-avr-firmware.hex fi # Update config.txt -./scripts/edit-boot-config max_usb_current=1 -./scripts/edit-boot-config config_hdmi_boost=8 +./installer/scripts/edit-boot-config \ + disable_overscan=1 \ + framebuffer_width=1280 \ + framebuffer_height=720 \ + nohz=on \ + dtparam=sd_overclock=100 \ + max_usb_current=1 \ + config_hdmi_boost=8 \ + disable_splash=1 \ + hdmi_force_hotplug=1 \ + hdmi_group=2 \ + hdmi_mode=82 # TODO Enable GPU -#./scripts/edit-boot-config dtoverlay=vc4-kms-v3d -#./scripts/edit-boot-config gpu_mem=16 +#./installer/scripts/edit-boot-config \ +# dtoverlay=vc4-kms-v3d \ +# gpu_mem=16 #chmod ug+s /usr/lib/xorg/Xorg -# Use the full screen resolution -# grep "^framebuffer_width=1280$" /boot/config.txt >/dev/null -# if [ $? -eq 0 ]; then -# mount -o remount,rw /boot && -# sed -i 's/^\(framebuffer_.*\)$/#\1/g' /boot/config.txt -# mount -o remount,ro /boot -# REBOOT=true -# fi - # Fix camera grep dwc_otg.fiq_fsm_mask /boot/cmdline.txt >/dev/null if [ $? -ne 0 ]; then mount -o remount,rw /boot && - sed -i 's/\(.*\)/\1 dwc_otg.fiq_fsm_mask=0x3/' /boot/cmdline.txt + sed -i -E 's/(.*)/\1 dwc_otg.fiq_fsm_mask=0x3/' /boot/cmdline.txt mount -o remount,ro /boot REBOOT=true fi @@ -59,55 +60,92 @@ fi grep cgroup_memory /boot/cmdline.txt >/dev/null if [ $? -ne 0 ]; then mount -o remount,rw /boot && - sed -i 's/\(.*\)/\1 cgroup_memory=1/' /boot/cmdline.txt + sed -i -E 's/(.*)/\1 cgroup_memory=1/' /boot/cmdline.txt mount -o remount,ro /boot REBOOT=true fi # Remove Hawkeye if [ -e /etc/init.d/hawkeye ]; then - apt-get remove --purge -y hawkeye + apt-get purge -y hawkeye fi # Decrease boot delay -sed -i 's/^TimeoutStartSec=.*$/TimeoutStartSec=1/' \ +sed -i -E 's/^TimeoutStartSec=.*$/TimeoutStartSec=1/' \ /etc/systemd/system/network-online.target.wants/networking.service # Change to US keyboard layout -sed -i 's/^XKBLAYOUT="gb"$/XKBLAYOUT="us" # Comment stops change on upgrade/' \ - /etc/default/keyboard +sed -i -E 's/^XKBLAYOUT="gb"$/XKBLAYOUT="us" # Comment stops change on upgrade/' /etc/default/keyboard + +# Set the default locale to en_US +grep '^en_US.UTF-8 UTF-8' /etc/locale.gen >/dev/null +if [ $? -ne 0 ]; then + perl -pi -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/g' /etc/locale.gen + locale-gen en_US.UTF-8 + update-locale en_US.UTF-8 +fi # Setup USB stick automount -diff ./scripts/11-automount.rules /etc/udev/rules.d/11-automount.rules \ - >/dev/null +diff ./installer/config/11-automount.rules /etc/udev/rules.d/11-automount.rules >/dev/null if [ $? -ne 0 ]; then - cp ./scripts/11-automount.rules /etc/udev/rules.d/ - sed -i 's/^\(MountFlags=slave\)/#\1/' \ + cp ./installer/config/11-automount.rules /etc/udev/rules.d/ + sed -i -E 's/^(MountFlags=slave)/#\1/' \ /lib/systemd/system/systemd-udevd.service REBOOT=true fi -# Increase swap -grep 'CONF_SWAPSIZE=1000' /etc/dphys-swapfile >/dev/null -if [ $? -ne 0 ]; then - sed -i 's/^CONF_SWAPSIZE=.*$/CONF_SWAPSIZE=1000/' /etc/dphys-swapfile - REBOOT=true +# Disable disk-based swap +if [ -e /etc/dphys-swapfile ]; then + apt-get purge -y dphys-swapfile + rm -f /var/swap +fi + +# Enable zram swap +# See https://github.com/ecdye/zram-config +# The zram-config-main.zip is a downloaded snapshot of the git repository +if [ ! -e /usr/local/sbin/zram-config ]; then + modprobe -a lz4 zram + + unzip ./installer/linux-packages/zram-config-main.zip -d /tmp + /tmp/zram-config-main/install.bash + + sed -i -E 's/^(swap\s+)(lzo-rle)(.*)$/\1lz4\3/' /etc/ztab + sed -i -E 's/^(swap.*)150\s*$/\1100/' /etc/ztab + sed -i -E 's/^(log.*)$/#\1/' /etc/ztab + + sed -i -E 's/^Type=exec$/Type=simple/' /etc/systemd/system/zram-config.service + + systemctl restart zram-config + + rm -rf /tmp/zram-config fi # Install .Xresources & .xinitrc -cp scripts/Xresources ~pi/.Xresources +cp ./installer/config/Xresources ~pi/.Xresources chown pi:pi ~pi/.Xresources -cp scripts/xinitrc ~pi/.xinitrc +cp ./installer/config/xinitrc ~pi/.xinitrc chmod +x ~pi/.xinitrc chown pi:pi ~pi/.xinitrc -#Configure the "ratpoison" window manager +# Configure the "ratpoison" window manager if [ ! -e ~pi/.ratpoisonrc ]; then - cp scripts/ratpoisonrc ~pi/.ratpoisonrc + cp ./installer/config/ratpoisonrc ~pi/.ratpoisonrc chmod 644 ~pi/.ratpoisonrc chown pi:pi ~pi/.ratpoisonrc fi +# Configure the Plymouth graphical bootloader with the Onefinity theme +rm -rf /usr/share/plymouth/themes/buildbotics +rm -rf /usr/share/plymouth/themes/onefinity +mkdir -p /usr/share/plymouth/themes/onefinity/ +cp -av ./installer/splash/* /usr/share/plymouth/themes/onefinity/ +plymouth-set-default-theme -R onefinity + +grep 'quiet splash plymouth.ignore-serial-consoles logo.nologo' /boot/cmdline.txt >/dev/null +if [ $? -ne 0 ]; then + echo -n " quiet splash plymouth.ignore-serial-consoles logo.nologo" >> /boot/cmdline.txt +fi + # Install bbserial MODSRC=src/bbserial/bbserial.ko MODDST=/lib/modules/$(uname -r)/kernel/drivers/tty/serial/bbserial.ko @@ -119,46 +157,51 @@ if [ $? -ne 0 ]; then fi # Install rc.local -cp scripts/rc.local /etc/ +cp ./installer/config/rc.local /etc/ # Install bbctrl if $UPDATE_PY; then - service bbctrl stop + systemctl stop bbctrl rm -rf /usr/local/lib/python*/dist-packages/bbctrl-* # Ensure python dependencies are installed - pip3 install --no-index --find-links python-packages -r requirements.txt + pip3 install --no-index --find-links installer/python-packages -r requirements.txt ./setup.py install --force HTTP_DIR=$(find /usr/local/lib/ -type d -name "http") chmod 777 $HTTP_DIR - service bbctrl restart + systemctl restart bbctrl fi +# Install the service that turns off the screen during shutdown +cp ./installer/config/bbctrl-poweroff.service /etc/systemd/system/ +systemctl daemon-reload +systemctl enable bbctrl-poweroff + # Expand the file system if necessary -chmod +x ./scripts/resize_root_fs.sh -./scripts/resize_root_fs.sh +chmod +x ./installer/scripts/resize_root_fs.sh +./installer/scripts/resize_root_fs.sh if [ $? -eq 0 ]; then REBOOT=true fi # Install our logrotate config -cp ./scripts/bbctrl-logrotate /etc/logrotate.d/bbctrl +cp ./installer/config/bbctrl-logrotate /etc/logrotate.d/bbctrl chown root:root /etc/logrotate.d/bbctrl # Ensure logrotate runs on every boot (for systems with no network, thus bad clock) if [ ! -e /etc/cron.d/reboot ]; then - cp ./scripts/cron_d_reboot /etc/cron.d/reboot + cp ./installer/config/cron_d_reboot /etc/cron.d/reboot mkdir -p /etc/cron.reboot - cp ./scripts/cron_reboot_logrotate /etc/cron.reboot/logrotate + cp ./installer/config/cron_reboot_logrotate /etc/cron.reboot/logrotate fi # Delete some cookies that were left behind in older images -chmod +x ./scripts/delete-cookies.py -./scripts/delete-cookies.py +chmod +x ./installer/scripts/delete-cookies.py +./installer/scripts/delete-cookies.py pkill -HUP chromium # Force Chromium to restart, to see the cookie changes # Get rid of some old files that were left behind in older images diff --git a/scripts/log-position-to-gcode b/scripts/log-position-to-gcode deleted file mode 100644 index 7597fb4..0000000 --- a/scripts/log-position-to-gcode +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python3 - -import json -import sys - -p = [0, 0, 0] - - -print('F400 G21') - -for line in sys.stdin: - try: - if not line.startswith('I:Comm:> '): continue - line = line[9:] - - data = json.loads(line) - - changed = False - for axis in range(3): - var = 'xyz'[axis] + 'p' - if var in data: - p[axis] = data[var] - changed = True - - if changed: print('G1 X%d Y%d Z%d' % tuple(p)) - - except json.decoder.JSONDecodeError: pass diff --git a/scripts/prep-controller-for-imaging.js b/scripts/prep-controller-for-imaging.js new file mode 100755 index 0000000..3616c52 --- /dev/null +++ b/scripts/prep-controller-for-imaging.js @@ -0,0 +1,66 @@ +#!/usr/bin/env node + +const inquirer = require("inquirer"); +const { runCommand, logErrorAndExit, initSignalHandlers, assertInstalled, info } = require("./util"); + +const PACKAGES_TO_PURGE = [ + "dphys-swapfile", + "gdb", + "geoip-database", + "gnome-icon-theme", + "hostapd", + "libfreetype6-dev", + "libglib2.0-data", + "libraspberrypi-doc", + "mlocate", + "triggerhappy", + "zip", +]; + +let controller; + +initSignalHandlers(); +main(); + +async function main() { + try { + controller = process.argv[2] ?? "onefinity"; + + assertInstalled([ "sshpass", "ssh" ]); + + const { password } = await inquirer.prompt({ + type: "password", + name: "password", + message: `What is the password for ${controller}?` + }); + + process.env.SSHPASS = password; + + ssh("echo sudo access confirmed", { + onError: () => { + logErrorAndExit([ + "You must configure the 'bbmc` user for no-password sudo.", + "The secret is 'NOPASSWD:ALL'", + "See: https://www.cyberciti.biz/faq/linux-unix-running-sudo-command-without-a-password/" + ].join("\n")); + } + }); + + ssh("apt-get update"); + ssh(`apt-get purge -y ${PACKAGES_TO_PURGE.join(" ")}`); + ssh("apt-get autoremove -y"); + ssh("touch /root/.prep-controller-completed"); + ssh("sed -i -E 's|NOPASSWD:ALL|ALL|' /etc/sudoers"); + } catch (error) { + logErrorAndExit("An unexpected error occurred", error); + } +} + +function ssh(command, options) { + info(`Running "${command}"`); + + return runCommand(`sshpass -e /usr/bin/ssh ${controller} "sudo ${command}"`, { + ...options, + stdio: "inherit" + }); +} \ No newline at end of file diff --git a/scripts/prep-sd-image.js b/scripts/prep-sd-image.js new file mode 100755 index 0000000..a85c6e8 --- /dev/null +++ b/scripts/prep-sd-image.js @@ -0,0 +1,479 @@ +#!/usr/bin/env node + +const inquirer = require("inquirer"); +const merge = require("lodash.merge"); +const { resolve } = require("path"); +const { + statSync, + rmdirSync, + copyFileSync, + writeFileSync, + readFileSync, + existsSync, + rmSync +} = require("fs"); +const { exit } = require("process"); +const { glob } = require("glob"); +const packageJSON = require("../package.json"); +const config_defaults = require("../src/resources/onefinity_defaults.json"); +const { + info, + runCommand, + logErrorAndExit, + assertOS, + assertEffectiveRoot, + assertFileExists, + assertInstalled, + initSignalHandlers, + doFinally +} = require("./util"); + +const variant_defaults = { + machinist_x35: require("../src/resources/onefinity_machinist_x35_defaults.json"), + woodworker_x35: require("../src/resources/onefinity_woodworker_x35_defaults.json"), + woodworker_x50: require("../src/resources/onefinity_woodworker_x50_defaults.json"), + journeyman_x50: require("../src/resources/onefinity_journeyman_x50_defaults.json") +}; + +const ORIGINAL_IMAGE_FILENAME = "onefinity-controller.img"; + +const REQUIRED_TOOLS = [ + "rsync", + "parted", + "losetup", + "tune2fs", + "md5sum", + "e2fsck", + "resize2fs", + "xz", + "zerofree" +]; + +const SYSTEM_FILES = [ + "/tmp/*", + "/usr/**/__pycache__", + "/usr/**/*.py[co]", + "/usr/share/doc/*", + "/var/@(cache|backups|log|tmp)/*", + "/var/lib/apt/lists/*", + "/var/lib/bbctrl/@(config|gamepads).json", + "/var/lib/bbctrl/@(firmware|plans|upload)/*", + "/var/lib/dhcpcd5/*", + "/var/swap", +]; + +const USER_FILES = [ + ".bash_history", + ".cache", + ".config", + ".lesshst", + ".local", + ".nano", + ".pki", + ".prep-controller-completed", + ".ratpoison_history", + ".viminfo", + ".wget-hsts", + ".Xauthority", + "Downloads", + "splash.png" +]; + +initSignalHandlers(); +main(); + +async function main() { + let meta; + + await doFinally(async () => { + assertOS(); + assertEffectiveRoot(); + assertFileExists(ORIGINAL_IMAGE_FILENAME); + assertInstalled(REQUIRED_TOOLS); + + const meta = prepareImage(); + + await attachToLoopback(meta, "root", async (loopback) => { + checkAndRepair(loopback); + await prepareFilesystem(loopback); + }); + + await attachToLoopback(meta, "root", (loopback) => { + checkAndRepair(loopback); + shrinkFilesystem(loopback); + shrinkPartition(loopback, meta); + zerofree(loopback); + }); + + truncateImage(meta); + await configureAutoExpand(meta); + compress(meta); + moveImageFiles(meta); + }, () => { + if (meta) { + if (existsSync(meta.imageFilePath)) { + rmSync(meta.imageFilePath); + } + + if (existsSync(meta.compressedImageFilePath)) { + rmSync(meta.compressedImageFilePath); + } + } + }); +} + +function createImageFileCopy() { + const target = runCommand("mktemp --tmpdir --suffix=.img onefinity-raspi-XXXXXXXXXX"); + + info(`Copying ${ORIGINAL_IMAGE_FILENAME} to ${target}...`); + + runCommand(`rsync --times --progress ${ORIGINAL_IMAGE_FILENAME} ${target}`, { + stdio: "inherit", + onError: error => { + logErrorAndExit(`Failed to copy ${ORIGINAL_IMAGE_FILENAME} to ${target}`, error); + } + }); + + return target; +} + +async function attachToLoopback(meta, partition, cb) { + info("Attaching the image to a loopback device..."); + + let loopback; + await doFinally( + async () => { + const start = meta.partitions[partition].start; + loopback = runCommand(`losetup -f --show -o "${start}" "${meta.imageFilePath}"`); + + await cb(loopback); + }, + () => { + if (loopback) { + runCommand(`losetup -d ${loopback}`); + } + } + ); +} + +function prepareImage() { + const imageFilePath = createImageFileCopy(); + + info("Gathering info about the image..."); + const { size: initialImageSize } = statSync(imageFilePath); + + const partedOutput = runCommand(`parted -s "${imageFilePath}" unit B print`, { + onError: error => { + logErrorAndExit(` + Error fetching disk image info. + + 'parted' failed with exitcode ${error.status} + + Run 'parted ${imageFilePath} unit B print' manually to investigate + `, error); + } + }); + + const [ boot, root ] = partedOutput + .split("\n") + .slice(-2) + .map(line => line + .trim() + .split(/\s+/) + .map(col => parseInt(col) || col) + ) + .map(columns => ({ + number: columns[0], + start: columns[1], + end: columns[2], + size: columns[3], + type: columns[4], + filesystem: columns[5], + flags: columns[6] + })); + + return { + initialImageSize, + imageFilePath, + compressedImageFilePath: getCompressedFilename(imageFilePath), + partitions: { + boot, + root + } + }; +} + +function checkAndRepair(loopback) { + info("Checking the filesystem..."); + + let success = true; + + runCommand(`e2fsck -pf "${loopback}"`, { + stdio: "inherit", + onError: error => { + success = error.status < 4; + if (error.status >= 4) { + info(`First e2fsck returned '${error.status}'.`); + } + } + }); + + if (!success) { + info("Trying harder to fix the image"); + runCommand(`e2fsck -y "${loopback}"`, { + stdio: "inherit", + onError: error => { + success = error.status < 4; + if (error.status >= 4) { + info(`Second e2fsck returned '${error.status}'.`); + } + } + }); + } + + if (!success) { + info("The filesystem must be pretty damaged. Trying again with the alternate superblock."); + runCommand(`e2fsck -yf -b 32768 "${loopback}"`, { + stdio: "inherit", + onError: error => { + if (error.status >= 4) { + logErrorAndExit(`The final e2fsck attempt returned '${error.status}'. Giving up.`, error); + } + } + }); + } +} + +async function prepareFilesystem(loopback) { + await mountLoopback(loopback, async mountpoint => { + info("Removing unnecessary files from the filesystem..."); + + if (!existsSync(`${mountpoint}/root/.prep-controller-completed`)) { + const { proceed } = await inquirer.prompt({ + type: "confirm", + name: "proceed", + message: [ + "It looks like 'prep-controller-for-imaging.js' has not been run on this image.", + "Do you want to proceed anyway?" + ].join("\n") + }); + + if (!proceed) { + exit(1); + } + } + + scrubFiles(mountpoint, SYSTEM_FILES); + scrubUserFiles(mountpoint, "/root"); + scrubUserFiles(mountpoint, "/home/bbmc"); + scrubUserFiles(mountpoint, "/home/pi"); + + info("Injecting files..."); + + copyFileSync( + resolve(`${__dirname}/../installer/gcode/Team Onefinity.ngc`), + resolve(`${mountpoint}/var/lib/bbctrl/upload/Team Onefinity.ngc`) + ); + + writeFileSync(`${mountpoint}/var/lib/bbctrl/config.json`, + JSON.stringify(merge( + {}, + config_defaults, + variant_defaults.woodworker_x35 + ), null, 4) + ); + + const virtualKeyboardZip = resolve(`${__dirname}/../installer/linux-packages/virtualKeyboard.zip`); + const userPiHome = resolve(`${mountpoint}/home/pi`); + runCommand(`unzip "${virtualKeyboardZip}" -d "${userPiHome}"`); + + runCommand(`chown -R 1000:1000 ${userPiHome}/.config`); + }); +} + +function shrinkFilesystem(loopback) { + info(`Shrinking the root filesystem`); + + // We run the shrink step multiple times, because + // each time, resize2fs can shrink it a little more, + // until eventually it can't. + // + // TODO: Switch to using pipes to both display the output and capture it + // We can then look at the output to determine when to stop, rather than + // using a fixed count for loop. + // See: https://stackoverflow.com/questions/22337446/how-to-wait-for-a-child-process-to-finish-in-node-js + for (let i = 0; i < 5; ++i) { + runCommand(`resize2fs -p "${loopback}" -M`, { + stdio: "inherit", + onError: error => { + logErrorAndExit("Error while resizing", error); + } + }); + } +} + +function shrinkPartition(loopback, meta) { + info(`Shrinking the root partition`); + + const tune2fsOutput = runCommand(`tune2fs -l "${loopback}"`, { + onError: error => logErrorAndExit("tune2fs failed. Unable to shrink this type of image", error) + }); + + const root = meta.partitions.root; + const [ , currentSize ] = tune2fsOutput.match(/^Block count:\s+(\d+)/m); + const [ , blockSize ] = tune2fsOutput.match(/^Block size:\s+(\d+)/m); + const newSize = parseInt(currentSize) * parseInt(blockSize); + const newEnd = root.start + newSize; + + runCommand(`parted -s -a minimal "${meta.imageFilePath}" rm "${root.number}"`, { + onError: error => logErrorAndExit("parted failed while deleting root partition", error) + }); + + runCommand(`parted -s "${meta.imageFilePath}" unit B mkpart "${root.type}" "${root.start}" "${newEnd}"`, { + onError: error => logErrorAndExit("parted failed while recreating the root partition", error) + }); +} + +function zerofree(loopback) { + info(`Zeroing out empty blocks for better compression...`); + info("(This will take a bit - it can look like it's hung, have patience)"); + + runCommand(`zerofree -v "${loopback}"`, { + stdio: "inherit" + }); +} + +function truncateImage(meta) { + info(`Shrinking the image`); + + const partedOutput = runCommand(`parted -sm "${meta.imageFilePath}" unit B print free`, { + onError: error => logErrorAndExit("parted failed while shrinking the image", error) + }); + + // The output of the parted command above will look something like this: + // + // BYT; + // image.img:31914983424B:file:512:512:msdos::; + // 1:16384B:1048575B:1032192B:free; + // 1:1048576B:135266303B:134217728B:fat32::boot; + // 2:135266304B:2002096639B:1866830336B:ext4::; + // 1:2002096640B:31914983423B:29912886784B:free; + // + // The format is: + // "number":"begin":"end":"size":"filesystem-type":"partition-name":"flags-set"; + // + // We're interested in the last line only, to determine + // the start of the free space in the image, after the partitions + + const [ , startOfFreeSpace, , , type ] = partedOutput + .split("\n") + .at(-1) + .replace(/^([^;]+);.*$/, "$1") + .split(":") + .map(col => parseInt(col) || col); + + if (type !== "free") { + info("There is no free space after the root partition, skipping image shrinking."); + return; + } + + runCommand(`truncate -s "${startOfFreeSpace}" "${meta.imageFilePath}"`); + + const { size: newSize } = statSync(meta.imageFilePath); + info(`Shrank the image from ${meta.initialImageSize} to ${newSize}`); +} + +async function configureAutoExpand(meta) { + info("Configuring the root partition to autoexpand on first boot..."); + + await attachToLoopback(meta, "boot", async (loopback) => { + await mountLoopback(loopback, mountpoint => { + let cmdline = readFileSync(`${mountpoint}/cmdline.txt`, { encoding: "utf8" }); + if (cmdline.match(/init_resize/)) { + logErrorAndExit("init_resize is already in /boot/cmdline.txt"); + } + + cmdline = `${cmdline.trim()} init=/usr/lib/raspi-config/init_resize.sh`; + writeFileSync(`${mountpoint}/cmdline.txt`, cmdline, { encoding: "utf8" }); + }); + }); +} + +function compress(meta) { + info(`Compressing the image`); + + runCommand(`xz -k9veT0 ${meta.imageFilePath}`, { + stdio: "inherit" + }); + + const { size: oldSize } = statSync(meta.imageFilePath); + const compressed = getCompressedFilename(meta.imageFilePath); + + const { size: newSize } = statSync(compressed); + info(`Compressed the image from ${oldSize} to ${newSize}`); +} + +function moveImageFiles(meta) { + info("Finalizing..."); + + const finalImageName = `onefinity-raspi-${packageJSON.version}.img`; + const finalCompressedImageName = getCompressedFilename(finalImageName); + runCommand(`mv ${meta.imageFilePath} ${finalImageName}`); + runCommand(`mv ${meta.compressedImageFilePath} ${finalCompressedImageName}`); +} + +function getCompressedFilename(target) { + return `${target}.xz`; +} + +async function mountLoopback(loopback, cb) { + let mountpoint; + + await doFinally(async () => { + mountpoint = runCommand("mktemp --tmpdir -d onefinity-raspi-root-XXXXXXXXXX"); + + runCommand(`mount ${loopback} ${mountpoint}`); + await cb(mountpoint); + }, () => { + if (mountpoint) { + runCommand(`umount "${mountpoint}"`); + rmdirSync(mountpoint); + } + }); +} + +function scrubFiles(mountpoint, patterns) { + for (const _pattern of patterns) { + const { pattern, ignore } = (typeof _pattern === "string") + ? { pattern: _pattern } + : _pattern; + + const options = { + dot: true, + cwd: mountpoint, + root: mountpoint, + ignore + }; + + const matches = glob.sync(pattern, options); + + for (const match of matches) { + runCommand(`rm -rvf "${match}"`, { + stdio: "inherit" + }); + } + } +} + +function scrubUserFiles(mountpoint, homedir) { + scrubFiles(mountpoint, USER_FILES.map(item => { + if (typeof item === "string") { + return `${homedir}/${item}`; + } + + return { + ...item, + pattern: `${homedir}/${item.pattern}`, + }; + })); +} diff --git a/scripts/reset-video b/scripts/reset-video deleted file mode 100644 index 94b46cd..0000000 --- a/scripts/reset-video +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import subprocess -import os.path -import time - -if not os.path.exists('/dev/video0'): - print('/dev/video0 not found') - sys.exit(1) - -p = subprocess.Popen('udevadm info -q path /dev/video0'.split(), - stdout = subprocess.PIPE) -s = p.communicate()[0].decode('utf-8') -dev = s.split('/')[7] - -with open('/sys/bus/usb/drivers/usb/unbind', 'w') as f: - f.write(dev) - -time.sleep(1) - -with open('/sys/bus/usb/drivers/usb/bind', 'w') as f: - f.write(dev) diff --git a/scripts/resize2fs_once b/scripts/resize2fs_once deleted file mode 100644 index 38a4d47..0000000 --- a/scripts/resize2fs_once +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh -### BEGIN INIT INFO -# Provides: resize2fs_once -# Required-Start: -# Required-Stop: -# Default-Start: 3 -# Default-Stop: -# Short-Description: Resize the root filesystem to fill partition -# Description: -### END INIT INFO -. /lib/lsb/init-functions -case "$1" in - start) - log_daemon_msg "Starting resize2fs_once" - ROOT_DEV=$(findmnt / -o source -n) && - resize2fs $ROOT_DEV && - update-rc.d resize2fs_once remove && - rm /etc/init.d/resize2fs_once && - log_end_msg $? - ;; - *) - echo "Usage: $0 start" >&2 - exit 3 - ;; -esac diff --git a/scripts/rpi-chroot.sh b/scripts/rpi-chroot.sh index 35e15be..ef52ca6 100755 --- a/scripts/rpi-chroot.sh +++ b/scripts/rpi-chroot.sh @@ -1,7 +1,6 @@ #!/bin/bash -ex ROOT="$PWD/rpi-root" -LOOP=12 if [ $# -lt 1 ]; then echo "Usage: $0 " @@ -9,7 +8,8 @@ if [ $# -lt 1 ]; then fi IMAGE="$1" -LOOP_DEV=/dev/loop${LOOP} +LOOP_BOOT= +LOOP_ROOT= EXEC= if [ $# -gt 1 ]; then @@ -26,25 +26,28 @@ fi # Clean up on EXIT function cleanup { umount "$ROOT"/{dev/pts,dev,sys,proc,boot,mnt/host,} 2>/dev/null || true - losetup -d $LOOP_DEV 2>/dev/null || true + losetup -d $LOOP_BOOT 2>/dev/null || true + losetup -d $LOOP_ROOT 2>/dev/null || true rmdir "$ROOT" 2>/dev/null || true } trap cleanup EXIT -# set up image as loop device -losetup $LOOP_DEV "$IMAGE" -partprobe $LOOP_DEV +LOOP_BOOT=`losetup -f` +losetup -o 4194304 $LOOP_BOOT "$IMAGE" + +LOOP_ROOT=`losetup -f` +losetup -o 48234496 $LOOP_ROOT "$IMAGE" # check and fix filesystems -fsck -f ${LOOP_DEV}p1 -fsck -f ${LOOP_DEV}p2 +fsck -f $LOOP_BOOT +fsck -f $LOOP_ROOT # make dir mkdir -p "$ROOT" # mount partition -mount -o rw ${LOOP_DEV}p2 -t ext4 "$ROOT" -mount -o rw ${LOOP_DEV}p1 "$ROOT/boot" +mount -o rw $LOOP_ROOT -t ext4 "$ROOT" +mount -o rw $LOOP_BOOT "$ROOT/boot" # mount binds mount --bind /dev "$ROOT/dev/" diff --git a/scripts/ssh-bbctrl b/scripts/ssh-bbctrl deleted file mode 100644 index ad9ed9a..0000000 --- a/scripts/ssh-bbctrl +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -USER=bbmc -HOST=bbctrl.local - -if [ $# -eq 1 ]; then - if [[ "$1" = *@ ]]; then - LOGIN="$1" - else - LOGIN=$USER@"$1" - fi -else - LOGIN=$USER@$HOST -fi - -ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$LOGIN" diff --git a/scripts/svg2abs.js b/scripts/svg2abs.js deleted file mode 100644 index 7cfc6dd..0000000 --- a/scripts/svg2abs.js +++ /dev/null @@ -1,64 +0,0 @@ -function convertToAbsolute(path) { - var x0, y0, x1, y1, x2, y2, segs = path.pathSegList; - - for (var x = 0, y = 0, i = 0, len = segs.numberOfItems; i < len; i++) { - var seg = segs.getItem(i), c = seg.pathSegTypeAsLetter; - - if (/[MLHVCSQTA]/.test(c)){ - if ('x' in seg) x = seg.x; - if ('y' in seg) y = seg.y; - - } else { - if ('x1' in seg) x1 = x + seg.x1; - if ('x2' in seg) x2 = x + seg.x2; - if ('y1' in seg) y1 = y + seg.y1; - if ('y2' in seg) y2 = y + seg.y2; - if ('x' in seg) x += seg.x; - if ('y' in seg) y += seg.y; - - switch(c) { - case 'm': - segs.replaceItem(path.createSVGPathSegMovetoAbs(x, y), i); - break; - case 'l': - segs.replaceItem(path.createSVGPathSegLinetoAbs(x, y), i); - break; - case 'h': - segs.replaceItem(path.createSVGPathSegLinetoHorizontalAbs(x), i); - break; - case 'v': - segs.replaceItem(path.createSVGPathSegLinetoVerticalAbs(y), i); - break; - case 'c': - segs.replaceItem( - path.createSVGPathSegCurvetoCubicAbs(x, y, x1, y1, x2, y2), i); - break; - case 's': - segs.replaceItem( - path.createSVGPathSegCurvetoCubicSmoothAbs(x, y, x2, y2), i); - break; - case 'q': - segs.replaceItem( - path.createSVGPathSegCurvetoQuadraticAbs(x, y, x1, y1), i); - break; - case 't': - segs.replaceItem( - path.createSVGPathSegCurvetoQuadraticSmoothAbs(x, y), i); - break; - case 'a': - segs.replaceItem( - path.createSVGPathSegArcAbs(x, y, seg.r1, seg.r2, seg.angle, - seg.largeArcFlag, seg.sweepFlag), i); - break; - - case 'z': case 'Z': - x = x0; - y = y0; - break; - } - } - - // Record the start of a subpath - if (c == 'M' || c == 'm') x0 = x, y0 = y; - } -} diff --git a/scripts/util.js b/scripts/util.js new file mode 100644 index 0000000..1685b52 --- /dev/null +++ b/scripts/util.js @@ -0,0 +1,161 @@ +const { execSync } = require("child_process"); +const { statSync } = require("fs"); +const { exit } = require("process"); + +module.exports = { + info, + runCommand, + logErrorAndExit, + registerSignalHandler, + initSignalHandlers, + assertOS, + assertEffectiveRoot, + assertFileExists, + assertInstalled, + doFinally +}; + +let signalHandlers = []; + +function registerSignalHandler(cb) { + signalHandlers.push(cb); + + return () => (signalHandlers = signalHandlers.filter(h => h === cb)); +} + +function initSignalHandlers() { + process.on("SIGTERM", handle); + process.on("SIGINT", handle); + process.on("SIGHUP", handle); +} + +function handle(signal) { + console.log(`Received ${signal}`); + + for (const handler of signalHandlers) { + handler(signal); + } +} + +function info(msg) { + console.log(`\n${msg}`); +} + +function runCommand(command, _options) { + const options = { + encoding: "utf8", + ..._options, + shell: true + }; + + const { onError } = options; + delete options["onError"]; + + try { + const result = execSync(command, options); + + return (typeof result === "string") + ? result.trim() + : result; + } catch (error) { + if (onError) { + onError(error); + } else { + throw error; + } + } +} + +function logErrorAndExit(msg, error) { + const lines = msg.split("\n"); + + // Get rid of leading blank lines + while (lines.length) { + if (lines[0].trim().length == 0) { + lines.shift(); + } else { + break; + } + } + + // Get rid of trailing blank lines + while (lines.length) { + if (lines.at(-1).trim().length == 0) { + lines.pop(); + } else { + break; + } + } + + const [ whitespace ] = lines[0].match(/^\s*/); + + console.error(lines + .map(line => line.replace(whitespace, "").trimEnd()) + .join("\n") + ); + + if (error) { + console.error("Error:", JSON.stringify({ + name: error.name, + code: error.code, + status: error.status, + signal: error.signal, + error: error.error, + pid: error.pid, + output: error.output, + msg: error.msg, + message: error.message + }, null, 4)); + } + + exit(1); +} + +function assertOS() { + if (process.platform !== "linux") { + logErrorAndExit("This script requires linux."); + } +} + +function assertEffectiveRoot() { + if (process.geteuid() !== 0) { + logErrorAndExit("Please run this script as root"); + } +} + +function assertFileExists(file) { + const stats = statSync(file); + if (!stats.isFile) { + logErrorAndExit(`${file} does not exist`); + } +} + +function assertInstalled(tools) { + const missingTools = []; + + for (const tool of tools) { + runCommand(`command -v ${tool}`, { + onError: () => missingTools.push(tool) + }); + } + + if (missingTools.length) { + logErrorAndExit(` + This script requires some tools that are not installed. + + Install them via: + apt-get install -y ${missingTools.join(" ")} + `); + } +} + +async function doFinally(doHandler, finallyHandler) { + const unregister = registerSignalHandler(finallyHandler); + + try { + await doHandler(); + } finally { + unregister(); + await finallyHandler(); + } +} \ No newline at end of file diff --git a/scripts/xorg.conf b/scripts/xorg.conf deleted file mode 100644 index acbd369..0000000 --- a/scripts/xorg.conf +++ /dev/null @@ -1,3 +0,0 @@ -Section "ServerFlags" - Option "DontVTSwitch" "on" -EndSection diff --git a/setup.py b/setup.py index e3bd034..5005f9b 100755 --- a/setup.py +++ b/setup.py @@ -18,8 +18,6 @@ setup( package_dir={'': 'src/py'}, packages=[ 'bbctrl', - 'inevent', - 'lcd', 'camotics', 'iw_parse' ], @@ -30,15 +28,13 @@ setup( ] }, scripts=[ - 'scripts/update-bbctrl', - 'scripts/upgrade-bbctrl', - 'scripts/sethostname', - 'scripts/reset-video', - 'scripts/config-wifi', - 'scripts/config-screen', - 'scripts/edit-config', - 'scripts/edit-boot-config', - 'scripts/browser', + 'installer/scripts/update-bbctrl', + 'installer/scripts/upgrade-bbctrl', + 'installer/scripts/sethostname', + 'installer/scripts/config-wifi', + 'installer/scripts/edit-config', + 'installer/scripts/edit-boot-config', + 'installer/scripts/browser', ], install_requires=[ 'tornado', diff --git a/src/avr/src/config.h b/src/avr/src/config.h index 7b01aac..702fb2a 100644 --- a/src/avr/src/config.h +++ b/src/avr/src/config.h @@ -201,7 +201,7 @@ enum { #define I2C_DEV TWIC #define I2C_ISR TWIC_TWIS_vect #define I2C_ADDR 0x2b -#define I2C_MAX_DATA 8 +#define I2C_MAX_DATA 16 // Motor diff --git a/src/avr/src/i2c.c b/src/avr/src/i2c.c index d115a1b..5832d3c 100644 --- a/src/avr/src/i2c.c +++ b/src/avr/src/i2c.c @@ -62,7 +62,9 @@ static void _i2c_end_command() { static void _i2c_command_byte(uint8_t byte) { - i2c.data[i2c.length++] = byte; + if (i2c.length < I2C_MAX_DATA) { + i2c.data[i2c.length++] = byte; + } } diff --git a/src/avr/src/lcd.c b/src/avr/src/lcd.c deleted file mode 100644 index 7802eb4..0000000 --- a/src/avr/src/lcd.c +++ /dev/null @@ -1,143 +0,0 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -#include "lcd.h" -#include "rtc.h" -#include "hardware.h" -#include "command.h" - -#include -#include -#include - -#include - - -void lcd_init(uint8_t addr) { - // Enable I2C master - TWIC.MASTER.BAUD = F_CPU / 2 / 100000 - 5; // 100 KHz - TWIC.MASTER.CTRLA = TWI_MASTER_ENABLE_bm; - TWIC.MASTER.CTRLB = TWI_MASTER_TIMEOUT_DISABLED_gc; - TWIC.MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc; - - _delay_ms(50); - lcd_nibble(addr, 3 << 4); // Home - _delay_ms(50); - lcd_nibble(addr, 3 << 4); // Home - _delay_ms(50); - lcd_nibble(addr, 3 << 4); // Home - lcd_nibble(addr, 2 << 4); // 4-bit - - lcd_write(addr, - LCD_FUNCTION_SET | LCD_2_LINE | LCD_5x8_DOTS | LCD_4_BIT_MODE, 0); - lcd_write(addr, LCD_DISPLAY_CONTROL | LCD_DISPLAY_ON, 0); - lcd_write(addr, LCD_ENTRY_MODE_SET | LCD_ENTRY_SHIFT_INC, 0); - - lcd_write(addr, LCD_CLEAR_DISPLAY, 0); - lcd_write(addr, LCD_RETURN_HOME, 0); -} - - -static void _master_wait() { -#ifdef __AVR__ - while (!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm)) continue; -#endif -} - - -static void _write_i2c(uint8_t addr, uint8_t data) { - data |= BACKLIGHT_BIT; - - TWIC.MASTER.ADDR = addr << 1; - _master_wait(); - - TWIC.MASTER.DATA = data; - _master_wait(); - - TWIC.MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc; - - _delay_us(100); -} - - -void lcd_nibble(uint8_t addr, uint8_t data) { - _write_i2c(addr, data); - _write_i2c(addr, data | ENABLE_BIT); - _delay_us(500); - _write_i2c(addr, data & ~ENABLE_BIT); - _delay_us(100); -} - - -void lcd_write(uint8_t addr, uint8_t cmd, uint8_t flags) { - lcd_nibble(addr, flags | (cmd & 0xf0)); - lcd_nibble(addr, flags | ((cmd << 4) & 0xf0)); -} - - -void lcd_goto(uint8_t addr, uint8_t x, uint8_t y) { - static uint8_t row[] = {0, 64, 20, 84}; - lcd_write(addr, LCD_SET_DDRAM_ADDR | (row[y] + x), 0); -} - - -void lcd_putchar(uint8_t addr, uint8_t c) { - lcd_write(addr, c, REG_SELECT_BIT); -} - - -void lcd_pgmstr(uint8_t addr, const char *s) { - while (true) { - char c = pgm_read_byte(s++); - if (!c) break; - lcd_putchar(addr, c); - } -} - - -void _splash(uint8_t addr) { - lcd_init(addr); - lcd_goto(addr, 1, 1); - lcd_pgmstr(addr, PSTR("Controller booting")); - lcd_goto(addr, 3, 2); - lcd_pgmstr(addr, PSTR("Please wait...")); -} - - -void lcd_splash() { - wdt_disable(); - _splash(0x27); - _splash(0x3f); - wdt_enable(WDTO_250MS); -} - - -void lcd_rtc_callback() { - // Display the splash if we haven't gotten any commands in 1sec since boot - if (!command_is_active() && rtc_get_time() == 1000) - lcd_splash(); -} diff --git a/src/avr/src/lcd.h b/src/avr/src/lcd.h deleted file mode 100644 index b7369f0..0000000 --- a/src/avr/src/lcd.h +++ /dev/null @@ -1,103 +0,0 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -#pragma once - -#include "pgmspace.h" - -#include - - -// Control flags -enum { - REG_SELECT_BIT = 1 << 0, - READ_BIT = 1 << 1, - ENABLE_BIT = 1 << 2, - BACKLIGHT_BIT = 1 << 3, -}; - - -// Commands -enum { - LCD_CLEAR_DISPLAY = 1 << 0, - LCD_RETURN_HOME = 1 << 1, - LCD_ENTRY_MODE_SET = 1 << 2, - LCD_DISPLAY_CONTROL = 1 << 3, - LCD_CURSOR_SHIFT = 1 << 4, - LCD_FUNCTION_SET = 1 << 5, - LCD_SET_CGRAM_ADDR = 1 << 6, - LCD_SET_DDRAM_ADDR = 1 << 7, -}; - - -// Entry Mode Set flags -#define LCD_ENTRY_SHIFT_DISPLAY (1 << 0) -#define LCD_ENTRY_SHIFT_INC (1 << 1) -#define LCD_ENTRY_SHIFT_DEC (0 << 1) - - -// Display Control flags -#define LCD_BLINK_ON (1 << 0) -#define LCD_BLINK_OFF (0 << 0) -#define LCD_CURSOR_ON (1 << 1) -#define LCD_CURSOR_OFF (0 << 1) -#define LCD_DISPLAY_ON (1 << 2) -#define LCD_DISPLAY_OFF (0 << 2) - - -// Cursor Shift flags -#define LCD_SHIFT_RIGHT (1 << 2) -#define LCD_SHIFT_LEFT (0 << 2) -#define LCD_SHIFT_DISPLAY (1 << 3) -#define LCD_SHIFT_CURSOR (0 << 3) - - -// Function Set flags -#define LCD_5x11_DOTS (1 << 2) -#define LCD_5x8_DOTS (0 << 2) -#define LCD_2_LINE (1 << 3) -#define LCD_1_LINE (0 << 3) -#define LCD_8_BIT_MODE (1 << 4) -#define LCD_4_BIT_MODE (0 << 4) - - -// Text justification flags -enum { - JUSTIFY_LEFT = 0, - JUSTIFY_RIGHT = 1, - JUSTIFY_CENTER = 2, -}; - - -void lcd_init(uint8_t addr); -void lcd_nibble(uint8_t addr, uint8_t data); -void lcd_write(uint8_t addr, uint8_t cmd, uint8_t flags); -void lcd_goto(uint8_t addr, uint8_t x, uint8_t y); -void lcd_putchar(uint8_t addr, uint8_t c); -void lcd_pgmstr(uint8_t addr, const char *s); -void lcd_splash(); -void lcd_rtc_callback(); diff --git a/src/avr/src/line.c b/src/avr/src/line.c index 132c14f..a94d186 100644 --- a/src/avr/src/line.c +++ b/src/avr/src/line.c @@ -54,7 +54,7 @@ static struct { line_t line; int section; - int seg; + uint32_t seg; float iD; // Initial section distance float iV; // Initial section velocity diff --git a/src/avr/src/rtc.c b/src/avr/src/rtc.c index 8020895..f52c4fc 100644 --- a/src/avr/src/rtc.c +++ b/src/avr/src/rtc.c @@ -30,7 +30,6 @@ #include "switch.h" #include "analog.h" #include "motor.h" -#include "lcd.h" #include "vfd_spindle.h" #include @@ -46,7 +45,6 @@ static uint32_t ticks; ISR(RTC_OVF_vect) { ticks++; - lcd_rtc_callback(); switch_rtc_callback(); analog_rtc_callback(); vfd_spindle_rtc_callback(); diff --git a/src/avr/step-test/Makefile b/src/avr/step-test/Makefile deleted file mode 100644 index 52f894a..0000000 --- a/src/avr/step-test/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Makefile for Bulidbotics step-test -PROJECT = step-test -MCU = atxmega192a3u -CLOCK = 32000000 - -# SRC -SRC = usart.c lcd.c pins.c hardware.c -SRC := $(wildcard *.c) $(patsubst %,../src/%,$(SRC)) - -include ../Makefile.common - -CFLAGS += -I../src -I. - -# Build -all: $(PROJECT).hex size - -$(PROJECT).elf: $(SRC) - $(CC) $(SRC) $(CFLAGS) $(LDFLAGS) $(LIBS) -o $@ - -.PHONY: all diff --git a/src/avr/step-test/plot_velocity.py b/src/avr/step-test/plot_velocity.py deleted file mode 100644 index 2006faf..0000000 --- a/src/avr/step-test/plot_velocity.py +++ /dev/null @@ -1,187 +0,0 @@ -#!/usr/bin/env python3 - -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import sys, serial, argparse -import numpy as np -import math -import json -from time import sleep -from collections import deque -from datetime import datetime - -import matplotlib.pyplot as plt -import matplotlib.animation as animation - - -MM_PER_STEP = 5 * 1.8 / 360 / 32 -SAMPLES_PER_MIN = 6000 - - -class Plot: - def __init__(self, port, baud, max_len): - # Open serial port - self.sp = serial.Serial(port, baud) - - # Create data series - self.series = [] - for i in range(5): - self.series.append(deque([0.0] * max_len)) - - # Init vars - self.max_len = max_len - self.incoming = '' - self.last = [None] * 4 - - # Open velocity log - ts = datetime.now().strftime('%Y-%m-%d-%H:%M:%S') - self.log = open('velocity-%s.log' % ts, 'w') - - - # Add new series data - def add(self, i, value): - self.series[i].pop() - self.series[i].appendleft(value) - - - def update_text(self, text, vel, data): - text[4].set_text('V {0:8,.2f}'.format(vel)) - - for i in range(4): - text[i].set_text('{} {:11,}'.format('XYZA'[i], int(data[i]))) - - - def update(self, frame, axes, text): - # Read new data - try: - data = self.sp.read(self.sp.in_waiting) - self.incoming += data.decode('utf-8') - - except Exception as e: - print(e) - return - - while True: - # Parse lines - i = self.incoming.find('\n') - if i == -1: break - line = self.incoming[0:i] - self.incoming = self.incoming[i + 1:] - - # Handle reset - if line.find('RESET') != -1: - self.update_text(text, 0, [0] * 4) - self.log.write(line + '\n') - self.last = [None] * 4 - continue - - # Parse data - try: - data = [float(value) for value in line.split(',')] - except ValueError: continue - - if len(data) != 4: continue - - # Compute axis velocities - v = [] # Axis velocity - totalV = 0 # Tool velocity - - for i in range(4): - if self.last[i] is not None: - delta = self.last[i] - data[i] - v.append(delta * MM_PER_STEP * SAMPLES_PER_MIN) # mm/min - totalV += math.pow(v[i], 2) - - self.last[i] = data[i] - - # Compute tool velocity - totalV = math.sqrt(totalV) - - # Update position and velocity text - self.update_text(text, totalV, data) - - # Don't update plots when not moving - if totalV == 0: continue - - # Add new data - for i in range(4): self.add(i, v[i]) - self.add(4, totalV) - - # Update plots - for i in range(5): - axes[i].set_data(range(self.max_len), self.series[i]) - - self.log.write(line + '\n') - - - def close(self): - self.sp.flush() - self.sp.close() - - -if __name__ == '__main__': - # Parse command line arguments - description = "Plot velocity data in real-time" - parser = argparse.ArgumentParser(description = description) - parser.add_argument('-p', '--port', default = '/dev/ttyUSB0') - parser.add_argument('-b', '--baud', default = 115200, type = int) - parser.add_argument('-m', '--max-width', default = 2000, type = int) - args = parser.parse_args() - - # Create plot - plot = Plot(args.port, args.baud, args.max_width) - fig = plt.figure() - ax = plt.axes(xlim = (0, args.max_width), ylim = (-10000, 10000)) - axes = [] - axes_text = [] - - # Setup position and velocity text fields - font = dict(fontsize = 14, family = 'monospace') - - axes_text.append(plt.text(0, 11700, '', **font)) - axes_text.append(plt.text(800, 11700, '', **font)) - axes_text.append(plt.text(0, 10500, '', **font)) - axes_text.append(plt.text(800, 10500, '', **font)) - axes_text.append(plt.text(1500, 11700, '', **font)) - - # Create axes - for i in range(5): - axes.append(ax.plot([], [])[0]) - # Set text color to match axis color - axes_text[i].set_color(axes[i].get_color()) - - # Initial text views - plot.update_text(axes_text, 0, [0] * 4) - - # Set up animation - anim = animation.FuncAnimation(fig, plot.update, fargs = [axes, axes_text], - interval = 100) - - # Run - plt.show() - plot.close() diff --git a/src/avr/step-test/step-test.c b/src/avr/step-test/step-test.c deleted file mode 100644 index db267bf..0000000 --- a/src/avr/step-test/step-test.c +++ /dev/null @@ -1,230 +0,0 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -#include "config.h" -#include "hardware.h" -#include "usart.h" -#include "lcd.h" - -#include - -#include -#include - - -#define RESET_PIN SPI_MOSI_PIN - - -void rtc_init() {} - - -static struct { - uint8_t step_pin; - uint8_t dir_pin; - TC0_t *timer; - volatile int16_t high; - volatile bool reading; - -} channel[4] = { - {STEP_X_PIN, DIR_X_PIN, &TCC0, 0}, - {STEP_Y_PIN, DIR_Y_PIN, &TCD0, 0}, - {STEP_Z_PIN, DIR_Z_PIN, &TCE0, 0}, - {STEP_A_PIN, DIR_A_PIN, &TCF0, 0}, -}; - - -static int reset = 0; - - -void channel_reset(int i) {channel[i].timer->CNT = channel[i].high = 0;} - - -#define EVSYS_CHMUX(CH) (&EVSYS_CH0MUX)[CH] -#define EVSYS_CHCTRL(CH) (&EVSYS_CH0CTRL)[CH] - - -void channel_overflow(int i) { - if (IN_PIN(channel[i].dir_pin)) channel[i].high--; - else channel[i].high++; - channel[i].reading = false; -} - - -ISR(TCC0_OVF_vect) {channel_overflow(0);} -ISR(TCD0_OVF_vect) {channel_overflow(1);} -ISR(TCE0_OVF_vect) {channel_overflow(2);} -ISR(TCF0_OVF_vect) {channel_overflow(3);} - - -void channel_update_dir(int i) { - if (IN_PIN(channel[i].dir_pin)) channel[i].timer->CTRLFSET = TC0_DIR_bm; - else channel[i].timer->CTRLFCLR = TC0_DIR_bm; -} - - -ISR(PORTE_INT0_vect) {for (int i = 0; i < 4; i++) channel_update_dir(i);} - - -int32_t __attribute__ ((noinline)) _channel_read(int i) { - return (int32_t)channel[i].high << 16 | channel[i].timer->CNT; -} - - -int32_t channel_read(int i) { - while (true) { - channel[i].reading = true; - - int32_t x = _channel_read(i); - int32_t y = _channel_read(i); - - if (x != y || !channel[i].reading) continue; - - channel[i].reading = false; - return x; - } -} - - -void channel_update_enable(int i) { - if (IN_PIN(MOTOR_ENABLE_PIN)) - channel[i].timer->CTRLA = TC_CLKSEL_EVCH0_gc + i; - else channel[i].timer->CTRLA = 0; -} - - -ISR(PORTF_INT0_vect) { - for (int i = 0; i < 4; i++) channel_update_enable(i); - if (!IN_PIN(MOTOR_ENABLE_PIN)) reset = 2; -} - - -ISR(PORTC_INT0_vect) {reset = 32;} - - -ISR(TCC1_OVF_vect) { - if (reset) reset--; - - // Report measured steps - static int32_t counts[4] = {0, 0, 0, 0}; - bool moving = false; - bool zero = true; - for (int i = 0; i < 4; i++) { - int32_t count = channel_read(i); - if (count != counts[i]) moving = true; - if (count) zero = false; - counts[i] = count; - } - - if (reset && !zero) { - for (int i = 0; i < 4; i++) channel_reset(i); - printf("RESET\n"); - return; - } - - if (moving) - printf("%ld,%ld,%ld,%ld\n", counts[0], counts[1], counts[2], counts[3]); -} - - -static void _splash(uint8_t addr) { - lcd_init(addr); - lcd_goto(addr, 5, 1); - lcd_pgmstr(addr, PSTR("Step Test")); -} - - -void channel_init(int i) { - uint8_t step_pin = channel[i].step_pin; - uint8_t dir_pin = channel[i].dir_pin; - - // Configure I/O - DIRCLR_PIN(step_pin); - DIRCLR_PIN(dir_pin); - PINCTRL_PIN(step_pin) = PORT_SRLEN_bm | PORT_ISC_RISING_gc; - PINCTRL_PIN(dir_pin) = PORT_SRLEN_bm | PORT_ISC_BOTHEDGES_gc; - - // Dir change interrupt - PIN_PORT(dir_pin)->INTCTRL |= PORT_INT0LVL_HI_gc; - PIN_PORT(dir_pin)->INT0MASK |= PIN_BM(dir_pin); - - // Events - EVSYS_CHMUX(i) = PIN_EVSYS_CHMUX(step_pin); - EVSYS_CHCTRL(i) = EVSYS_DIGFILT_8SAMPLES_gc; - - // Clock - channel_update_enable(i); - channel[i].timer->INTCTRLA = TC_OVFINTLVL_HI_gc; - - // Set initial clock direction - channel_update_dir(i); -} - - -static void init() { - cli(); - - hw_init(); - usart_init(); - - // Motor channels - for (int i = 0; i < 4; i++) channel_init(i); - - // Motor enable - DIRCLR_PIN(MOTOR_ENABLE_PIN); - PINCTRL_PIN(MOTOR_ENABLE_PIN) = - PORT_SRLEN_bm | PORT_ISC_BOTHEDGES_gc | PORT_OPC_PULLUP_gc; - PIN_PORT(MOTOR_ENABLE_PIN)->INTCTRL |= PORT_INT0LVL_HI_gc; - PIN_PORT(MOTOR_ENABLE_PIN)->INT0MASK |= PIN_BM(MOTOR_ENABLE_PIN); - - // Configure report clock - TCC1.INTCTRLA = TC_OVFINTLVL_LO_gc; - TCC1.PER = F_CPU / 256 * 0.01; // 10ms - TCC1.CTRLA = TC_CLKSEL_DIV256_gc; - - // Reset switch - DIRCLR_PIN(RESET_PIN); - PINCTRL_PIN(RESET_PIN) = - PORT_SRLEN_bm | PORT_ISC_RISING_gc | PORT_OPC_PULLUP_gc; - PIN_PORT(RESET_PIN)->INTCTRL |= PORT_INT0LVL_LO_gc; - PIN_PORT(RESET_PIN)->INT0MASK |= PIN_BM(RESET_PIN); - - printf("RESET\n"); - - sei(); -} - - -int main() { - init(); - - _splash(0x27); - _splash(0x3f); - - while (true) continue; - - return 0; -} diff --git a/src/bbserial/Makefile b/src/bbserial/Makefile index 0b7bbc6..792ddfd 100644 --- a/src/bbserial/Makefile +++ b/src/bbserial/Makefile @@ -5,7 +5,7 @@ ccflags-y:=-std=gnu99 -Wno-declaration-after-statement KPKG=raspberrypi-kernel_1.20171029-1.tar.gz KURL=https://github.com/dbrgn/linux-rpi/archive/$(KPKG) -KDIR=linux-rpi-raspberrypi-kernel_1.20171029-1 +KDIR=/tmp/rpi-kernel export KERNEL=kernel7 KOPTS=ARCH=arm CROSS_COMPILE=$(CROSS) -C $(KDIR) @@ -14,7 +14,9 @@ all: $(KDIR) $(MAKE) $(KOPTS) M=$(DIR) modules $(KDIR): $(KPKG) - tar xf $(KPKG) + rm -rf $(KDIR) + mkdir -p $(KDIR) + tar xf $(KPKG) -C $(KDIR) --strip-components 1 $(MAKE) $(KOPTS) bcm2709_defconfig $(MAKE) $(KOPTS) modules_prepare diff --git a/src/js/admin-general-view.js b/src/js/admin-general-view.js index 795bd1b..bbc5791 100644 --- a/src/js/admin-general-view.js +++ b/src/js/admin-general-view.js @@ -1,143 +1,120 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict' +"use strict"; +const api = require("./api"); +const utils = require("./utils"); const merge = require("lodash.merge"); const config_defaults = require("../resources/onefinity_defaults.json"); const variant_defaults = { - machinist_x35: require("../resources/onefinity_machinist_x35_defaults.json"), - woodworker_x35: require("../resources/onefinity_woodworker_x35_defaults.json"), - woodworker_x50: require("../resources/onefinity_woodworker_x50_defaults.json"), - journeyman_x50: require("../resources/onefinity_journeyman_x50_defaults.json") + machinist_x35: require("../resources/onefinity_machinist_x35_defaults.json"), + woodworker_x35: require("../resources/onefinity_woodworker_x35_defaults.json"), + woodworker_x50: require("../resources/onefinity_woodworker_x50_defaults.json"), + journeyman_x50: require("../resources/onefinity_journeyman_x50_defaults.json") }; -const api = require('./api'); - module.exports = { - template: '#admin-general-view-template', - props: ['config', 'state'], + template: "#admin-general-view-template", + props: [ "config", "state" ], - data: function () { - return { - configRestored: false, - confirmReset: false, - configReset: false, - autoCheckUpgrade: true, - reset_variant: '' - } - }, - - ready: function () { - this.autoCheckUpgrade = this.config.admin['auto-check-upgrade'] - }, - - methods: { - backup: function () { - document.getElementById('download-target').src = '/api/config/download'; + data: function() { + return { + confirmReset: false, + autoCheckUpgrade: true, + reset_variant: "" + }; }, - restore_config: function () { - // If we don't reset the form the browser may cache file if name is same - // even if contents have changed - $('.restore-config')[0].reset(); - $('.restore-config input').click(); + ready: function() { + this.autoCheckUpgrade = this.config.admin["auto-check-upgrade"]; }, - restore: function (e) { - var files = e.target.files || e.dataTransfer.files; - if (!files.length) return; + methods: { + backup: function() { + document.getElementById("download-target").src = "/api/config/download"; + }, - var fr = new FileReader(); - fr.onload = function (e) { - var config; - try { - config = JSON.parse(e.target.result); - } catch (ex) { - api.alert("Invalid config file"); - return; + restore_config: function() { + utils.clickFileInput("restore-config"); + }, + + restore: function(e) { + const files = e.target.files || e.dataTransfer.files; + if (!files.length) { + return; + } + + const fileReader = new FileReader(); + fileReader.onload = async ({ target }) => { + let config; + try { + config = JSON.parse(target.result); + } catch (error) { + console.error("Invalid config file:", error); + alert("Invalid config file"); + return; + } + + try { + await api.put("config/save", config); + this.$dispatch("update"); + SvelteComponents.showDialog("Message", { + title: "Success", + message: "Configuration restored" + }); + } catch (error) { + console.error("Restore failed:", error); + alert("Restore failed"); + } + }; + + fileReader.readAsText(files[0]); + }, + + reset: async function() { + const config = merge( + {}, + config_defaults, + variant_defaults[this.reset_variant] + ); + + try { + await api.put("config/save", config); + this.confirmReset = false; + this.$dispatch("update"); + SvelteComponents.showDialog("Message", { + title: "Success", + message: "Configuration restored" + }); + } catch (error) { + console.error("Restore failed:", error); + alert("Restore failed"); + } + }, + + check: function() { + this.$dispatch("check"); + }, + + upgrade: function() { + this.$dispatch("upgrade"); + }, + + upload_firmware: function() { + utils.clickFileInput("upload-firmware"); + }, + + upload: function(e) { + const files = e.target.files || e.dataTransfer.files; + if (!files.length) { + return; + } + this.$dispatch("upload", files[0]); + }, + + change_auto_check_upgrade: function() { + this.config.admin["auto-check-upgrade"] = this.autoCheckUpgrade; + this.$dispatch("config-changed"); } - - api.put('config/save', config).done(function (data) { - this.$dispatch('update'); - this.configRestored = true; - - }.bind(this)).fail(function (error) { - api.alert('Restore failed', error); - }) - }.bind(this); - - fr.readAsText(files[0]); - }, - - reset: async function () { - const config = merge( - {}, - config_defaults, - variant_defaults[this.reset_variant] - ); - - try { - await api.put('config/save', config) - this.confirmReset = false; - this.$dispatch('update'); - this.configRestored = true; - } catch (err) { - api.alert('Restore failed'); - console.error('Restore failed', err); - } - }, - - check: function () { - this.$dispatch('check') - }, - - upgrade: function () { - this.$dispatch('upgrade') - }, - - upload_firmware: function () { - // If we don't reset the form the browser may cache file if name is same - // even if contents have changed - $('.upload-firmware')[0].reset(); - $('.upload-firmware input').click(); - }, - - upload: function (e) { - var files = e.target.files || e.dataTransfer.files; - if (!files.length) return; - this.$dispatch('upload', files[0]); - }, - - change_auto_check_upgrade: function () { - this.config.admin['auto-check-upgrade'] = this.autoCheckUpgrade; - this.$dispatch('config-changed'); } - } -} +}; diff --git a/src/js/admin-network-view.js b/src/js/admin-network-view.js index 004ef54..69f3e8d 100644 --- a/src/js/admin-network-view.js +++ b/src/js/admin-network-view.js @@ -1,14 +1,14 @@ module.exports = { - template: "#admin-network-view-template", + template: "#admin-network-view-template", - attached: function () { - this.svelteComponent = SvelteComponents.create( - "AdminNetworkView", - document.getElementById("svelte-root") - ); - }, + attached: function() { + this.svelteComponent = SvelteComponents.createComponent( + "AdminNetworkView", + document.getElementById("admin-network") + ); + }, - detached: function() { - this.svelteComponent.$destroy(); - } + detached: function() { + this.svelteComponent.$destroy(); + } }; diff --git a/src/js/api.js b/src/js/api.js index c97e86f..45a74e8 100644 --- a/src/js/api.js +++ b/src/js/api.js @@ -1,77 +1,48 @@ -'use strict' +"use strict"; +async function callApi(method, url, data) { + try { + const headers = {}; + let body = undefined; -function api_cb(method, url, data, config) { - config = $.extend({ - type: method, - url: '/api/' + url, - dataType: 'json', - cache: false - }, config); + if (data) { + if (data instanceof FormData) { + body = data; + } else { + headers["Content-Type"] = "application/json; charset=utf-8"; + body = JSON.stringify(data); + } + } - if (typeof data == 'object') { - config.data = JSON.stringify(data); - config.contentType = 'application/json; charset=utf-8'; - } + const response = await fetch(`/api/${url}`, { + method, + headers, + body, + cache: "no-cache", + }); - var d = $.Deferred(); + if (response.ok) { + return await response.json(); + } - $.ajax(config).success(function (data, status, xhr) { - d.resolve(data, status, xhr); + throw new Error(await response.text()); + } catch (error) { + console.debug(`API Error: ${url}: ${error}`); - }).error(function (xhr, status, error) { - var text = xhr.responseText; - try {text = $.parseJSON(xhr.responseText)} catch(e) {} - if (!text) text = error; - - d.reject(text, xhr, status, error); - console.debug('API Error: ' + url + ': ' + text); - }); - - return d.promise(); + throw error; + } } - module.exports = { - get: function (url, config) { - return api_cb('GET', url, undefined, config); - }, + get: function(url) { + return callApi("GET", url); + }, + put: function(url, body = undefined) { + return callApi("PUT", url, body); + }, - put: function(url, data, config) { - return api_cb('PUT', url, data, config); - }, - - - post: function(url, data, config) { - return api_cb('POST', url, data, config); - }, - - - upload: function(url, data, config) { - config = $.extend({ - processData: false, - contentType: false, - cache: false, - data: data - }, config); - - return api_cb('PUT', url, undefined, config); - }, - - - 'delete': function (url, config) { - return api_cb('DELETE', url, undefined, config); - }, - - - alert: function (msg, error) { - if (typeof error != 'undefined') { - if (typeof error.message != 'undefined') - msg += '\n' + error.message; - else msg += '\n' + JSON.stringify(error); + delete: function(url) { + return callApi("DELETE", url); } - - alert(msg); - } -} +}; diff --git a/src/js/app.js b/src/js/app.js index bec006a..b34f3c6 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -3,444 +3,428 @@ const api = require("./api"); const cookie = require("./cookie")("bbctrl-"); const Sock = require("./sock"); -const omit = require("lodash.omit"); -SvelteComponents.initNetworkInfo(); +SvelteComponents.createComponent("DialogHost", + document.getElementById("svelte-dialog-host") +); function is_newer_version(current, latest) { - const pattern = /(\d+)\.(\d+)\.(\d+)(.*)/; - const currentParts = current.match(pattern); - const latestParts = latest.match(pattern); + const pattern = /(\d+)\.(\d+)\.(\d+)(.*)/; + const currentParts = current.match(pattern); + const latestParts = latest.match(pattern); - if (!currentParts || !latestParts) { - return false; - } + if (!currentParts || !latestParts) { + return false; + } - // Normal version comparisons - const major = latestParts[1] - currentParts[1]; - const minor = latestParts[2] - currentParts[2]; - const patch = latestParts[3] - currentParts[3]; + // Normal version comparisons + const major = latestParts[1] - currentParts[1]; + const minor = latestParts[2] - currentParts[2]; + const patch = latestParts[3] - currentParts[3]; - // If current is a pre-release, and latest is a release - const betaToRelease = - latestParts[4].length === 0 && currentParts[4].length > 0; + // If current is a pre-release, and latest is a release + const betaToRelease = latestParts[4].length === 0 && currentParts[4].length > 0; - switch (true) { - case major > 0: - case major === 0 && minor > 0: - case major === 0 && minor === 0 && patch > 0: - case major === 0 && minor === 0 && patch === 0 && betaToRelease: - return true; + switch (true) { + case major > 0: + case major === 0 && minor > 0: + case major === 0 && minor === 0 && patch > 0: + case major === 0 && minor === 0 && patch === 0 && betaToRelease: + return true; - default: - return false; - } + default: + return false; + } } function is_object(o) { - return o !== null && typeof o == "object"; + return o !== null && typeof o == "object"; } + function is_array(o) { - return Array.isArray(o); + return Array.isArray(o); } function update_array(dst, src) { - while (dst.length) dst.pop(); - for (var i = 0; i < src.length; i++) Vue.set(dst, i, src[i]); + while (dst.length) { + dst.pop(); + } + + for (let i = 0; i < src.length; i++) { + Vue.set(dst, i, src[i]); + } +} + +function hasOwnProperty(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); } function update_object(dst, src, remove) { - var props, index, key, value; + let props, index, key, value; - if (remove) { - props = Object.getOwnPropertyNames(dst); + if (remove) { + props = Object.getOwnPropertyNames(dst); - for (index in props) { - key = props[index]; - if (!src.hasOwnProperty(key)) Vue.delete(dst, key); + for (index in props) { + key = props[index]; + if (!hasOwnProperty(src, key)) { + Vue.delete(dst, key); + } + } } - } - props = Object.getOwnPropertyNames(src); - for (index in props) { - key = props[index]; - value = src[key]; + props = Object.getOwnPropertyNames(src); + for (index in props) { + key = props[index]; + value = src[key]; - if (is_array(value) && dst.hasOwnProperty(key) && is_array(dst[key])) - update_array(dst[key], value); - else if (is_object(value) && dst.hasOwnProperty(key) && is_object(dst[key])) - update_object(dst[key], value, remove); - else Vue.set(dst, key, value); - } + if (is_array(value) && hasOwnProperty(dst, key) && is_array(dst[key])) { + update_array(dst[key], value); + } else if (is_object(value) && hasOwnProperty(dst, key) && is_object(dst[key])) { + update_object(dst[key], value, remove); + } else { + Vue.set(dst, key, value); + } + } } module.exports = new Vue({ - el: "body", + el: "body", - data: function () { - return { - status: "connecting", - currentView: "loading", - index: -1, - modified: false, - template: require("../resources/config-template.json"), - config: { - settings: { units: "METRIC" }, - motors: [{}, {}, {}, {}], - version: "", - full_version: "", - }, - state: { - messages: [], - probing_active: false, - wait_for_probing_complete: false, - show_probe_complete_modal: false, - show_probe_failed_modal: false, - }, - video_size: cookie.get("video-size", "small"), - crosshair: cookie.get("crosshair", "false") != "false", - errorTimeout: 30, - errorTimeoutStart: 0, - errorShow: false, - errorMessage: "", - confirmUpgrade: false, - confirmUpload: false, - firmwareUpgrading: false, - checkedUpgrade: false, - firmwareName: "", - latestVersion: "", - confirmShutdown: false, - }; - }, - - components: { - estop: { template: "#estop-template" }, - "loading-view": { template: "

Loading...

" }, - "control-view": require("./control-view"), - "settings-view": require("./settings-view"), - "motor-view": require("./motor-view"), - "tool-view": require("./tool-view"), - "io-view": require("./io-view"), - "admin-general-view": require("./admin-general-view"), - "admin-network-view": require("./admin-network-view"), - "help-view": { template: "#help-view-template" }, - "cheat-sheet-view": { - template: "#cheat-sheet-view-template", - data: function () { - return { showUnimplemented: false }; - }, - }, - }, - - events: { - "config-changed": function () { - this.modified = true; + data: function() { + return { + status: "connecting", + currentView: "loading", + display_units: localStorage.getItem("display_units") || "METRIC", + index: -1, + modified: false, + template: require("../resources/config-template.json"), + config: { + settings: { units: "METRIC" }, + motors: [ {}, {}, {}, {} ], + version: "", + full_version: "", + }, + state: { + messages: [], + }, + video_size: cookie.get("video-size", "small"), + crosshair: cookie.get("crosshair", "false") != "false", + errorTimeout: 30, + errorTimeoutStart: 0, + errorShow: false, + errorMessage: "", + confirmUpgrade: false, + confirmUpload: false, + firmwareUpgrading: false, + checkedUpgrade: false, + firmwareName: "", + latestVersion: "" + }; }, - send: function (msg) { - if (this.status == "connected") { - console.debug(">", msg); - this.sock.send(msg); - } + components: { + estop: { template: "#estop-template" }, + "loading-view": { template: "

Loading...

" }, + "control-view": require("./control-view"), + "settings-view": require("./settings-view"), + "motor-view": require("./motor-view"), + "tool-view": require("./tool-view"), + "io-view": require("./io-view"), + "admin-general-view": require("./admin-general-view"), + "admin-network-view": require("./admin-network-view"), + "help-view": { template: "#help-view-template" }, + "cheat-sheet-view": { + template: "#cheat-sheet-view-template", + data: function() { + return { + showUnimplemented: false + }; + }, + }, }, - connected: function () { - this.update(); + watch: { + display_units: function(value) { + localStorage.setItem("display_units", value); + SvelteComponents.setDisplayUnits(value); + }, }, - update: function () { - this.update(); - }, + events: { + "config-changed": function() { + this.modified = true; + }, - check: async function () { - try { - const response = await fetch("https://raw.githubusercontent.com/OneFinityCNC/onefinity-release/master/latest.txt", { - cache: "no-cache" - }); + send: function(msg) { + if (this.status == "connected") { + this.sock.send(msg); + } + }, - this.latestVersion = (await response.text()).trim(); - } catch (err) { - this.latestVersion = ""; - } - }, + connected: function() { + this.update(); + }, - upgrade: function () { - this.confirmUpgrade = true; - }, + update: function() { + this.update(); + }, - upload: function (firmware) { - this.firmware = firmware; - this.firmwareName = firmware.name; - this.confirmUpload = true; - }, + check: async function() { + try { + const response = await fetch("https://raw.githubusercontent.com/OneFinityCNC/onefinity-release/master/latest.txt", { + cache: "no-cache" + }); - error: function (msg) { - // Honor user error blocking - if (Date.now() - this.errorTimeoutStart < this.errorTimeout * 1000) - return; + this.latestVersion = (await response.text()).trim(); + } catch (err) { + this.latestVersion = ""; + } + }, - // Wait at least 1 sec to pop up repeated errors - if (1 < msg.repeat && Date.now() - msg.ts < 1000) { - return; - } + upgrade: function() { + this.confirmUpgrade = true; + }, - // Popup error dialog - this.errorShow = true; - this.errorMessage = msg.msg; - }, - }, + upload: function(firmware) { + this.firmware = firmware; + this.firmwareName = firmware.name; + this.confirmUpload = true; + }, - computed: { - popupMessages: function () { - const msgs = []; - - for (let i = 0; i < this.state.messages.length; i++) { - const text = this.state.messages[i].text; - if (!/^#/.test(text)) { - msgs.push(text); - } - } - - return msgs; - }, - }, - - ready: function () { - $(window).on("hashchange", this.parse_hash); - this.connect(); - }, - - methods: { - metric: function () { - return this.config.settings.units != "IMPERIAL"; - }, - - block_error_dialog: function () { - this.errorTimeoutStart = Date.now(); - this.errorShow = false; - }, - - toggle_video: function (e) { - if (this.video_size == "small") this.video_size = "large"; - else if (this.video_size == "large") this.video_size = "small"; - cookie.set("video-size", this.video_size); - }, - - toggle_crosshair: function (e) { - e.preventDefault(); - this.crosshair = !this.crosshair; - cookie.set("crosshair", this.crosshair); - }, - - estop: function () { - if (this.state.xx == "ESTOPPED") api.put("clear"); - else api.put("estop"); - }, - - upgrade_confirmed: async function () { - this.confirmUpgrade = false; - - try { - await api.put("upgrade"); - this.firmwareUpgrading = true; - } catch (err) { - api.alert("Error during upgrade."); - console.error("Error during upgrade", err); - } - }, - - upload_confirmed: function () { - this.confirmUpload = false; - - const form = new FormData(); - form.append("firmware", this.firmware); - - $.ajax({ - url: "/api/firmware/update", - type: "PUT", - data: form, - cache: false, - contentType: false, - processData: false, - }) - .success( - function () { - this.firmwareUpgrading = true; - }.bind(this) - ) - .error( - function (err) { - api.alert("Firmware update failed"); - console.error("Firmware update failed", err); - }.bind(this) - ); - }, - - show_upgrade: function () { - if (!this.latestVersion) return false; - return is_newer_version(this.config.version, this.latestVersion); - }, - - update: async function () { - const config = await api.get("config/load"); - - update_object(this.config, config, true); - this.parse_hash(); - - if (!this.checkedUpgrade) { - this.checkedUpgrade = true; - - var check = this.config.admin["auto-check-upgrade"]; - if (typeof check == "undefined" || check) this.$emit("check"); - } - - }, - - shutdown: function () { - this.confirmShutdown = false; - api.put("shutdown"); - }, - - reboot: function () { - this.confirmShutdown = false; - api.put("reboot"); - }, - - connect: function () { - this.sock = new Sock(`//${location.host}/sockjs`); - - this.sock.onmessage = (e) => { - if (typeof e.data != "object") { - return; - } - - if ("log" in e.data) { - if (e.data.log.msg === "Switch not found") { - this.$broadcast("probing_failed"); - } else { - this.$broadcast("log", e.data.log); - } - - delete e.data.log; - } - - // Check for session ID change on controller - if ("sid" in e.data) { - if (typeof this.sid == "undefined") { - this.sid = e.data.sid; - } else if (this.sid != e.data.sid) { - if ( - typeof this.hostname !== "undefined" && - location.hostname !== "localhost" - ) { - location.hostname = this.hostname; + error: function(msg) { + // Honor user error blocking + if (Date.now() - this.errorTimeoutStart < this.errorTimeout * 1000) { + return; } - location.reload(); - } - } + // Wait at least 1 sec to pop up repeated errors + if (1 < msg.repeat && Date.now() - msg.ts < 1000) { + return; + } - // Set this to true to get console output of changes to the state - const debugStateChanges = false; - if (debugStateChanges) { - const data = omit(e.data, [ - "vdd", - "vin", - "vout", - "motor", - "temp", - "heartbeat", - "load1", - "load2", - "rpi_temp", - ]); - if (Object.keys(data).length > 0) { - console.log(JSON.stringify(data, null, 4)); - } - } - - update_object(this.state, e.data, false); - - if (this.state.pw === 0) { - Vue.set(this.state, "saw_probe_connected", true); - } - - if (this.state.cycle === "idle") { - if (this.state.wait_for_probing_complete) { - Vue.set(this.state, "wait_for_probing_complete", false); - this.$broadcast("probing_complete"); - } - } - - this.$broadcast("update"); - }; - - this.sock.onopen = () => { - this.status = "connected"; - this.$emit(this.status); - this.$broadcast(this.status); - }; - - this.sock.onclose = () => { - this.status = "disconnected"; - this.$emit(this.status); - this.$broadcast(this.status); - }; + // Popup error dialog + this.errorShow = true; + this.errorMessage = msg.msg; + }, }, - parse_hash: function () { - var hash = location.hash.substr(1); + computed: { + popupMessages: function() { + const msgs = []; - if (!hash.trim().length) { - location.hash = "control"; - return; - } + for (let i = 0; i < this.state.messages.length; i++) { + const text = this.state.messages[i].text; + if (!/^#/.test(text)) { + msgs.push(text); + } + } - var parts = hash.split(":"); - - if (parts.length == 2) this.index = parts[1]; - - this.currentView = parts[0]; + return msgs; + }, }, - save: function () { - const selected_tool = this.config.tool["selected-tool"]; - const saveModbus = - selected_tool !== "pwm" && - selected_tool !== "laser" && - selected_tool !== "router"; - const settings = { - ["tool"]: { ...this.config.tool }, - ["pwm-spindle"]: { ...this.config["pwm-spindle"] }, - ["modbus-spindle"]: saveModbus - ? { ...this.config["modbus-spindle"] } - : undefined, - }; - delete settings.tool["tool-type"]; + ready: function() { + window.onhashchange = () => this.parse_hash(); + this.connect(); - this.config["selected-tool-settings"][selected_tool] = settings; - - api - .put("config/save", this.config) - .done( - function (data) { - this.modified = false; - }.bind(this) - ) - .fail(function (error) { - api.alert("Save failed", error); + SvelteComponents.registerControllerMethods({ + dispatch: (...args) => this.$dispatch(...args) }); }, - close_messages: function (action) { - if (action == "stop") api.put("stop"); - if (action == "continue") api.put("unpause"); + methods: { + block_error_dialog: function() { + this.errorTimeoutStart = Date.now(); + this.errorShow = false; + }, - // Acknowledge messages - if (this.state.messages.length) { - var id = this.state.messages.slice(-1)[0].id; - api.put("message/" + id + "/ack"); - } + toggle_video: function() { + if (this.video_size == "small") { + this.video_size = "large"; + } else if (this.video_size == "large") { + this.video_size = "small"; + } + cookie.set("video-size", this.video_size); + }, + + toggle_crosshair: function(e) { + e.preventDefault(); + this.crosshair = !this.crosshair; + cookie.set("crosshair", this.crosshair); + }, + + estop: function() { + if (this.state.xx == "ESTOPPED") { + api.put("clear"); + } else { + api.put("estop"); + } + }, + + upgrade_confirmed: async function() { + this.confirmUpgrade = false; + + try { + await api.put("upgrade"); + this.firmwareUpgrading = true; + } catch (error) { + console.error("Error during upgrade:", error); + alert("Error during upgrade"); + } + }, + + upload_confirmed: async function() { + this.confirmUpload = false; + + const form = new FormData(); + form.append("firmware", this.firmware); + + try { + await api.put("firmware/update", form); + this.firmwareUpgrading = true; + } catch (error) { + console.error("Firmware update failed:", error); + alert("Firmware update failed"); + } + }, + + show_upgrade: function() { + if (!this.latestVersion) { + return false; + } + + return is_newer_version(this.config.version, this.latestVersion); + }, + + showShutdownDialog: function() { + SvelteComponents.showDialog("Shutdown"); + }, + + update: async function() { + const config = await api.get("config/load"); + + update_object(this.config, config, true); + this.parse_hash(); + + if (!this.checkedUpgrade) { + this.checkedUpgrade = true; + + const check = this.config.admin["auto-check-upgrade"]; + if (typeof check == "undefined" || check) { + this.$emit("check"); + } + } + + SvelteComponents.handleConfigUpdate(this.config); + }, + + connect: function() { + this.sock = new Sock(`//${location.host}/sockjs`); + + this.sock.onmessage = (e) => { + if (typeof e.data != "object") { + return; + } + + if ("log" in e.data) { + if (e.data.log.msg !== "Switch not found") { + this.$broadcast("log", e.data.log); + } + } + + // Check for session ID change on controller + if ("sid" in e.data) { + if (typeof this.sid == "undefined") { + this.sid = e.data.sid; + } else if (this.sid != e.data.sid) { + if (this.hostname && location.hostname !== "localhost") { + location.hostname = this.hostname; + } + + location.reload(); + } + } + + update_object(this.state, e.data, false); + + SvelteComponents.handleControllerStateUpdate(this.state); + + delete this.state.log; + + this.$broadcast("update"); + }; + + this.sock.onopen = () => { + this.status = "connected"; + this.$emit(this.status); + this.$broadcast(this.status); + }; + + this.sock.onclose = () => { + this.status = "disconnected"; + this.$emit(this.status); + this.$broadcast(this.status); + }; + }, + + parse_hash: function() { + const hash = location.hash.substr(1); + + if (!hash.trim().length) { + location.hash = "control"; + return; + } + + const parts = hash.split(":"); + + if (parts.length == 2) { + this.index = parts[1]; + } + + this.currentView = parts[0]; + }, + + save: async function() { + const selected_tool = this.config.tool["selected-tool"]; + const saveModbus = + selected_tool !== "pwm" && + selected_tool !== "laser" && + selected_tool !== "router"; + const settings = { + ["tool"]: { ...this.config.tool }, + ["pwm-spindle"]: { ...this.config["pwm-spindle"] }, + ["modbus-spindle"]: saveModbus + ? { ...this.config["modbus-spindle"] } + : undefined, + }; + delete settings.tool["tool-type"]; + + this.config["selected-tool-settings"][selected_tool] = settings; + + try { + await api.put("config/save", this.config); + this.modified = false; + } catch (error) { + console.error("Save failed:", error); + alert("Save failed"); + } + }, + + close_messages: function(action) { + if (action == "stop") { + api.put("stop"); + } + + if (action == "continue") { + api.put("unpause"); + } + + // Acknowledge messages + if (this.state.messages.length) { + const id = this.state.messages.slice(-1)[0].id; + api.put(`message/${id}/ack`); + } + }, }, - }, }); diff --git a/src/js/axis-control.js b/src/js/axis-control.js index c6fa5c3..81a9bed 100644 --- a/src/js/axis-control.js +++ b/src/js/axis-control.js @@ -1,65 +1,37 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict' - +"use strict"; module.exports = { - template: '#axis-control-template', - props: ['axes', 'colors', 'enabled', 'adjust', 'step'], + template: "#axis-control-template", + props: [ "axes", "colors", "enabled", "adjust", "step" ], + methods: { + jog: function(axis, ring, direction) { + const value = direction * this.value(ring); + this.$dispatch(this.step ? "step" : "jog", this.axes[axis], value); + }, - methods: { - jog: function (axis, ring, direction) { - var value = direction * this.value(ring); - this.$dispatch(this.step ? 'step' : 'jog', this.axes[axis], value); - }, + back2zero: function(axis0,axis1) { + this.$dispatch("back2zero",this.axes[axis0],this.axes[axis1]); + }, - back2zero: function(axis0,axis1) { - this.$dispatch('back2zero',this.axes[axis0],this.axes[axis1]) - }, + release: function(axis) { + if (!this.step) { + this.$dispatch("jog", this.axes[axis], 0); + } + }, + value: function(ring) { + const adjust = [ 0.01, 0.1, 1 ][this.adjust]; + if (this.step) { + return adjust * [ 0.1, 1, 10, 100 ][ring]; + } + return adjust * [ 0.1, 0.25, 0.5, 1 ][ring]; + }, - release: function (axis) { - if (!this.step) this.$dispatch('jog', this.axes[axis], 0) - }, - - - value: function (ring) { - var adjust = [0.01, 0.1, 1][this.adjust]; - if (this.step) return adjust * [0.1, 1, 10, 100][ring]; - return adjust * [0.1, 0.25, 0.5, 1][ring]; - }, - - - text: function (ring) { - var value = this.value(ring) * (this.step ? 1 : 100); - value = parseFloat(value.toFixed(3)); - return value + (this.step ? '' : '%'); + text: function(ring) { + let value = this.value(ring) * (this.step ? 1 : 100); + value = parseFloat(value.toFixed(3)); + return value + (this.step ? "" : "%"); + } } - } -} +}; diff --git a/src/js/axis-vars.js b/src/js/axis-vars.js index 99eff79..92fc20f 100644 --- a/src/js/axis-vars.js +++ b/src/js/axis-vars.js @@ -1,232 +1,254 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict' - - -function is_defined(x) {return typeof x != 'undefined'} - +"use strict"; module.exports = { - props: ['state', 'config'], + props: [ "state", "config" ], + computed: { + metric: function() { + return this.$root.display_units === "METRIC"; + }, - computed: { - x: function () {return this._compute_axis('x')}, - y: function () {return this._compute_axis('y')}, - z: function () {return this._compute_axis('z')}, - a: function () {return this._compute_axis('a')}, - b: function () {return this._compute_axis('b')}, - c: function () {return this._compute_axis('c')}, - axes: function () {return this._compute_axes()} - }, + x: function() { + return this._compute_axis("x"); + }, + y: function() { + return this._compute_axis("y"); + }, - methods: { - _convert_length: function (value) { - return this.state.imperial ? value / 25.4 : value; - }, + z: function() { + return this._compute_axis("z"); + }, + a: function() { + return this._compute_axis("a"); + }, - _length_str: function (value) { - return this._convert_length(value).toLocaleString() + - (this.state.imperial ? ' in' : ' mm'); - }, + b: function() { + return this._compute_axis("b"); + }, + c: function() { + return this._compute_axis("c"); + }, - _compute_axis: function (axis) { - var abs = this.state[axis + 'p'] || 0; - var off = this.state['offset_' + axis]; - var motor_id = this._get_motor_id(axis); - var motor = motor_id == -1 ? {} : this.config.motors[motor_id]; - var enabled = typeof motor.enabled != 'undefined' && motor.enabled; - var homingMode = motor['homing-mode'] - var homed = this.state[motor_id + 'homed']; - var min = this.state[motor_id + 'tn']; - var max = this.state[motor_id + 'tm']; - var dim = max - min; - var pathMin = this.state['path_min_' + axis]; - var pathMax = this.state['path_max_' + axis]; - var pathDim = pathMax - pathMin; - var under = pathMin + off < min; - var over = max < pathMax + off; - var klass = (homed ? 'homed' : 'unhomed') + ' axis-' + axis; - var state = 'UNHOMED'; - var icon = 'question-circle'; - var fault = this.state[motor_id + 'df'] & 0x1f; - var shutdown = this.state.power_shutdown; - var title; - var ticon = 'question-circle'; - var tstate = 'NO FILE'; - var toolmsg; - var tklass = (homed ? 'homed' : 'unhomed') + ' axis-' + axis; - - if (fault || shutdown) { - state = shutdown ? 'SHUTDOWN' : 'FAULT'; - klass += ' error'; - icon = 'exclamation-circle'; - - } else if(homed) { - state = 'HOMED'; - icon = 'check-circle'; - } - - if (0 < dim && dim < pathDim) { - tstate = 'NO FIT'; - tklass += ' error'; - ticon = 'ban'; - - } else { - - if (over || under) { - tstate = over ? 'OVER' : 'UNDER'; - tklass += ' warn'; - ticon = 'exclamation-circle'; - } else { - tstate = 'OK'; - ticon = 'check-circle'; + axes: function() { + return this._compute_axes(); } - } - - switch (state) { - case 'UNHOMED': title = 'Click the home button to home axis.'; break; - case 'HOMED': title = 'Axis successfuly homed.'; break; - case 'FAULT': - title = 'Motor driver fault. A potentially damaging electrical ' + - 'condition was detected and the motor driver was shutdown. ' + - 'Please power down the controller and check your motor cabling. ' + - 'See the "Motor Faults" table on the "Indicators" tab for more ' + - 'information.'; - break; - case 'SHUTDOWN': - title = 'Motor power fault. All motors in shutdown. ' + - 'See the "Power Faults" table on the "Indicators" tab for more ' + - 'information. Reboot controller to reset.'; - } - - switch(tstate) { - - case 'OVER': - toolmsg = 'Caution: The current tool path file would move ' + - this._length_str(pathMax + off - max) + ' above axis limit with the current offset.'; - break; - - case 'UNDER': - toolmsg = 'Caution: The current tool path file would move ' + - this._length_str(min - pathMin - off) + ' below limit with the current offset.'; - break; - - case 'NO FIT': - toolmsg = 'Warning: The current tool path dimensions (' + - this._length_str(pathDim) + ') exceed axis dimensions (' + - this._length_str(dim) + ') by ' + - this._length_str(pathDim - dim) + '.'; - break; - - default: - toolmsg = 'Tool path ' + axis + ' dimensions OK.'; - break; - - } - - - return { - pos: abs - off, - abs: abs, - off: off, - min: min, - max: max, - dim: dim, - pathMin: pathMin, - pathMax: pathMax, - pathDim: pathDim, - motor: motor_id, - enabled: enabled, - homingMode: homingMode, - homed: homed, - klass: klass, - state: state, - icon: icon, - title: title, - ticon: ticon, - tstate: tstate, - toolmsg: toolmsg, - tklass: tklass - } }, + methods: { + _convert_length: function(value) { + return this.metric + ? value + : value / 25.4; + }, - _get_motor_id: function (axis) { - for (var i = 0; i < this.config.motors.length; i++) { - var motor = this.config.motors[i]; - if (motor.axis.toLowerCase() == axis) return i; - } + _length_str: function(value) { + return this._convert_length(value).toLocaleString() + (this.metric ? " mm" : " in"); + }, - return -1; - }, + _compute_axis: function(axis) { + const abs = this.state[`${axis}p`] || 0; + const off = this.state[`offset_${axis}`]; + const motor_id = this._get_motor_id(axis); + const motor = motor_id == -1 ? {} : this.config.motors[motor_id]; + const enabled = typeof motor.enabled != "undefined" && motor.enabled; + const homingMode = motor["homing-mode"]; + const homed = this.state[`${motor_id}homed`]; + const min = this.state[`${motor_id}tn`]; + const max = this.state[`${motor_id}tm`]; + const dim = max - min; + const pathMin = this.state[`path_min_${axis}`]; + const pathMax = this.state[`path_max_${axis}`]; + const pathDim = pathMax - pathMin; + const under = pathMin + off < min; + const over = max < pathMax + off; + let klass = `${homed ? "homed" : "unhomed"} axis-${axis}`; + let state = "UNHOMED"; + let icon = "question-circle"; + const fault = this.state[`${motor_id}df`] & 0x1f; + const shutdown = this.state.power_shutdown; + let title; + let ticon = "question-circle"; + let tstate = "NO FILE"; + let toolmsg; + let tklass = `${homed ? "homed" : "unhomed"} axis-${axis}`; + if (fault || shutdown) { + state = shutdown ? "SHUTDOWN" : "FAULT"; + klass += " error"; + icon = "exclamation-circle"; + } else if (homed) { + state = "HOMED"; + icon = "check-circle"; + } - _compute_axes: function () { - var homed = false; + if (0 < dim && dim < pathDim) { + tstate = "NO FIT"; + tklass += " error"; + ticon = "ban"; + } else { + if (over || under) { + tstate = over ? "OVER" : "UNDER"; + tklass += " warn"; + ticon = "exclamation-circle"; + } else { + tstate = "OK"; + ticon = "check-circle"; + } + } - for (var name of 'xyzabc') { - var axis = this[name]; + switch (state) { + case "UNHOMED": + title = "Click the home button to home axis."; + break; - if (!axis.enabled) continue - if (!axis.homed) {homed = false; break} - homed = true; - } + case "HOMED": + title = "Axis successfuly homed."; + break; - var error = false; - var warn = false; + case "FAULT": + title = [ + `Motor driver fault. A potentially damaging electrical`, + `condition was detected and the motor driver was shutdown.`, + `Please power down the controller and check your motor cabling.`, + `See the "Motor Faults" table on the "Indicators" tab for more`, + `information.`, + ].join(" "); + break; - if (homed) - for (name of 'xyzabc') { - axis = this[name]; + case "SHUTDOWN": + title = [ + `Motor power fault. All motors in shutdown.`, + `See the "Power Faults" table on the "Indicators" tab for more`, + `information. Reboot controller to reset.` + ].join(" "); + break; + } - if (!axis.enabled) continue; - if (axis.klass.indexOf('error') != -1) error = true; - if (axis.klass.indexOf('warn') != -1) warn = true; + switch (tstate) { + case "OVER": + toolmsg = [ + `Caution: The current tool path file would move`, + `${this._length_str(pathMax + off - max)}`, + `above axis limit with the current offset.` + ].join(" "); + break; + + case "UNDER": + toolmsg = [ + `Caution: The current tool path file would move`, + `${this._length_str(min - pathMin - off)}`, + `below limit with the current offset.` + ].join(" "); + break; + + case "NO FIT": + toolmsg = [ + `Warning: The current tool path dimensions`, + `(${this._length_str(pathDim)}) exceed axis dimensions`, + `(${this._length_str(dim)}) by ${this._length_str(pathDim - dim)}.` + ].join(" "); + break; + + default: + toolmsg = `Tool path ${axis} dimensions OK.`; + break; + } + + return { + pos: abs - off, + abs: abs, + off: off, + min: min, + max: max, + dim: dim, + pathMin: pathMin, + pathMax: pathMax, + pathDim: pathDim, + motor: motor_id, + enabled: enabled, + homingMode: homingMode, + homed: homed, + klass: klass, + state: state, + icon: icon, + title: title, + ticon: ticon, + tstate: tstate, + toolmsg: toolmsg, + tklass: tklass + }; + }, + + _get_motor_id: function(axis) { + for (let i = 0; i < this.config.motors.length; i++) { + const motor = this.config.motors[i]; + if (motor.axis.toLowerCase() == axis) { + return i; + } + } + + return -1; + }, + + _compute_axes: function() { + let homed = false; + + for (const name of "xyzabc") { + const axis = this[name]; + + if (!axis.enabled) { + continue; + } + + if (!axis.homed) { + homed = false; break; + } + + homed = true; + } + + let error = false; + let warn = false; + + if (homed) { + for (const name of "xyzabc") { + const axis = this[name]; + + if (!axis.enabled) { + continue; + } + + if (axis.klass.indexOf("error") != -1) { + error = true; + } + + if (axis.klass.indexOf("warn") != -1) { + warn = true; + } + } + } + + let klass = homed ? "homed" : "unhomed"; + if (error) { + klass += " error"; + } else if (warn) { + klass += " warn"; + } + + if (!homed && this.ask_home) { + this.ask_home = false; + SvelteComponents.showDialog("HomeMachine", { + home: () => this.home() + }); + } + + return { + homed: homed, + klass: klass + }; } - - var klass = homed ? 'homed' : 'unhomed'; - if (error) klass += ' error'; - else if (warn) klass += ' warn'; - - if(!homed && this.ask_home) - { - this.ask_home_msg = true; - this.ask_home = false; - } - - return { - homed: homed, - klass: klass - } } - } -} +}; diff --git a/src/js/console.js b/src/js/console.js index 5607bba..90cf8bf 100644 --- a/src/js/console.js +++ b/src/js/console.js @@ -1,87 +1,72 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict' - +"use strict"; function _msg_equal(a, b) { - return a.level == b.level && a.source == b.source && a.where == b.where && - a.msg == b.msg; + return a.level == b.level + && a.source == b.source + && a.where == b.where + && a.msg == b.msg; } - // Shared among all instances -var messages = []; - +const messages = []; module.exports = { - template: '#console-template', + template: "#console-template", + data: function() { + return { + messages + }; + }, - data: function () { - return {messages: messages} - }, + events: { + log: function(msg) { + // There may be multiple instances of this module so ignore messages + // that have already been processed. + if (msg.logged) { + return; + } + msg.logged = true; - events: { - log: function (msg) { - // There may be multiple instances of this module so ignore messages - // that have already been processed. - if (msg.logged) return; - msg.logged = true; + // Make sure we have a message level + msg.level = msg.level || "info"; - // Make sure we have a message level - msg.level = msg.level || 'info'; + // Add to message log and count and collapse repeats + const repeat = messages.length && _msg_equal(msg, messages[0]); + if (repeat) { + messages[0].repeat++; + } else { + msg.repeat = msg.repeat || 1; + messages.unshift(msg); + while (256 < messages.length) { + messages.pop(); + } + } + msg.ts = Date.now(); - // Add to message log and count and collapse repeats - var repeat = messages.length && _msg_equal(msg, messages[0]); - if (repeat) messages[0].repeat++; - else { - msg.repeat = msg.repeat || 1; - messages.unshift(msg); - while (256 < messages.length) messages.pop(); - } - msg.ts = Date.now(); + // Write message to browser console for debugging + const text = JSON.stringify(msg); + if (msg.level == "error" || msg.level == "critical") { + console.error(text); + } else if (msg.level == "warning") { + console.warn(text); + } else if (msg.level == "debug" && console.debug) { + console.debug(text); + } else { + console.log(text); + } - // Write message to browser console for debugging - var text = JSON.stringify(msg); - if (msg.level == 'error' || msg.level == 'critical') console.error(text); - else if (msg.level == 'warning') console.warn(text); - else if (msg.level == 'debug' && console.debug) console.debug(text); - else console.log(text); + // Event on errors + if (msg.level == "error" || msg.level == "critical") { + this.$dispatch("error", msg); + } + } + }, - // Event on errors - if (msg.level == 'error' || msg.level == 'critical') - this.$dispatch('error', msg); + methods: { + clear: function() { + messages.splice(0, messages.length); + }, } - }, - - - methods: { - clear: function () {messages.splice(0, messages.length);}, - } -} +}; diff --git a/src/js/control-view.js b/src/js/control-view.js index 802f3d5..bce3252 100644 --- a/src/js/control-view.js +++ b/src/js/control-view.js @@ -1,713 +1,499 @@ -/******************************************************************************\ +"use strict"; - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict' - -var api = require('./api'); -var cookie = require('./cookie')('bbctrl-'); +const api = require("./api"); +const utils = require("./utils"); +const cookie = require("./cookie")("bbctrl-"); module.exports = { - template: '#control-view-template', - props: ['config', 'template', 'state'], + template: "#control-view-template", + props: [ "config", "template", "state" ], - data: function () { - return { - mach_units: 'METRIC', - mdi: '', - last_file: undefined, - last_file_time: undefined, - toolpath: {}, - toolpath_progress: 0, - axes: 'xyzabc', - history: [], - speed_override: 1, - feed_override: 1, - manual_home: { - x: false, - y: false, - z: false, - a: false, - b: false, - c: false - }, - position_msg: { - x: false, - y: false, - z: false, - a: false, - b: false, - c: false - }, - axis_position: 0, - jog_step: cookie.get_bool('jog-step'), - jog_adjust: parseInt(cookie.get('jog-adjust', 2)), - deleteGCode: false, - tab: 'auto', - jog_incr: 1.0, - tool_diameter: 6.35, - tool_diameter_for_prompt: 6.35, - show_probe_test_modal: false, - show_tool_diameter_modal: false, - toolpath_msg: { - x: false, - y: false, - z: false, - a: false, - b: false, - c: false - }, - ask_home: true, - ask_home_msg: false, - ask_zero_xy_msg: false, - ask_zero_z_msg: false, - showGcodeMessage: false - } - }, - - components: { - 'axis-control': require('./axis-control'), - 'path-viewer': require('./path-viewer'), - 'gcode-viewer': require('./gcode-viewer') - }, - - - watch: { - 'state.imperial': { - handler: function (imperial) { - this.mach_units = imperial ? 'IMPERIAL' : 'METRIC'; - }, - immediate: true - }, - - 'state.bitDiameter': { - handler: function (bitDiameter) { - this.tool_diameter = bitDiameter; - }, - immediate: true + data: function() { + return { + current_time: "", + mach_units: this.$root.state.metric ? "METRIC" : "IMPERIAL", + mdi: "", + last_file: undefined, + last_file_time: undefined, + toolpath: {}, + toolpath_progress: 0, + axes: "xyzabc", + history: [], + speed_override: 1, + feed_override: 1, + jog_incr_amounts: { + "METRIC": { + fine: 0.1, + small: 1.0, + medium: 10, + large: 100, + }, + "IMPERIAL": { + fine: 0.005, + small: 0.05, + medium: 0.5, + large: 5, + } + }, + jog_incr: localStorage.getItem("jog_incr") || "small", + jog_step: cookie.get_bool("jog-step"), + jog_adjust: parseInt(cookie.get("jog-adjust", 2)), + deleteGCode: false, + tab: "auto", + ask_home: true, + showGcodeMessage: false + }; }, - - mach_units: function (units) { - if ((units == 'METRIC') != this.metric) - this.send(units == 'METRIC' ? 'G21' : 'G20'); - - this.units_changed(); + components: { + "axis-control": require("./axis-control"), + "path-viewer": require("./path-viewer"), + "gcode-viewer": require("./gcode-viewer") }, - 'state.line': function () { - if (this.mach_state != 'HOMING') - this.$broadcast('gcode-line', this.state.line); - }, - - 'state.selected_time': function () { - this.load(); - }, - - jog_step: function () { - cookie.set_bool('jog-step', this.jog_step); - }, - - jog_adjust: function () { - cookie.set('jog-adjust', this.jog_adjust); - } - }, - - - computed: { - metric: function () { - return !this.state.imperial; - }, - - - mach_state: function () { - var cycle = this.state.cycle; - var state = this.state.xx; - - if (typeof cycle != 'undefined' && state != 'ESTOPPED' && - (cycle == 'jogging' || cycle == 'homing')) - return cycle.toUpperCase(); - return state || '' - }, - - - pause_reason: function () {return this.state.pr}, - - - is_running: function () { - return this.mach_state == 'RUNNING' || this.mach_state == 'HOMING'; - }, - - - is_stopping: function () {return this.mach_state == 'STOPPING'}, - is_holding: function () {return this.mach_state == 'HOLDING'}, - is_ready: function () {return this.mach_state == 'READY'}, - is_idle: function () {return this.state.cycle == 'idle'}, - - - is_paused: function () { - return this.is_holding && - (this.pause_reason == 'User pause' || - this.pause_reason == 'Program pause') - }, - - - can_mdi: function () {return this.is_idle || this.state.cycle == 'mdi'}, - - - can_set_axis: function () { - return this.is_idle - // TODO allow setting axis position during pause - return this.is_idle || this.is_paused - }, - - - message: function () { - if (this.mach_state == 'ESTOPPED') return this.state.er; - if (this.mach_state == 'HOLDING') return this.state.pr; - if (this.state.messages.length) - return this.state.messages.slice(-1)[0].text; - return ''; - }, - - - highlight_state: function () { - return this.mach_state == 'ESTOPPED' || this.mach_state == 'HOLDING'; - }, - - - plan_time: function () {return this.state.plan_time}, - - - plan_time_remaining: function () { - if (!(this.is_stopping || this.is_running || this.is_holding)) return 0; - return this.toolpath.time - this.plan_time - }, - - - eta: function () { - if (this.mach_state != 'RUNNING') return ''; - var remaining = this.plan_time_remaining; - var d = new Date(); - d.setSeconds(d.getSeconds() + remaining); - return d.toLocaleString(); - }, - - - progress: function () { - if (!this.toolpath.time || this.is_ready) return 0; - var p = this.plan_time / this.toolpath.time; - return p < 1 ? p : 1; - } - }, - - - events: { - jog: function (axis, power) { - var data = {ts: new Date().getTime()}; - data[axis] = power; - api.put('jog', data); - }, - - back2zero: function(axis0,axis1) { - this.send("G0"+axis0+"0"+axis1+"0"); - }, - - step: function (axis, value) { - this.send('M70\nG91\nG0' + axis + value + '\nM72'); - }, - - probing_failed: function() { - Vue.set(this.state, "probing_active", false); - Vue.set(this.state, "wait_for_probing_complete", false); - Vue.set(this.state, "show_probe_complete_modal", false); - Vue.set(this.state, "goto_xy_zero_after_probe", false); - - Vue.set(this.state, "show_probe_failed_modal", true); - }, - - probing_complete: function() { - Vue.set(this.state, "probing_active", false); - - if (this.config.settings['probing-prompts']) { - Vue.set(this.state, "show_probe_complete_modal", true); - } else { - this.$emit("finalize_probe"); - } - }, - - finalize_probe: function() { - Vue.set(this.state, "show_probe_complete_modal", false); - - if (this.state.goto_xy_zero_after_probe) { - this.goto_zero(1, 1, 0, 0); - } - - Vue.set(this.state, "goto_xy_zero_after_probe", false); - } - }, - - - ready: function () { - this.load() - }, - - - methods: { - units_changed : function() { - if(this.mach_units == 'METRIC') { - document.getElementById("jog_button_fine").innerHTML = "0.1"; - document.getElementById("jog_button_small").innerHTML = "1.0"; - document.getElementById("jog_button_medium").innerHTML = "10"; - document.getElementById("jog_button_large").innerHTML = "100"; - } else { - document.getElementById("jog_button_fine").innerHTML = "0.005"; - document.getElementById("jog_button_small").innerHTML = "0.05"; - document.getElementById("jog_button_medium").innerHTML = "0.5"; - document.getElementById("jog_button_large").innerHTML = "5"; - } - - this.set_jog_incr('small'); - }, - - start_probe_test: function(on_finish) { - if (!this.config.settings['probing-prompts']) { - on_finish(); - return; - } - - this.show_probe_test_modal = true; - Vue.set(this.state, "saw_probe_connected", false); - Vue.set(this.state, "on_probe_finish", on_finish); - }, - - finish_probe_test: function() { - this.show_probe_test_modal = false; - Vue.set(this.state, "saw_probe_connected", false); - - const on_finish = this.state.on_probe_finish; - Vue.set(this.state, "on_probe_finish", undefined); - - on_finish(); - }, - - hide_probe_failed_modal: function() { - Vue.set(this.state, "show_probe_failed_modal", false); - }, - - prep_and_show_tool_diameter_modal() { - this.tool_diameter_for_prompt = (this.mach_units == 'METRIC') - ? this.tool_diameter - : this.tool_diameter / 25.4; - - this.tool_diameter_for_prompt = this.tool_diameter_for_prompt.toFixed(3).replace(/0+$/, ""); - - this.show_tool_diameter_modal = true; - }, - - set_tool_diameter() { - this.tool_diameter = parseFloat(this.tool_diameter_for_prompt); - - if (!isFinite(this.tool_diameter)) { - return; - } - - this.show_tool_diameter_modal = false; - - if (this.mach_units !== "METRIC") { - this.tool_diameter *= 25.4; - } - - this.probe_xyz(); - }, - - probe(zOnly = false) { - const xdim = this.config.probe["probe-xdim"]; - const ydim = this.config.probe["probe-ydim"]; - const zdim = this.config.probe["probe-zdim"]; - const slowSeek = this.config.probe["probe-slow-seek"]; - const fastSeek = this.config.probe["probe-fast-seek"]; - - const zlift = 1; - const xoffset = xdim + (this.tool_diameter / 2.0); - const yoffset = ydim + (this.tool_diameter / 2.0); - const zoffset = zdim; - - const metric = this.mach_units == "METRIC"; - const mm = n => (metric ? n : n / 25.4).toFixed(5); - const speed = s => `F${mm(s)}`; - - // After probing Z, we want to drop the bit down: - // Ideally, 12.7mm/0.5in - // And we don't want to be more than 75% down on the probe block - // Also, add zlift to compensate for the fact that we lift after probing Z - const plunge = Math.min(12.7, zoffset * 0.75) + zlift; - - Vue.set(this.state, "probing_active", true); - Vue.set(this.state, "goto_xy_zero_after_probe", !zOnly); - - if (zOnly) { - this.send(` - ${metric ? "G21" : "G20"} - G92 Z0 - - G38.2 Z ${mm(-25.4)} ${speed(fastSeek)} - G91 G1 Z ${mm(1)} - G38.2 Z ${mm(-2)} ${speed(slowSeek)} - G92 Z ${mm(zoffset)} - - G91 G0 Z ${mm(3)} - - M2 - `); - } else { - this.send(` - ${metric ? "G21" : "G20"} - G92 X0 Y0 Z0 - - G38.2 Z ${mm(-25.4)} ${speed(fastSeek)} - G91 G1 Z ${mm(1)} - G38.2 Z ${mm(-2)} ${speed(slowSeek)} - G92 Z ${mm(zoffset)} - - G91 G0 Z ${mm(zlift)} - G91 G0 X ${mm(20)} - G91 G0 Z ${mm(-plunge)} - G38.2 X ${mm(-20)} ${speed(fastSeek)} - G91 G1 X ${mm(1)} - G38.2 X ${mm(-2)} ${speed(slowSeek)} - G92 X ${mm(xoffset)} - - G91 G0 X ${mm(1)} - G91 G0 Y ${mm(20)} - G91 G0 X ${mm(-20)} - G38.2 Y ${mm(-20)} ${speed(fastSeek)} - G91 G1 Y ${mm(1)} - G38.2 Y ${mm(-2)} ${speed(slowSeek)} - G92 Y ${mm(yoffset)} - - G91 G0 Y ${mm(3)} - G91 G0 Z ${mm(25.4)} - - M2 - `); - } - - // Wait 1 second to let the probing sequence begin, - // then wait for probing to be complete - setTimeout(() => Vue.set(this.state, "wait_for_probing_complete", true), 1000); - }, - - probe_xyz() { - this.probe(false); - }, - - probe_z() { - this.probe(true); - }, - - set_jog_incr: function(newValue) { - document.getElementById("jog_button_fine").style.fontWeight = 'normal'; - document.getElementById("jog_button_small").style.fontWeight = 'normal'; - document.getElementById("jog_button_medium").style.fontWeight = 'normal'; - document.getElementById("jog_button_large").style.fontWeight = 'normal'; - - if (newValue == 'fine') { - document.getElementById("jog_button_fine").style.fontWeight = 'bold'; - if(this.mach_units == 'METRIC') - this.jog_incr = 0.1; - else - this.jog_incr = 0.005; - } else if (newValue == 'small') { - document.getElementById("jog_button_small").style.fontWeight = 'bold'; - if(this.mach_units == 'METRIC') - this.jog_incr = 1.0; - else - this.jog_incr = 0.05; - } else if (newValue == 'medium') { - document.getElementById("jog_button_medium").style.fontWeight = 'bold'; - if(this.mach_units == 'METRIC') - this.jog_incr = 10; - else - this.jog_incr = 0.5; - } else if (newValue == 'large') { - document.getElementById("jog_button_large").style.fontWeight = 'bold'; - - this.jog_incr = (this.mach_units == 'METRIC') - ? 100 - : 5; - } - }, - - goto_zero(zero_x,zero_y,zero_z,zero_a) { - var xcmd = ""; - var ycmd = ""; - var zcmd = ""; - var acmd = ""; - if(zero_x) xcmd = "X0"; - if(zero_y) ycmd = "Y0"; - if(zero_z) zcmd = "Z0"; - if(zero_a) acmd = "A0"; - - this.ask_zero_xy_msg = false; - this.ask_zero_z_msg = false; - - this.send('G90\nG0' + xcmd + ycmd + zcmd + acmd + '\n'); - }, - - jog_fn: function (x_jog,y_jog,z_jog,a_jog) { - var xcmd = "X" + x_jog * this.jog_incr; - var ycmd = "Y" + y_jog * this.jog_incr; - var zcmd = "Z" + z_jog * this.jog_incr; - var acmd = "A" + a_jog * this.jog_incr; - - this.send('G91\nG0' + xcmd + ycmd + zcmd + acmd + '\n'); - }, - - send: function (msg) { - this.$dispatch('send', msg) - }, - - load: function () { - var file_time = this.state.selected_time; - var file = this.state.selected; - if (this.last_file == file && this.last_file_time == file_time) return; - this.last_file = file; - this.last_file_time = file_time; - - this.$broadcast('gcode-load', file); - this.$broadcast('gcode-line', this.state.line); - this.toolpath_progress = 0; - this.load_toolpath(file, file_time); - }, - - - load_toolpath: async function (file, file_time) { - this.toolpath = {}; - - if (!file) return; - if (this.last_file_time != file_time) return; - - this.showGcodeMessage = true; - - while (this.showGcodeMessage) { - const toolpath = await api.get(`path/${file}`); - this.toolpath_progress = toolpath.progress; - - if (toolpath.progress === 1 || typeof toolpath.progress == 'undefined') { - this.showGcodeMessage = false - - if (toolpath.bounds) { - toolpath.filename = file; - this.toolpath_progress = 1; - this.toolpath = toolpath; - - const state = this.$root.state; - for (let axis of 'xyzabc') { - Vue.set(state, 'path_min_' + axis, toolpath.bounds.min[axis]); - Vue.set(state, 'path_max_' + axis, toolpath.bounds.max[axis]); + watch: { + jog_incr: function(value) { + localStorage.setItem("jog_incr", value); + }, + + "state.metric": { + handler: function(metric) { + this.mach_units = metric + ? "METRIC" + : "IMPERIAL"; + }, + immediate: true + }, + + "state.line": function() { + if (this.mach_state != "HOMING") { + this.$broadcast("gcode-line", this.state.line); } - } + }, + + "state.selected_time": function() { + this.load(); + }, + + jog_step: function() { + cookie.set_bool("jog-step", this.jog_step); + }, + + jog_adjust: function() { + cookie.set("jog-adjust", this.jog_adjust); } - } }, + computed: { + display_units: { + cache: false, + get: function() { + return this.$root.display_units; + }, + set: function(value) { + this.$root.display_units = value; + } + }, - submit_mdi: function () { - this.send(this.mdi); - if (!this.history.length || this.history[0] != this.mdi) - this.history.unshift(this.mdi); - this.mdi = ''; + metric: function() { + return this.display_units === "METRIC"; + }, + + mach_state: function() { + const cycle = this.state.cycle; + const state = this.state.xx; + + if (state != "ESTOPPED" && (cycle == "jogging" || cycle == "homing")) { + return cycle.toUpperCase(); + } + + return state || ""; + }, + + pause_reason: function() { + return this.state.pr; + }, + + is_running: function() { + return this.mach_state == "RUNNING" || this.mach_state == "HOMING"; + }, + + is_stopping: function() { + return this.mach_state == "STOPPING"; + }, + + is_holding: function() { + return this.mach_state == "HOLDING"; + }, + + is_ready: function() { + return this.mach_state == "READY"; + }, + + is_idle: function() { + return this.state.cycle == "idle"; + }, + + is_paused: function() { + return this.is_holding && (this.pause_reason == "User pause" || this.pause_reason == "Program pause"); + }, + + can_mdi: function() { + return this.is_idle || this.state.cycle == "mdi"; + }, + + can_set_axis: function() { + return this.is_idle; + + // TODO allow setting axis position during pause + // return this.is_idle || this.is_paused; + }, + + message: function() { + if (this.mach_state == "ESTOPPED") { + return this.state.er; + } + + if (this.mach_state == "HOLDING") { + return this.state.pr; + } + + if (this.state.messages.length) { + return this.state.messages.slice(-1)[0].text; + } + + return ""; + }, + + highlight_state: function() { + return this.mach_state == "ESTOPPED" || this.mach_state == "HOLDING"; + }, + + plan_time: function() { + return this.state.plan_time; + }, + + plan_time_remaining: function() { + if (!(this.is_stopping || this.is_running || this.is_holding)) { + return 0; + } + + return this.toolpath.time - this.plan_time; + }, + + eta: function() { + if (this.mach_state != "RUNNING") { + return ""; + } + + const remaining = this.plan_time_remaining; + const d = new Date(); + d.setSeconds(d.getSeconds() + remaining); + return d.toLocaleString(); + }, + + progress: function() { + if (!this.toolpath.time || this.is_ready) { + return 0; + } + + const p = this.plan_time / this.toolpath.time; + return Math.min(1, p); + } }, + events: { + jog: function(axis, power) { + const data = { ts: new Date().getTime() }; + data[axis] = power; + api.put("jog", data); + }, - mdi_start_pause: function () { - if (this.state.xx == 'RUNNING') this.pause(); + back2zero: function(axis0, axis1) { + this.send(`G0 ${axis0}0 ${axis1}0`); + }, - else if (this.state.xx == 'STOPPING' || this.state.xx == 'HOLDING') - this.unpause(); - - else this.submit_mdi(); + step: function(axis, value) { + this.send(` + M70 + G91 + G0 ${axis}${value} + M72 + `); + }, }, + ready: function() { + this.load(); - load_history: function (index) { - this.mdi = this.history[index]; + setInterval(() => { + this.current_time = new Date().toLocaleTimeString(); + }, 1000); + + SvelteComponents.registerControllerMethods({ + stop: (...args) => this.stop(...args), + send: (...args) => this.send(...args), + isAxisHomed: (axis) => this[axis].homed, + unhome: (...args) => this.unhome(...args), + set_position: (...args) => this.set_position(...args), + set_home: (...args) => this.set_home(...args) + }); }, + methods: { + getJogIncrStyle(value) { + const weight = `font-weight:${this.jog_incr === value ? "bold" : "normal"}`; + const color = this.jog_incr === value ? "color:#0078e7" : ""; - open: function (e) { - // If we don't reset the form the browser may cache file if name is same - // even if contents have changed - $('.gcode-file-input')[0].reset(); - $('.gcode-file-input input').click(); + return [ weight, color ].join(";"); + }, + + jog_fn: function(x_jog, y_jog, z_jog, a_jog) { + const amount = this.jog_incr_amounts[this.display_units][this.jog_incr]; + + const xcmd = `X${x_jog * amount}`; + const ycmd = `Y${y_jog * amount}`; + const zcmd = `Z${z_jog * amount}`; + const acmd = `A${a_jog * amount}`; + + this.send(` + G91 + ${this.metric ? "G21" : "G20"} + G0 ${xcmd}${ycmd}${zcmd}${acmd} + `); + }, + + send: function(msg) { + this.$dispatch("send", msg); + }, + + load: function() { + const file_time = this.state.selected_time; + const file = this.state.selected; + if (this.last_file == file && this.last_file_time == file_time) { + return; + } + + this.last_file = file; + this.last_file_time = file_time; + + this.$broadcast("gcode-load", file); + this.$broadcast("gcode-line", this.state.line); + this.toolpath_progress = 0; + this.load_toolpath(file, file_time); + }, + + load_toolpath: async function(file, file_time) { + this.toolpath = {}; + + if (!file || this.last_file_time != file_time) { + return; + } + + this.showGcodeMessage = true; + + while (this.showGcodeMessage) { + const toolpath = await api.get(`path/${file}`); + this.toolpath_progress = toolpath.progress; + + if (toolpath.progress === 1 || typeof toolpath.progress == "undefined") { + this.showGcodeMessage = false; + + if (toolpath.bounds) { + toolpath.filename = file; + this.toolpath_progress = 1; + this.toolpath = toolpath; + + const state = this.$root.state; + for (const axis of "xyzabc") { + Vue.set(state, `path_min_${axis}`, toolpath.bounds.min[axis]); + Vue.set(state, `path_max_${axis}`, toolpath.bounds.max[axis]); + } + } + } + } + }, + + submit_mdi: function() { + this.send(this.mdi); + + if (!this.history.length || this.history[0] != this.mdi) { + this.history.unshift(this.mdi); + } + + this.mdi = ""; + }, + + mdi_start_pause: function() { + if (this.state.xx == "RUNNING") { + this.pause(); + } else if (this.state.xx == "STOPPING" || this.state.xx == "HOLDING") { + this.unpause(); + } else { + this.submit_mdi(); + } + }, + + load_history: function(index) { + this.mdi = this.history[index]; + }, + + open: function() { + utils.clickFileInput("gcode-file-input"); + }, + + upload: function(e) { + const files = e.target.files || e.dataTransfer.files; + if (!files.length) { + return; + } + + const file = files[0]; + + const extension = file.name.split(".").pop(); + switch (extension.toLowerCase()) { + case "nc": + case "ngc": + case "gcode": + case "gc": + break; + + default: + alert(`Unsupported file type: ${extension}`); + return; + } + + SvelteComponents.showDialog("Upload", { + file, + onComplete: () => { + this.last_file_time = undefined; // Force reload + this.$broadcast("gcode-reload", file.name); + } + }); + }, + + delete_current: function() { + if (this.state.selected) { + api.delete(`file/${this.state.selected}`); + } + + this.deleteGCode = false; + }, + + delete_all: function() { + api.delete("file"); + this.deleteGCode = false; + }, + + home: function(axis) { + this.ask_home = false; + + if (typeof axis == "undefined") { + api.put("home"); + } else if (this[axis].homingMode != "manual") { + api.put(`home/${axis}`); + } else { + SvelteComponents.showDialog("ManualHomeAxis", { axis }); + } + }, + + set_home: function(axis, position) { + api.put(`home/${axis}/set`, { position: parseFloat(position) }); + }, + + unhome: function(axis) { + api.put(`home/${axis}/clear`); + }, + + show_set_position: function(axis) { + SvelteComponents.showDialog("SetAxisPosition", { axis }); + }, + + showMoveToZeroDialog: function(axes) { + SvelteComponents.showDialog("MoveToZero", { axes }); + }, + + showToolpathMessageDialog: function(axis) { + SvelteComponents.showDialog("Message", { title: this[axis].toolmsg }); + }, + + set_position: function(axis, position) { + api.put(`position/${axis}`, { "position": parseFloat(position) }); + }, + + zero_all: function() { + for (const axis of "xyzabc") { + if (this[axis].enabled) { + this.zero(axis); + } + } + }, + + zero: function(axis) { + if (typeof axis == "undefined") { + this.zero_all(); + } else { + this.set_position(axis, 0); + } + }, + + start_pause: function() { + if (this.state.xx == "RUNNING") { + this.pause(); + } else if (this.state.xx == "STOPPING" || this.state.xx == "HOLDING") { + this.unpause(); + } else { + this.start(); + } + }, + + start: function() { + api.put("start"); + }, + + pause: function() { + api.put("pause"); + }, + + unpause: function() { + api.put("unpause"); + }, + + optional_pause: function() { + api.put("pause/optional"); + }, + + stop: function() { + api.put("stop"); + }, + + step: function() { + api.put("step"); + }, + + override_feed: function() { + api.put(`override/feed/${this.feed_override}`); + }, + + override_speed: function() { + api.put(`override/speed/${this.speed_override}`); + }, + + current: function(axis, value) { + const x = value / 32.0; + if (this.state[`${axis}pl`] == x) { + return; + } + + const data = {}; + data[`${axis}pl`] = x; + this.send(JSON.stringify(data)); + }, + + showProbeDialog: function(probeType) { + SvelteComponents.showDialog("Probe", { probeType }); + } }, - - upload: async function (e) { - const files = e.target.files || e.dataTransfer.files; - if (!files.length) { - return; - } - - const file = files[0]; - - const extension = file.name.split(".").pop(); - switch (extension.toLowerCase()) { - case "nc": - case "ngc": - case "gcode": - case "gc": - break; - - default: - alert(`Unsupported file type: ${extension}`); - return; - } - - const fd = new FormData(); - - fd.append('gcode', file); - - try { - await api.upload('file', fd); - - this.last_file_time = undefined; // Force reload - this.$broadcast('gcode-reload', file.name); - } catch (err) { - api.alert('Upload failed', err) - } - }, - - - delete_current: function () { - if (this.state.selected) { - api.delete('file/' + this.state.selected); - } - - this.deleteGCode = false; - }, - - - delete_all: function () { - api.delete('file'); - this.deleteGCode = false; - }, - - - home: function (axis) { - - this.ask_home = false; - this.ask_home_msg = false; - - if (typeof axis == 'undefined') api.put('home'); - - else { - if (this[axis].homingMode != 'manual') api.put('home/' + axis); - else this.manual_home[axis] = true; - } - }, - - - set_home: function (axis, position) { - this.manual_home[axis] = false; - api.put('home/' + axis + '/set', {position: parseFloat(position)}); - }, - - - unhome: function (axis) { - this.position_msg[axis] = false; - api.put('home/' + axis + '/clear'); - }, - - - show_set_position: function (axis) { - this.axis_position = 0; - this.position_msg[axis] = true; - }, - - show_toolpath_msg : function(axis) { - this.toolpath_msg[axis] = true; - }, - - - set_position: function (axis, position) { - this.position_msg[axis] = false; - api.put('position/' + axis, {'position': parseFloat(position)}); - }, - - - zero_all: function () { - for (var axis of 'xyzabc') - if (this[axis].enabled) this.zero(axis); - }, - - - zero: function (axis) { - if (typeof axis == 'undefined') this.zero_all(); - else this.set_position(axis, 0); - }, - - - start_pause: function () { - if (this.state.xx == 'RUNNING') this.pause(); - - else if (this.state.xx == 'STOPPING' || this.state.xx == 'HOLDING') - this.unpause(); - - else this.start(); - }, - - - start: function () {api.put('start')}, - pause: function () {api.put('pause')}, - unpause: function () {api.put('unpause')}, - optional_pause: function () {api.put('pause/optional')}, - stop: function () {api.put('stop')}, - step: function () {api.put('step')}, - - - override_feed: function () {api.put('override/feed/' + this.feed_override)}, - - - override_speed: function () { - api.put('override/speed/' + this.speed_override) - }, - - - current: function (axis, value) { - var x = value / 32.0; - if (this.state[axis + 'pl'] == x) return; - - var data = {}; - data[axis + 'pl'] = x; - this.send(JSON.stringify(data)); - } - }, - - - mixins: [require('./axis-vars')] -} + mixins: [ require("./axis-vars") ] +}; diff --git a/src/js/cookie.js b/src/js/cookie.js index 6244436..2ec1e36 100644 --- a/src/js/cookie.js +++ b/src/js/cookie.js @@ -1,69 +1,49 @@ -/******************************************************************************\ +"use strict"; - Copyright 2018. Buildbotics LLC - All Rights Reserved. - - For information regarding this software email: - Joseph Coffland - joseph@buildbotics.com - - This software is free software: you clan redistribute it and/or - modify it under the terms of the GNU Lesser General Public License - as published by the Free Software Foundation, either version 2.1 of - the License, or (at your option) any later version. - - This software is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the C! library. If not, see - . - -\******************************************************************************/ - -'use strict' - - -module.exports = function (prefix) { - if (typeof prefix == 'undefined') prefix = ''; - - var cookie = { - get: function (name, defaultValue) { - var decodedCookie = decodeURIComponent(document.cookie); - var ca = decodedCookie.split(';'); - name = prefix + name + '='; - - for (var i = 0; i < ca.length; i++) { - var c = ca[i]; - while (c.charAt(0) == ' ') c = c.substring(1); - if (!c.indexOf(name)) return c.substring(name.length, c.length); - } - - return defaultValue; - }, - - - set: function (name, value, days) { - var offset = 2147483647; // Max value - if (typeof days != 'undefined') offset = days * 24 * 60 * 60 * 1000; - var d = new Date(); - d.setTime(d.getTime() + offset); - var expires = 'expires=' + d.toUTCString(); - document.cookie = prefix + name + '=' + value + ';' + expires + ';path=/'; - }, - - - set_bool: function (name, value) { - cookie.set(name, value ? 'true' : 'false'); - }, - - - get_bool: function (name, defaultValue) { - return cookie.get(name, defaultValue ? 'true' : 'false') == 'true'; +module.exports = function(prefix) { + if (typeof prefix == "undefined") { + prefix = ""; } - } - return cookie; -} + const cookie = { + get: function(name, defaultValue) { + const decodedCookie = decodeURIComponent(document.cookie); + const ca = decodedCookie.split(";"); + name = `${prefix + name}=`; + + for (let i = 0; i < ca.length; i++) { + let c = ca[i]; + while (c.charAt(0) == " ") { + c = c.substring(1); + } + if (!c.indexOf(name)) { + return c.substring(name.length, c.length); + } + } + + return defaultValue; + }, + + set: function(name, value, days) { + let offset = 2147483647; // Max value + if (typeof days != "undefined") { + offset = days * 24 * 60 * 60 * 1000; + } + + const d = new Date(); + d.setTime(d.getTime() + offset); + const expires = `expires=${d.toUTCString()}`; + document.cookie = `${prefix}${name}=${value};${expires};path=/`; + }, + + set_bool: function(name, value) { + cookie.set(name, value ? "true" : "false"); + }, + + get_bool: function(name, defaultValue) { + return cookie.get(name, defaultValue ? "true" : "false") == "true"; + } + }; + + return cookie; +}; diff --git a/src/js/gcode-viewer.js b/src/js/gcode-viewer.js index 633a8d5..4a877df 100644 --- a/src/js/gcode-viewer.js +++ b/src/js/gcode-viewer.js @@ -1,168 +1,154 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict' - -var api = require('./api'); - - -var entityMap = { - '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', - '/': '/', '`': '`', '=': '='} +"use strict"; +const entityMap = { + "&": "&", "<": "<", ">": ">", '"': """, "'": "'", + "/": "/", "`": "`", "=": "=" }; function escapeHTML(s) { - return s.replace(/[&<>"'`=\/]/g, function (c) {return entityMap[c]}) + return s.replace(/[&<>"'`=\\/]/g, function(c) { + return entityMap[c]; + }); } - module.exports = { - template: '#gcode-viewer-template', + template: "#gcode-viewer-template", - - data: function () { - return { - empty: true, - file: '', - line: -1, - scrolling: false - } - }, - - - events: { - 'gcode-load': function (file) {this.load(file)}, - 'gcode-clear': function () {this.clear()}, - 'gcode-reload': function (file) {this.reload(file)}, - 'gcode-line': function (line) {this.update_line(line)} - }, - - - ready: function () { - this.clusterize = new Clusterize({ - rows: [], - scrollElem: $(this.$el).find('.clusterize-scroll')[0], - contentElem: $(this.$el).find('.clusterize-content')[0], - no_data_text: 'GCode view...', - callbacks: {clusterChanged: this.highlight} - }); - }, - - - attached: function () { - if (typeof this.clusterize != 'undefined') - this.clusterize.refresh(true); - }, - - - methods: { - load: async function(file) { - if (file == this.file) return; - this.clear(); - this.file = file; - - if (!file) return; - - const response = await fetch(`/api/file/${file}?${Math.random()}`); - const text = await response.text(); - - if (text.length > 20e6) { - this.clusterize.update(['File is large - gcode view disabled']); - } else { - const lines = escapeHTML(text.trimRight()) - .split(/[\r\n]/) - .map((line, i) => `
  • ${i + 1}${line}
  • `); - - this.clusterize.update(lines); - } - - this.empty = false; - - Vue.nextTick(this.update_line); + data: function() { + return { + empty: true, + file: "", + line: -1 + }; }, - - clear: function () { - this.empty = true; - this.file = ''; - this.line = -1; - this.clusterize.clear(); - }, - - - reload: function (file) { - if (file != this.file) return; - this.clear(); - this.load(file); - }, - - - highlight: function () { - var e = $(this.$el).find('.highlight'); - if (e.length) e.removeClass('highlight'); - - e = $(this.$el).find('.ln' + this.line); - if (e.length) e.addClass('highlight'); - }, - - - update_line: function(line) { - if (typeof line != 'undefined') { - if (this.line == line) return; - this.line = line; - - } else line = this.line; - - var totalLines = this.clusterize.getRowsAmount(); - - if (line <= 0) line = 1; - if (totalLines < line) line = totalLines; - - var e = $(this.$el).find('.clusterize-scroll'); - - var lineHeight = e[0].scrollHeight / totalLines; - var linesPerPage = Math.floor(e[0].clientHeight / lineHeight); - var current = e[0].scrollTop / lineHeight; - var target = line - 1 - Math.floor(linesPerPage / 2); - - // Update scroll position - if (!this.scrolling) { - if (target < current - 20 || current + 20 < target) - e[0].scrollTop = target * lineHeight; - - else { - this.scrolling = true; - e.animate({scrollTop: target * lineHeight}, { - complete: function () {this.scrolling = false}.bind(this) - }) + events: { + "gcode-load": function(file) { + this.load(file); + }, + "gcode-clear": function() { + this.clear(); + }, + "gcode-reload": function(file) { + this.reload(file); + }, + "gcode-line": function(line) { + this.update_line(line); } - } + }, - Vue.nextTick(this.highlight); + ready: function() { + this.clusterize = new Clusterize({ + rows: [], + scrollElem: this.$el.querySelector(".clusterize-scroll"), + contentElem: this.$el.querySelector(".clusterize-content"), + no_data_text: "GCode view...", + callbacks: { clusterChanged: this.highlight } + }); + }, + + attached: function() { + if (typeof this.clusterize != "undefined") { + this.clusterize.refresh(true); + } + }, + + methods: { + load: async function(file) { + if (file == this.file) { + return; + } + + this.clear(); + this.file = file; + + if (!file) { + return; + } + + const response = await fetch(`/api/file/${file}`, { cache: "no-cache" }); + const text = await response.text(); + + if (text.length > 20e6) { + this.clusterize.update([ "File is large - gcode view disabled" ]); + } else { + const lines = escapeHTML(text.trimRight()) + .split(/[\r\n]/) + .map((line, i) => `
  • ${i + 1}${line}
  • `); + + this.clusterize.update(lines); + } + + this.empty = false; + + Vue.nextTick(this.update_line); + }, + + clear: function() { + this.empty = true; + this.file = ""; + this.line = -1; + this.clusterize.clear(); + }, + + reload: function(file) { + if (file != this.file) { + return; + } + + this.clear(); + this.load(file); + }, + + highlight: function() { + const highlights = this.$el.querySelectorAll(".highlight"); + for (const highlight of highlights) { + highlight.className = (highlight.className || "") + .split(" ") + .filter(c => c !== "highlight") + .join(" "); + } + + const lines = this.$el.querySelectorAll(`.ln${this.line}`); + for (const line of lines) { + line.className = (line.className || "") + .split(" ") + .filter(c => c !== "highlight") + .concat([ "highlight" ]) + .join(" "); + } + }, + + update_line: function(line) { + if (typeof line != "undefined") { + if (this.line == line) { + return; + } + + this.line = line; + } else { + line = this.line; + } + + const totalLines = this.clusterize.getRowsAmount(); + + if (line <= 0) { + line = 1; + } + + if (totalLines < line) { + line = totalLines; + } + + const scroll = this.$el.querySelector(".clusterize-scroll"); + + const lineHeight = scroll.scrollHeight / totalLines; + const linesPerPage = Math.floor(scroll.clientHeight / lineHeight); + const target = line - 1 - Math.floor(linesPerPage / 2); + + // Update scroll position + scroll.scrollTop = target * lineHeight; + + Vue.nextTick(this.highlight); + } } - } -} +}; diff --git a/src/js/indicators.js b/src/js/indicators.js index 0285784..811d63f 100644 --- a/src/js/indicators.js +++ b/src/js/indicators.js @@ -1,107 +1,94 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict' - -var modbus = require('./modbus.js'); +"use strict"; +const modbus = require("./modbus.js"); module.exports = { - template: '#indicators-template', - props: ['state'], + template: "#indicators-template", + props: [ "state" ], + computed: { + modbus_status: function() { + return modbus.status_to_string(this.state.mx); + }, - computed: { - modbus_status: function () {return modbus.status_to_string(this.state.mx)}, + sense_error: function() { + let error = ""; + if (this.state.motor_voltage_sense_error) { + error += "Motor voltage\n"; + } + if (this.state.motor_current_sense_error) { + error += "Motor current\n"; + } + if (this.state.load1_sense_error) { + error += "Load 1\n"; + } + if (this.state.load2_sense_error) { + error += "Load 2\n"; + } + if (this.state.vdd_current_sense_error) { + error += "Vdd current\n"; + } - sense_error: function () { - var error = ''; + return error; + } + }, - if (this.state.motor_voltage_sense_error) error += 'Motor voltage\n'; - if (this.state.motor_current_sense_error) error += 'Motor current\n'; - if (this.state.load1_sense_error) error += 'Load 1\n'; - if (this.state.load2_sense_error) error += 'Load 2\n'; - if (this.state.vdd_current_sense_error) error += 'Vdd current\n'; + methods: { + is_motor_enabled: function(motor) { + return typeof this.state[`${motor}me`] != "undefined" && this.state[`${motor}me`]; + }, - return error; + get_min_pin: function(motor) { + switch (motor) { + case 0: return 3; + case 1: return 5; + case 2: return 9; + case 3: return 11; + } + }, + + get_max_pin: function(motor) { + switch (motor) { + case 0: return 4; + case 1: return 8; + case 2: return 10; + case 3: return 12; + } + }, + + motor_fault_class: function(motor, bit) { + if (typeof motor == "undefined") { + const status = this.state["fa"]; + + if (typeof status == "undefined") { + return "fa-question"; + } + + return `fa-thumbs-${status ? "down error" : "up success"}`; + } + + const flags = this.state[`${motor}df`]; + + if (typeof flags == "undefined") { + return "fa-question"; + } + + return (flags & (1 << bit)) ? "fa-thumbs-down error" : + "fa-thumbs-up success"; + }, + + motor_reset: function(motor) { + if (typeof motor == "undefined") { + let cmd = ""; + for (let i = 0; i < 4; i++) { + cmd += `\\$${i}df=0\n`; + } + + this.$dispatch("send", cmd); + } else { + this.$dispatch("send", `\\$${motor}df=0`); + } + } } - }, - - - methods: { - is_motor_enabled: function (motor) { - return typeof this.state[motor + 'me'] != 'undefined' && - this.state[motor + 'me']; - }, - - - get_min_pin: function (motor) { - switch (motor) { - case 0: return 3; - case 1: return 5; - case 2: return 9; - case 3: return 11; - } - }, - - - get_max_pin: function (motor) { - switch (motor) { - case 0: return 4; - case 1: return 8; - case 2: return 10; - case 3: return 12; - } - }, - - - motor_fault_class: function (motor, bit) { - if (typeof motor == 'undefined') { - var status = this.state['fa']; - if (typeof status == 'undefined') return 'fa-question'; - return 'fa-thumbs-' + (status ? 'down error' : 'up success') - } - - var flags = this.state[motor + 'df']; - if (typeof flags == 'undefined') return 'fa-question'; - return (flags & (1 << bit)) ? 'fa-thumbs-down error' : - 'fa-thumbs-up success'; - }, - - - motor_reset: function (motor) { - if (typeof motor == 'undefined') { - var cmd = ''; - for (var i = 0; i < 4; i++) - cmd += '\\$' + i + 'df=0\n'; - this.$dispatch('send', cmd); - - } else this.$dispatch('send', '\\$' + motor + 'df=0'); - } - } -} +}; diff --git a/src/js/io-indicator.js b/src/js/io-indicator.js index 1803661..f1956d0 100644 --- a/src/js/io-indicator.js +++ b/src/js/io-indicator.js @@ -1,177 +1,155 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict' - +"use strict"; module.exports = { - template: "#io-indicator-template", - props: ['name', 'state'], + template: "#io-indicator-template", + props: [ "name", "state" ], + computed: { + klass: function() { + switch (this.name) { + case "min-switch-0": return this.get_motor_min_class(0); + case "min-switch-1": return this.get_motor_min_class(1); + case "min-switch-2": return this.get_motor_min_class(2); + case "min-switch-3": return this.get_motor_min_class(3); + case "max-switch-0": return this.get_motor_max_class(0); + case "max-switch-1": return this.get_motor_max_class(1); + case "max-switch-2": return this.get_motor_max_class(2); + case "max-switch-3": return this.get_motor_max_class(3); + case "estop": return this.get_input_class("ew", "et"); + case "probe": return this.get_input_class("pw", "pt"); + case "load-1": return this.get_output_class("1"); + case "load-2": return this.get_output_class("2"); + case "fault": return this.get_output_class("f"); + case "tool-enable-mode": return this.get_output_class("e"); + case "tool-direction-mode": return this.get_output_class("d"); + } + }, - computed: { - klass: function () { - if (this.name == 'min-switch-0') return this.get_motor_min_class(0); - if (this.name == 'min-switch-1') return this.get_motor_min_class(1); - if (this.name == 'min-switch-2') return this.get_motor_min_class(2); - if (this.name == 'min-switch-3') return this.get_motor_min_class(3); - if (this.name == 'max-switch-0') return this.get_motor_max_class(0); - if (this.name == 'max-switch-1') return this.get_motor_max_class(1); - if (this.name == 'max-switch-2') return this.get_motor_max_class(2); - if (this.name == 'max-switch-3') return this.get_motor_max_class(3); - if (this.name == 'estop') return this.get_input_class('ew', 'et'); - if (this.name == 'probe') return this.get_input_class('pw', 'pt'); - if (this.name == 'load-1') return this.get_output_class('1'); - if (this.name == 'load-2') return this.get_output_class('2'); - if (this.name == 'fault') return this.get_output_class('f'); - if (this.name == 'tool-enable-mode') return this.get_output_class('e'); - if (this.name == 'tool-direction-mode') return this.get_output_class('d'); + tooltip: function() { + switch (this.name) { + case "min-switch-0": return this.get_motor_min_tooltip(0); + case "min-switch-1": return this.get_motor_min_tooltip(1); + case "min-switch-2": return this.get_motor_min_tooltip(2); + case "min-switch-3": return this.get_motor_min_tooltip(3); + case "max-switch-0": return this.get_motor_max_tooltip(0); + case "max-switch-1": return this.get_motor_max_tooltip(1); + case "max-switch-2": return this.get_motor_max_tooltip(2); + case "max-switch-3": return this.get_motor_max_tooltip(3); + case "estop": return this.get_input_tooltip("ew", "et"); + case "probe": return this.get_input_tooltip("pw", "pt"); + case "load-1": return this.get_output_tooltip("1"); + case "load-2": return this.get_output_tooltip("2"); + case "fault": return this.get_output_tooltip("f"); + case "tool-direction-mode": return this.get_output_tooltip("d"); + case "tool-enable-mode": return this.get_output_tooltip("e"); + } + } }, + methods: { + get_io_state_class: function(active, state) { + if (typeof active == "undefined" || typeof state == "undefined") { + return "fa-exclamation-triangle warn"; + } - tooltip: function () { - if (this.name == 'min-switch-0') return this.get_motor_min_tooltip(0); - if (this.name == 'min-switch-1') return this.get_motor_min_tooltip(1); - if (this.name == 'min-switch-2') return this.get_motor_min_tooltip(2); - if (this.name == 'min-switch-3') return this.get_motor_min_tooltip(3); - if (this.name == 'max-switch-0') return this.get_motor_max_tooltip(0); - if (this.name == 'max-switch-1') return this.get_motor_max_tooltip(1); - if (this.name == 'max-switch-2') return this.get_motor_max_tooltip(2); - if (this.name == 'max-switch-3') return this.get_motor_max_tooltip(3); - if (this.name == 'estop') return this.get_input_tooltip('ew', 'et'); - if (this.name == 'probe') return this.get_input_tooltip('pw', 'pt'); - if (this.name == 'load-1') return this.get_output_tooltip('1'); - if (this.name == 'load-2') return this.get_output_tooltip('2'); - if (this.name == 'fault') return this.get_output_tooltip('f'); - if (this.name == 'tool-direction-mode') - return this.get_output_tooltip('d'); - if (this.name == 'tool-enable-mode') - return this.get_output_tooltip('e'); + if (state == 2) { + return "fa-circle-o"; + } + + const icon = state ? "fa-plus-circle" : "fa-minus-circle"; + return `${icon} ${active ? "active" : "inactive"}`; + }, + + get_input_active: function(stateCode, typeCode) { + const type = this.state[typeCode]; + const state = this.state[stateCode]; + + if (type == 1) { + return !state; // Normally open + } else if (type == 2) { + return state; // Normally closed + } + + return false; + }, + + get_input_class: function(stateCode, typeCode) { + return this.get_io_state_class(this.get_input_active(stateCode, typeCode), this.state[stateCode]); + }, + + get_output_class: function(output) { + return this.get_io_state_class(this.state[`${output}oa`], this.state[`${output}os`]); + }, + + get_motor_min_class: function(motor) { + return this.get_input_class(`${motor}lw`, `${motor}ls`); + }, + + get_motor_max_class: function(motor) { + return this.get_input_class(`${motor}xw`, `${motor}xs`); + }, + + get_tooltip: function(mode, active, state) { + if (typeof mode == "undefined" || typeof active == "undefined" || typeof state == "undefined") { + return "Invalid"; + } + + if (state == 0) { + state = "Lo/Gnd"; + } else if (state == 1) { + state = "Hi/+3.3v"; + } else if (state == 2) { + state = "Tristated"; + } else { + return "Invalid"; + } + + return `Mode: ${mode}\nActive: ${active ? "True" : "False"}\nLevel: ${state}`; + }, + + get_input_tooltip: function(stateCode, typeCode) { + let type = this.state[typeCode]; + if (type == 0) { + return "Disabled"; + } else if (type == 1) { + type = "Normally open"; + } else if (type == 2) { + type = "Normally closed"; + } + + const active = this.get_input_active(stateCode, typeCode); + const state = this.state[stateCode]; + + return this.get_tooltip(type, active, state); + }, + + get_output_tooltip: function(output) { + let mode = this.state[`${output}om`]; + + switch (mode) { + case 0: return "Disabled"; + case 1: mode = "Lo/Hi"; break; + case 2: mode = "Hi/Lo"; break; + case 3: mode = "Tri/Lo"; break; + case 4: mode = "Tri/Hi"; break; + case 5: mode = "Lo/Tri"; break; + case 6: mode = "Hi/Tri"; break; + default: + mode = undefined; + } + + const active = this.state[`${output}oa`]; + const state = this.state[`${output}os`]; + + return this.get_tooltip(mode, active, state); + }, + + get_motor_min_tooltip: function(motor) { + return this.get_input_tooltip(`${motor}lw`, `${motor}ls`); + }, + + get_motor_max_tooltip: function(motor) { + return this.get_input_tooltip(`${motor}xw`, `${motor}xs`); + } } - }, - - - methods: { - get_io_state_class: function (active, state) { - if (typeof active == 'undefined' || typeof state == 'undefined') - return 'fa-exclamation-triangle warn'; - - if (state == 2) return 'fa-circle-o'; - - return (state ? 'fa-plus-circle' : 'fa-minus-circle') + ' ' + - (active ? 'active' : 'inactive'); - }, - - - get_input_active: function (stateCode, typeCode) { - var type = this.state[typeCode]; - var state = this.state[stateCode]; - - if (type == 1) return !state; // Normally open - else if (type == 2) return state; // Normally closed - - return false - }, - - - get_input_class: function (stateCode, typeCode) { - return this.get_io_state_class(this.get_input_active(stateCode, typeCode), - this.state[stateCode]); - }, - - - get_output_class: function (output) { - return this.get_io_state_class(this.state[output + 'oa'], - this.state[output + 'os']); - }, - - - get_motor_min_class: function (motor) { - return this.get_input_class(motor + 'lw', motor + 'ls'); - }, - - - get_motor_max_class: function (motor) { - return this.get_input_class(motor + 'xw', motor + 'xs'); - }, - - - get_tooltip: function (mode, active, state) { - if (typeof mode == 'undefined' || typeof active == 'undefined' || - typeof state == 'undefined') return 'Invalid'; - - if (state == 0) state = 'Lo/Gnd'; - else if (state == 1) state = 'Hi/+3.3v'; - else if (state == 2) state = 'Tristated'; - else return 'Invalid'; - - return 'Mode: ' + mode + '\nActive: ' + (active ? 'True' : 'False') + - '\nLevel: ' + state; - }, - - - get_input_tooltip: function (stateCode, typeCode) { - var type = this.state[typeCode]; - if (type == 0) return 'Disabled'; - else if (type == 1) type = 'Normally open'; - else if (type == 2) type = 'Normally closed'; - - var active = this.get_input_active(stateCode, typeCode); - var state = this.state[stateCode]; - - return this.get_tooltip(type, active, state); - }, - - - get_output_tooltip: function (output) { - var mode = this.state[output + 'om']; - if (mode == 0) return 'Disabled'; - else if (mode == 1) mode = 'Lo/Hi'; - else if (mode == 2) mode = 'Hi/Lo'; - else if (mode == 3) mode = 'Tri/Lo'; - else if (mode == 4) mode = 'Tri/Hi'; - else if (mode == 5) mode = 'Lo/Tri'; - else if (mode == 6) mode = 'Hi/Tri'; - else mode = undefined; - - var active = this.state[output + 'oa']; - var state = this.state[output + 'os']; - - return this.get_tooltip(mode, active, state); - }, - - - get_motor_min_tooltip: function (motor) { - return this.get_input_tooltip(motor + 'lw', motor + 'ls'); - }, - - - get_motor_max_tooltip: function (motor) { - return this.get_input_tooltip(motor + 'xw', motor + 'xs'); - } - } -} +}; diff --git a/src/js/io-view.js b/src/js/io-view.js index 1cbdc49..4d2679b 100644 --- a/src/js/io-view.js +++ b/src/js/io-view.js @@ -1,42 +1,13 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict' - +"use strict"; module.exports = { - template: '#io-view-template', - props: ['config', 'template', 'state'], + template: "#io-view-template", + props: [ "config", "template", "state" ], - - events: { - 'input-changed': function() { - this.$dispatch('config-changed'); - return false; + events: { + "input-changed": function() { + this.$dispatch("config-changed"); + return false; + } } - } -} +}; diff --git a/src/js/main.js b/src/js/main.js index d369409..f58ad13 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -1,147 +1,148 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict'; - +"use strict"; function cookie_get(name) { - var decodedCookie = decodeURIComponent(document.cookie); - var ca = decodedCookie.split(';'); - name = name + '='; + const decodedCookie = decodeURIComponent(document.cookie); + const ca = decodedCookie.split(";"); + name = `${name}=`; - for (var i = 0; i < ca.length; i++) { - var c = ca[i]; - while (c.charAt(0) == ' ') c = c.substring(1); - if (!c.indexOf(name)) return c.substring(name.length, c.length); - } + for (let i = 0; i < ca.length; i++) { + let c = ca[i]; + while (c.charAt(0) == " ") { + c = c.substring(1); + } + + if (!c.indexOf(name)) { + return c.substring(name.length, c.length); + } + } } - function cookie_set(name, value, days) { - var d = new Date(); - d.setTime(d.getTime() + days * 24 * 60 * 60 * 1000); - var expires = 'expires=' + d.toUTCString(); - document.cookie = name + '=' + value + ';' + expires + ';path=/'; + const d = new Date(); + d.setTime(d.getTime() + days * 24 * 60 * 60 * 1000); + const expires = `expires=${d.toUTCString()}`; + document.cookie = `${name}=${value};${expires};path=/`; } - -var uuid_chars = - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_+'; - +const uuid_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_+"; function uuid(length) { - if (typeof length == 'undefined') length = 52; + if (typeof length == "undefined") { + length = 52; + } - var s = ''; - for (var i = 0; i < length; i++) - s += uuid_chars[Math.floor(Math.random() * uuid_chars.length)]; + let s = ""; + for (let i = 0; i < length; i++) { + s += uuid_chars[Math.floor(Math.random() * uuid_chars.length)]; + } - return s + return s; } - -$(function() { - if (typeof cookie_get('client-id') == 'undefined') - cookie_set('client-id', uuid(), 10000); - - // Vue debugging - Vue.config.debug = true; - //Vue.util.warn = function (msg) {console.debug('[Vue warn]: ' + msg)} - - // Register global components - Vue.component('templated-input', require('./templated-input')); - Vue.component('message', require('./message')); - Vue.component('indicators', require('./indicators')); - Vue.component('io-indicator', require('./io-indicator')); - Vue.component('console', require('./console')); - Vue.component('unit-value', require('./unit-value')); - - Vue.filter('number', function (value) { - if (isNaN(value)) return 'NaN'; - return value.toLocaleString(); - }); - - Vue.filter('percent', function (value, precision) { - if (typeof value == 'undefined') return ''; - if (typeof precision == 'undefined') precision = 2; - return (value * 100.0).toFixed(precision) + '%'; - }); - - Vue.filter('non_zero_percent', function (value, precision) { - if (!value) return ''; - if (typeof precision == 'undefined') precision = 2; - return (value * 100.0).toFixed(precision) + '%'; - }); - - Vue.filter('fixed', function (value, precision) { - if (typeof value == 'undefined') return '0'; - return parseFloat(value).toFixed(precision) - }); - - Vue.filter('upper', function (value) { - if (typeof value == 'undefined') return ''; - return value.toUpperCase() - }); - - Vue.filter('time', function (value, precision) { - if (isNaN(value)) return ''; - if (isNaN(precision)) precision = 0; - - var MIN = 60; - var HR = MIN * 60; - var DAY = HR * 24; - var parts = []; - - if (DAY <= value) { - parts.push(Math.floor(value / DAY)); - value %= DAY; +window.onload = function() { + if (typeof cookie_get("client-id") == "undefined") { + cookie_set("client-id", uuid(), 10000); } - if (HR <= value) { - parts.push(Math.floor(value / HR)); - value %= HR; - } + // Register global components + Vue.component("templated-input", require("./templated-input")); + Vue.component("message", require("./message")); + Vue.component("indicators", require("./indicators")); + Vue.component("io-indicator", require("./io-indicator")); + Vue.component("console", require("./console")); + Vue.component("unit-value", require("./unit-value")); - if (MIN <= value) { - parts.push(Math.floor(value / MIN)); - value %= MIN; + Vue.filter("number", function(value) { + if (isNaN(value)) { + return "NaN"; + } - } else parts.push(0); + return value.toLocaleString(); + }); - parts.push(value); + Vue.filter("percent", function(value, precision) { + if (typeof value == "undefined") { + return ""; + } - for (var i = 0; i < parts.length; i++) { - parts[i] = parts[i].toFixed(i == parts.length - 1 ? precision : 0); - if (i && parts[i] < 10) parts[i] = '0' + parts[i]; - } + if (typeof precision == "undefined") { + precision = 2; + } - return parts.join(':'); - }); + return `${(value * 100.0).toFixed(precision)}%`; + }); - // Vue app - require('./app'); -}); + Vue.filter("non_zero_percent", function(value, precision) { + if (!value) { + return ""; + } + + if (typeof precision == "undefined") { + precision = 2; + } + + return `${(value * 100.0).toFixed(precision)}%`; + }); + + Vue.filter("fixed", function(value, precision) { + if (typeof value == "undefined") { + return "0"; + } + + return parseFloat(value).toFixed(precision); + }); + + Vue.filter("upper", function(value) { + if (typeof value == "undefined") { + return ""; + } + + return value.toUpperCase(); + }); + + Vue.filter("time", function(value, precision) { + if (isNaN(value)) { + return ""; + } + + if (isNaN(precision)) { + precision = 0; + } + + const MIN = 60; + const HR = MIN * 60; + const DAY = HR * 24; + const parts = []; + + if (DAY <= value) { + parts.push(Math.floor(value / DAY)); + value %= DAY; + } + + if (HR <= value) { + parts.push(Math.floor(value / HR)); + value %= HR; + } + + if (MIN <= value) { + parts.push(Math.floor(value / MIN)); + value %= MIN; + } else { + parts.push(0); + } + + parts.push(value); + + for (let i = 0; i < parts.length; i++) { + parts[i] = parts[i].toFixed(i == parts.length - 1 ? precision : 0); + if (i && parts[i] < 10) { + parts[i] = `0${parts[i]}`; + } + } + + return parts.join(":"); + }); + + // Vue app + require("./app"); +}; diff --git a/src/js/message.js b/src/js/message.js index 57c1fae..3f4c1d4 100644 --- a/src/js/message.js +++ b/src/js/message.js @@ -1,47 +1,19 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict' - +"use strict"; module.exports = { - template: '#message-template', + template: "#message-template", - props: { - show: { - type: Boolean, - required: true, - twoWay: true - }, + props: { + show: { + type: Boolean, + required: true, + twoWay: true + }, - class: { - type: String, - required: false, - twoWay: false + class: { + type: String, + required: false, + twoWay: false + } } - } -} +}; diff --git a/src/js/modbus-reg.js b/src/js/modbus-reg.js index 224f22e..464dcf0 100644 --- a/src/js/modbus-reg.js +++ b/src/js/modbus-reg.js @@ -1,48 +1,20 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict' - +"use strict"; module.exports = { - replace: true, - template: '#modbus-reg-view-template', - props: ['index', 'model', 'template', 'enable'], + replace: true, + template: "#modbus-reg-view-template", + props: [ "index", "model", "template", "enable" ], + computed: { + has_user_value: function() { + const type = this.model["reg-type"]; + return type.indexOf("write") != -1 || type.indexOf("fixed") != -1; + } + }, - computed: { - has_user_value: function () { - var type = this.model['reg-type']; - return type.indexOf('write') != -1 || type.indexOf('fixed') != -1; + methods: { + change: function() { + this.$dispatch("input-changed"); + } } - }, - - - methods: { - change: function () {this.$dispatch('input-changed')} - } -} +}; diff --git a/src/js/modbus.js b/src/js/modbus.js index 83a7504..8ce2543 100644 --- a/src/js/modbus.js +++ b/src/js/modbus.js @@ -1,51 +1,23 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict' - +"use strict"; // Must match modbus.c -var exports = { - DISCONNECTED: 0, - OK: 1, - CRC: 2, - INVALID: 3, - TIMEDOUT: 4 +const constants = { + DISCONNECTED: 0, + OK: 1, + CRC: 2, + INVALID: 3, + TIMEDOUT: 4 }; - -exports.status_to_string = - function (status) { - if (status == exports.OK) return 'Ok'; - if (status == exports.CRC) return 'CRC error'; - if (status == exports.INVALID) return 'Invalid response'; - if (status == exports.TIMEDOUT) return 'Timedout'; - return 'Disconnected'; - } - - -module.exports = exports; +module.exports = { + ...constants, + status_to_string: function(status) { + switch (status) { + case constants.OK: return "Ok"; + case constants.CRC: return "CRC error"; + case constants.INVALID: return "Invalid response"; + case constants.TIMEDOUT: return "Timedout"; + default: return "Disconnected"; + } + } +}; diff --git a/src/js/motor-view.js b/src/js/motor-view.js index 49bbf08..8a41d3a 100644 --- a/src/js/motor-view.js +++ b/src/js/motor-view.js @@ -1,136 +1,120 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict' - +"use strict"; module.exports = { - template: '#motor-view-template', - props: ['index', 'config', 'template', 'state'], + template: "#motor-view-template", + props: [ "index", "config", "template", "state" ], + computed: { + metric: function() { + return this.$root.display_units === "METRIC"; + }, - computed: { - metric: function () {return this.$root.metric()}, + is_slave: function() { + for (let i = 0; i < this.index; i++) { + if (this.motor.axis == this.config.motors[i].axis) { + return true; + } + } + return false; + }, - is_slave: function () { - for (var i = 0; i < this.index; i++) - if (this.motor.axis == this.config.motors[i].axis) - return true; + motor: function() { + return this.config.motors[this.index]; + }, - return false; + invalidMaxVelocity: function() { + return this.maxMaxVelocity < this.motor["max-velocity"]; + }, + + maxMaxVelocity: function() { + return 1 * (15 * this.umPerStep / this.motor["microsteps"]).toFixed(3); + }, + + ustepPerSec: function() { + return this.rpm * this.stepsPerRev * this.motor["microsteps"] / 60; + }, + + rpm: function() { + return 1000 * this.motor["max-velocity"] / this.motor["travel-per-rev"]; + }, + + gForce: function() { + return this.motor["max-accel"] * 0.0283254504; + }, + + gForcePerMin: function() { + return this.motor["max-jerk"] * 0.0283254504; + }, + + stepsPerRev: function() { + return 360 / this.motor["step-angle"]; + }, + + umPerStep: function() { + return this.motor["travel-per-rev"] * this.motor["step-angle"] / 0.36; + }, + + milPerStep: function() { + return this.umPerStep / 25.4; + }, + + invalidStallVelocity: function() { + if (!this.motor["homing-mode"].startsWith("stall-")) { + return false; + } + + return this.maxStallVelocity < this.motor["search-velocity"]; + }, + + stallRPM: function() { + const v = this.motor["search-velocity"]; + return 1000 * v / this.motor["travel-per-rev"]; + }, + + maxStallVelocity: function() { + const maxRate = 900000 / this.motor["stall-sample-time"]; + const ustep = this.motor["stall-microstep"]; + const angle = this.motor["step-angle"]; + const travel = this.motor["travel-per-rev"]; + const maxStall = maxRate * 60 / 360 / 1000 * angle / ustep * travel; + + return 1 * maxStall.toFixed(3); + }, + + stallUStepPerSec: function() { + const ustep = this.motor["stall-microstep"]; + return this.stallRPM * this.stepsPerRev * ustep / 60; + } }, + events: { + "input-changed": function() { + Vue.nextTick(function() { + // Limit max-velocity + if (this.invalidMaxVelocity) { + this.$set('motor["max-velocity"]', this.maxMaxVelocity); + } - motor: function () {return this.config.motors[this.index]}, + //Limit stall-velocity + if (this.invalidStallVelocity) { + this.$set('motor["search-velocity"]', this.maxStallVelocity); + } + this.$dispatch("config-changed"); + }.bind(this)); - invalidMaxVelocity: function () { - return this.maxMaxVelocity < this.motor['max-velocity']; + return false; + } }, + methods: { + show: function(name, templ) { + if (templ.hmodes == undefined) { + return true; + } - maxMaxVelocity: function () { - return 1 * (15 * this.umPerStep / this.motor['microsteps']).toFixed(3); - }, - - - ustepPerSec: function () { - return this.rpm * this.stepsPerRev * this.motor['microsteps'] / 60; - }, - - - rpm: function () { - return 1000 * this.motor['max-velocity'] / this.motor['travel-per-rev']; - }, - - - gForce: function () {return this.motor['max-accel'] * 0.0283254504}, - gForcePerMin: function () {return this.motor['max-jerk'] * 0.0283254504}, - stepsPerRev: function () {return 360 / this.motor['step-angle']}, - - - umPerStep: function () { - return this.motor['travel-per-rev'] * this.motor['step-angle'] / 0.36 - }, - - - milPerStep: function () {return this.umPerStep / 25.4}, - - invalidStallVelocity: function() { - if(!this.motor['homing-mode'].startsWith('stall-')) return false; - return this.maxStallVelocity < this.motor['search-velocity']; - }, - - stallRPM: function() { - var v = this.motor['search-velocity']; - return 1000 * v / this.motor['travel-per-rev']; - }, - - maxStallVelocity: function() { - var maxRate = 900000/this.motor['stall-sample-time']; - var ustep = this.motor['stall-microstep']; - var angle = this.motor['step-angle']; - var travel = this.motor['travel-per-rev']; - var maxStall = maxRate * 60/ 360 /1000 * angle/ ustep * travel; - - return 1 * maxStall.toFixed(3); - }, - - stallUStepPerSec: function() { - var ustep = this.motor['stall-microstep']; - return this.stallRPM * this.stepsPerRev * ustep / 60; + return templ.hmodes.indexOf(this.motor["homing-mode"]) != -1; + } } - - }, - - - events: { - 'input-changed': function() { - Vue.nextTick(function () { - // Limit max-velocity - if (this.invalidMaxVelocity) - this.$set('motor["max-velocity"]', this.maxMaxVelocity); - - //Limit stall-velocity - if(this.invalidStallVelocity) - this.$set('motor["search-velocity"]', this.maxStallVelocity); - - this.$dispatch('config-changed'); - }.bind(this)) - - return false; - } - }, - - methods: { - show: function(name, templ) { - if(templ.hmodes == undefined) return true; - return templ.hmodes.indexOf(this.motor['homing-mode']) != -1; - } - } -} +}; diff --git a/src/js/orbit.js b/src/js/orbit.js index 45c5768..ef7a4fc 100644 --- a/src/js/orbit.js +++ b/src/js/orbit.js @@ -7,7 +7,7 @@ * @author jcoffland / https://buildbotics.com/ */ -'use strict' +"use strict"; // This set of controls performs orbiting, dollying (zooming), and panning. // Unlike TrackballControls, it maintains the "up" direction object.up @@ -17,665 +17,682 @@ // Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish // Pan - right mouse, or arrow keys / touch: two-finger move +const OrbitControls = function(object, domElement) { + // internals + // eslint-disable-next-line @typescript-eslint/no-this-alias + const scope = this; -var OrbitControls = function (object, domElement) { - this.object = object; - this.domElement = domElement != undefined ? domElement : document; + const changeEvent = { type: "change" }; + const startEvent = { type: "start" }; + const endEvent = { type: "end" }; - // Set to false to disable this control - this.enabled = true; + const STATE = { + NONE: -1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY_PAN: 4 + }; - // "target" sets the location of focus, where the object orbits around - this.target = new THREE.Vector3(); + let state = STATE.NONE; + const EPS = 0.000001; - // How far you can zoom in and out (OrthographicCamera only) - this.minZoom = 0; - this.maxZoom = Infinity; + // current position in spherical coordinates + const spherical = new THREE.Spherical(); + const sphericalDelta = new THREE.Spherical(); - // How far you can orbit vertically, upper and lower limits. - // Range is 0 to Math.PI radians. - this.minPolarAngle = 0; // radians - this.maxPolarAngle = Math.PI; // radians + let scale = 1; + const panOffset = new THREE.Vector3(); + let zoomChanged = false; - // How far you can orbit horizontally, upper and lower limits. - // If set, must be a sub-interval of the interval [- Math.PI, Math.PI]. - this.minAzimuthAngle = -Infinity; // radians - this.maxAzimuthAngle = Infinity; // radians + const rotateStart = new THREE.Vector2(); + const rotateEnd = new THREE.Vector2(); + const rotateDelta = new THREE.Vector2(); - // Set to true to enable damping (inertia) - // If damping is enabled, call controls.update() in your animation loop - this.enableDamping = false; - this.dampingFactor = 0.25; + const panStart = new THREE.Vector2(); + const panEnd = new THREE.Vector2(); + const panDelta = new THREE.Vector2(); - // This option enables dollying in and out; - // left as "zoom" for backwards compatibility. - // Set to false to disable zooming - this.enableZoom = true; - this.zoomSpeed = 1.0; + const dollyStart = new THREE.Vector2(); + const dollyEnd = new THREE.Vector2(); + const dollyDelta = new THREE.Vector2(); - // Set to false to disable rotating - this.enableRotate = true; - this.rotateSpeed = 1.0; + this.object = object; + this.domElement = domElement != undefined ? domElement : document; - // Set to false to disable panning - this.enablePan = true; - this.panSpeed = 1.0; - this.screenSpacePanning = false; // if true, pan in screen-space - this.keyPanSpeed = 7.0; // pixels moved per arrow key push + // Set to false to disable this control + this.enabled = true; - // Set to true to automatically rotate around the target - // If auto-rotate is enabled, call controls.update() in your animation loop - this.autoRotate = false; - this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 + // "target" sets the location of focus, where the object orbits around + this.target = new THREE.Vector3(); - // Set to false to disable use of the keys - this.enableKeys = true; + // How far you can zoom in and out (OrthographicCamera only) + this.minZoom = 0; + this.maxZoom = Infinity; - // The four arrow keys - this.keys = {LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40}; + // How far you can orbit vertically, upper and lower limits. + // Range is 0 to Math.PI radians. + this.minPolarAngle = 0; // radians + this.maxPolarAngle = Math.PI; // radians - // Mouse buttons - this.mouseButtons = { - ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT - }; + // How far you can orbit horizontally, upper and lower limits. + // If set, must be a sub-interval of the interval [- Math.PI, Math.PI]. + this.minAzimuthAngle = -Infinity; // radians + this.maxAzimuthAngle = Infinity; // radians - // for reset - this.target0 = this.target.clone(); - this.position0 = this.object.position.clone(); - this.zoom0 = this.object.zoom; + // Set to true to enable damping (inertia) + // If damping is enabled, call controls.update() in your animation loop + this.enableDamping = false; + this.dampingFactor = 0.25; - // public methods - this.getPolarAngle = function () {return spherical.phi} - this.getAzimuthalAngle = function () {return spherical.theta} + // This option enables dollying in and out; + // left as "zoom" for backwards compatibility. + // Set to false to disable zooming + this.enableZoom = true; + this.zoomSpeed = 1.0; + // Set to false to disable rotating + this.enableRotate = true; + this.rotateSpeed = 1.0; - this.saveState = function () { - scope.target0.copy(scope.target); - scope.position0.copy(scope.object.position); - scope.zoom0 = scope.object.zoom; - } + // Set to false to disable panning + this.enablePan = true; + this.panSpeed = 1.0; + this.screenSpacePanning = false; // if true, pan in screen-space + this.keyPanSpeed = 7.0; // pixels moved per arrow key push + // Set to true to automatically rotate around the target + // If auto-rotate is enabled, call controls.update() in your animation loop + this.autoRotate = false; + this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 - this.reset = function () { - scope.target.copy(scope.target0); - scope.object.position.copy(scope.position0); - scope.object.zoom = scope.zoom0; - scope.object.updateProjectionMatrix(); + // Set to false to disable use of the keys + this.enableKeys = true; - scope.dispatchEvent(changeEvent); - scope.update(); + // The four arrow keys + this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; - state = STATE.NONE; - } + // Mouse buttons + this.mouseButtons = { + ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT + }; + // for reset + this.target0 = this.target.clone(); + this.position0 = this.object.position.clone(); + this.zoom0 = this.object.zoom; - this.update = function () { - var offset = new THREE.Vector3(); + // public methods + this.getPolarAngle = function() { + return spherical.phi; + }; - // so camera.up is the orbit axis - var quat = new THREE.Quaternion() - .setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0)); - var quatInverse = quat.clone().inverse(); + this.getAzimuthalAngle = function() { + return spherical.theta; + }; - var lastPosition = new THREE.Vector3(); - var lastQuaternion = new THREE.Quaternion(); + this.saveState = function() { + scope.target0.copy(scope.target); + scope.position0.copy(scope.object.position); + scope.zoom0 = scope.object.zoom; + }; - return function update() { - var position = scope.object.position; - - offset.copy(position).sub(scope.target); - - // rotate offset to "y-axis-is-up" space - offset.applyQuaternion(quat); - - // angle from z-axis around y-axis - spherical.setFromVector3(offset); - - if (scope.autoRotate && state == STATE.NONE) - rotateLeft(getAutoRotationAngle()); - - spherical.theta += sphericalDelta.theta; - spherical.phi += sphericalDelta.phi; - - // restrict theta to be between desired limits - spherical.theta = - Math.max(scope.minAzimuthAngle, - Math.min(scope.maxAzimuthAngle, spherical.theta)); - - // restrict phi to be between desired limits - spherical.phi = - Math.max(scope.minPolarAngle, - Math.min(scope.maxPolarAngle, spherical.phi)); - - spherical.makeSafe(); - spherical.radius *= scale; - - // restrict radius to be between desired limits - spherical.radius = - Math.max(10, Math.min(scope.object.far * 0.8, spherical.radius)); - - // move target to panned location - scope.target.add(panOffset); - - offset.setFromSpherical(spherical); - - // rotate offset back to "camera-up-vector-is-up" space - offset.applyQuaternion(quatInverse); - - position.copy(scope.target).add(offset); - scope.object.lookAt(scope.target); - - if (scope.enableDamping) { - sphericalDelta.theta *= (1 - scope.dampingFactor); - sphericalDelta.phi *= (1 - scope.dampingFactor); - panOffset.multiplyScalar(1 - scope.dampingFactor); - - } else { - sphericalDelta.set(0, 0, 0); - panOffset.set(0, 0, 0); - } - - // update condition is: - // min(camera displacement, camera rotation in radians)^2 > EPS - // using small-angle approximation cos(x/2) = 1 - x^2 / 8 - if (zoomChanged || scale != 1 || - lastPosition.distanceToSquared(scope.object.position) > EPS || - 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) { + this.reset = function() { + scope.target.copy(scope.target0); + scope.object.position.copy(scope.position0); + scope.object.zoom = scope.zoom0; + scope.object.updateProjectionMatrix(); scope.dispatchEvent(changeEvent); + scope.update(); - lastPosition.copy(scope.object.position); - lastQuaternion.copy(scope.object.quaternion); - zoomChanged = false; - scale = 1; + state = STATE.NONE; + }; - return true; - } + this.update = function() { + const offset = new THREE.Vector3(); - return false; + // so camera.up is the orbit axis + const quat = new THREE.Quaternion().setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0)); + const quatInverse = quat.clone().inverse(); + + const lastPosition = new THREE.Vector3(); + const lastQuaternion = new THREE.Quaternion(); + + return function update() { + const position = scope.object.position; + + offset.copy(position).sub(scope.target); + + // rotate offset to "y-axis-is-up" space + offset.applyQuaternion(quat); + + // angle from z-axis around y-axis + spherical.setFromVector3(offset); + + if (scope.autoRotate && state == STATE.NONE) { + rotateLeft(getAutoRotationAngle()); + } + + spherical.theta += sphericalDelta.theta; + spherical.phi += sphericalDelta.phi; + + // restrict theta to be between desired limits + spherical.theta = Math.max(scope.minAzimuthAngle, Math.min(scope.maxAzimuthAngle, spherical.theta)); + + // restrict phi to be between desired limits + spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi)); + + spherical.makeSafe(); + spherical.radius *= scale; + + // restrict radius to be between desired limits + spherical.radius = Math.max(10, Math.min(scope.object.far * 0.8, spherical.radius)); + + // move target to panned location + scope.target.add(panOffset); + + offset.setFromSpherical(spherical); + + // rotate offset back to "camera-up-vector-is-up" space + offset.applyQuaternion(quatInverse); + + position.copy(scope.target).add(offset); + scope.object.lookAt(scope.target); + + if (scope.enableDamping) { + sphericalDelta.theta *= (1 - scope.dampingFactor); + sphericalDelta.phi *= (1 - scope.dampingFactor); + panOffset.multiplyScalar(1 - scope.dampingFactor); + + } else { + sphericalDelta.set(0, 0, 0); + panOffset.set(0, 0, 0); + } + + // update condition is: + // min(camera displacement, camera rotation in radians)^2 > EPS + // using small-angle approximation cos(x/2) = 1 - x^2 / 8 + if (zoomChanged + || scale != 1 + || lastPosition.distanceToSquared(scope.object.position) > EPS + || 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) { + + scope.dispatchEvent(changeEvent); + + lastPosition.copy(scope.object.position); + lastQuaternion.copy(scope.object.quaternion); + zoomChanged = false; + scale = 1; + + return true; + } + + return false; + }; + }(); + + this.dispose = function() { + scope.domElement.removeEventListener("contextmenu", onContextMenu, false); + scope.domElement.removeEventListener("mousedown", onMouseDown, false); + scope.domElement.removeEventListener("wheel", onMouseWheel, false); + scope.domElement.removeEventListener("touchstart", onTouchStart, false); + scope.domElement.removeEventListener("touchend", onTouchEnd, false); + scope.domElement.removeEventListener("touchmove", onTouchMove, false); + document.removeEventListener("mousemove", onMouseMove, false); + document.removeEventListener("mouseup", onMouseUp, false); + window.removeEventListener("keydown", onKeyDown, false); + }; + + function getAutoRotationAngle() { + return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; } - }() - - this.dispose = function () { - scope.domElement.removeEventListener('contextmenu', onContextMenu, false); - scope.domElement.removeEventListener('mousedown', onMouseDown, false); - scope.domElement.removeEventListener('wheel', onMouseWheel, false); - scope.domElement.removeEventListener('touchstart', onTouchStart, false); - scope.domElement.removeEventListener('touchend', onTouchEnd, false); - scope.domElement.removeEventListener('touchmove', onTouchMove, false); - document.removeEventListener('mousemove', onMouseMove, false); - document.removeEventListener('mouseup', onMouseUp, false); - window.removeEventListener('keydown', onKeyDown, false); - } - - - // internals - var scope = this; - - var changeEvent = {type: 'change'}; - var startEvent = {type: 'start'}; - var endEvent = {type: 'end'}; - - var STATE = { - NONE: -1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY_PAN: 4 - }; - - var state = STATE.NONE; - var EPS = 0.000001; - - // current position in spherical coordinates - var spherical = new THREE.Spherical(); - var sphericalDelta = new THREE.Spherical(); - - var scale = 1; - var panOffset = new THREE.Vector3(); - var zoomChanged = false; - - var rotateStart = new THREE.Vector2(); - var rotateEnd = new THREE.Vector2(); - var rotateDelta = new THREE.Vector2(); - - var panStart = new THREE.Vector2(); - var panEnd = new THREE.Vector2(); - var panDelta = new THREE.Vector2(); - - var dollyStart = new THREE.Vector2(); - var dollyEnd = new THREE.Vector2(); - var dollyDelta = new THREE.Vector2(); - - - function getAutoRotationAngle() { - return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; - } - - - function getZoomScale() {return Math.pow(0.95, scope.zoomSpeed)} - function rotateLeft(angle) {sphericalDelta.theta -= angle} - function rotateUp(angle) {sphericalDelta.phi -= angle} - - - var panLeft = function () { - var v = new THREE.Vector3(); - - return function panLeft(distance, objectMatrix) { - v.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix - v.multiplyScalar(-distance); - panOffset.add(v); + function getZoomScale() { + return Math.pow(0.95, scope.zoomSpeed); } - }() - - var panUp = function () { - var v = new THREE.Vector3(); - - return function panUp(distance, objectMatrix) { - if (scope.screenSpacePanning) v.setFromMatrixColumn(objectMatrix, 1); - else { - v.setFromMatrixColumn(objectMatrix, 0); - v.crossVectors(scope.object.up, v); - } - - v.multiplyScalar(distance); - panOffset.add(v); + function rotateLeft(angle) { + sphericalDelta.theta -= angle; } - }() - - function unknownCamera() { - console.warn('WARNING: OrbitControls.js encountered an unknown camera ' + - 'type - pan & zoom disabled.'); - scope.enablePan = false; - scope.enableZoom = false; - } - - - // deltaX and deltaY are in pixels; right and down are positive - var pan = function () { - var offset = new THREE.Vector3(); - - return function pan(deltaX, deltaY) { - var element = scope.domElement === document ? - scope.domElement.body : scope.domElement; - - if (scope.object.isPerspectiveCamera) { - // perspective - offset.copy(scope.object.position).sub(scope.target); - var targetDistance = offset.length(); - - // half of the fov is center to top of screen - targetDistance *= Math.tan((scope.object.fov / 2) * Math.PI / 180.0); - - // we use only clientHeight here so aspect ratio does not distort speed - panLeft(2 * deltaX * targetDistance / element.clientHeight, - scope.object.matrix); - panUp(2 * deltaY * targetDistance / element.clientHeight, - scope.object.matrix); - - } else if (scope.object.isOrthographicCamera) { - // orthographic - panLeft(deltaX * (scope.object.right - scope.object.left) / - scope.object.zoom / element.clientWidth, scope.object.matrix); - panUp(deltaY * (scope.object.top - scope.object.bottom) / - scope.object.zoom / element.clientHeight, scope.object.matrix); - - } else unknownCamera(); + function rotateUp(angle) { + sphericalDelta.phi -= angle; } - }() + const panLeft = function() { + const v = new THREE.Vector3(); - function dollyIn(dollyScale) { - if (scope.object.isPerspectiveCamera) scale /= dollyScale; + return function panLeft(distance, objectMatrix) { + v.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix + v.multiplyScalar(-distance); + panOffset.add(v); + }; + }(); - else if (scope.object.isOrthographicCamera) { - scope.object.zoom = + const panUp = function() { + const v = new THREE.Vector3(); + + return function panUp(distance, objectMatrix) { + if (scope.screenSpacePanning) { + v.setFromMatrixColumn(objectMatrix, 1); + } else { + v.setFromMatrixColumn(objectMatrix, 0); + v.crossVectors(scope.object.up, v); + } + + v.multiplyScalar(distance); + panOffset.add(v); + }; + }(); + + function unknownCamera() { + console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan & zoom disabled."); + scope.enablePan = false; + scope.enableZoom = false; + } + + // deltaX and deltaY are in pixels; right and down are positive + const pan = function() { + const offset = new THREE.Vector3(); + + return function pan(deltaX, deltaY) { + const element = scope.domElement === document + ? scope.domElement.body + : scope.domElement; + + if (scope.object.isPerspectiveCamera) { + // perspective + offset.copy(scope.object.position).sub(scope.target); + let targetDistance = offset.length(); + + // half of the fov is center to top of screen + targetDistance *= Math.tan((scope.object.fov / 2) * Math.PI / 180.0); + + // we use only clientHeight here so aspect ratio does not distort speed + panLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix); + panUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix); + + } else if (scope.object.isOrthographicCamera) { + // orthographic + panLeft(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth, scope.object.matrix); + panUp(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight, scope.object.matrix); + + } else { + unknownCamera(); + } + }; + }(); + + function dollyIn(dollyScale) { + if (scope.object.isPerspectiveCamera) { + scale /= dollyScale; + } else if (scope.object.isOrthographicCamera) { + scope.object.zoom = Math.max(scope.minZoom, - Math.min(scope.maxZoom, scope.object.zoom * dollyScale)); - scope.object.updateProjectionMatrix(); - zoomChanged = true; + Math.min(scope.maxZoom, scope.object.zoom * dollyScale)); + scope.object.updateProjectionMatrix(); + zoomChanged = true; - } else unknownCamera(); - } + } else { + unknownCamera(); + } + } - - function dollyOut(dollyScale) { - if (scope.object.isPerspectiveCamera) scale *= dollyScale; - - else if (scope.object.isOrthographicCamera) { - scope.object.zoom = + function dollyOut(dollyScale) { + if (scope.object.isPerspectiveCamera) { + scale *= dollyScale; + } else if (scope.object.isOrthographicCamera) { + scope.object.zoom = Math.max(scope.minZoom, - Math.min(scope.maxZoom, scope.object.zoom / dollyScale)); - scope.object.updateProjectionMatrix(); - zoomChanged = true; + Math.min(scope.maxZoom, scope.object.zoom / dollyScale)); + scope.object.updateProjectionMatrix(); + zoomChanged = true; - } else unknownCamera(); - } - - - // event callbacks - update the object state - function handleMouseDownRotate(event) { - rotateStart.set(event.clientX, event.clientY); - } - - - function handleMouseDownDolly(event) { - dollyStart.set(event.clientX, event.clientY); - } - - - function handleMouseDownPan(event) { - panStart.set(event.clientX, event.clientY); - } - - - function handleMouseMoveRotate(event) { - rotateEnd.set(event.clientX, event.clientY); - rotateDelta.subVectors(rotateEnd, rotateStart) - .multiplyScalar(scope.rotateSpeed); - - var element = scope.domElement === document ? - scope.domElement.body : scope.domElement; - - // yes, height - rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight); - rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight); - - rotateStart.copy(rotateEnd); - - scope.update(); - } - - - function handleMouseMoveDolly(event) { - dollyEnd.set(event.clientX, event.clientY); - dollyDelta.subVectors(dollyEnd, dollyStart); - - if (dollyDelta.y > 0) dollyIn(getZoomScale()); - else if (dollyDelta.y < 0) dollyOut(getZoomScale()); - - dollyStart.copy(dollyEnd); - scope.update(); - } - - - function handleMouseMovePan(event) { - panEnd.set(event.clientX, event.clientY); - panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed); - pan(panDelta.x, panDelta.y); - panStart.copy(panEnd); - scope.update(); - } - - - function handleMouseUp(event) {} - - - function handleMouseWheel(event) { - if (event.deltaY < 0) dollyOut(getZoomScale()); - else if (event.deltaY > 0) dollyIn(getZoomScale()); - - scope.update(); - } - - - function handleKeyDown(event) { - switch (event.keyCode) { - case scope.keys.UP: - pan(0, scope.keyPanSpeed); - scope.update(); - break; - - case scope.keys.BOTTOM: - pan(0, -scope.keyPanSpeed); - scope.update(); - break; - - case scope.keys.LEFT: - pan(scope.keyPanSpeed, 0); - scope.update(); - break; - - case scope.keys.RIGHT: - pan(-scope.keyPanSpeed, 0); - scope.update(); - break; - } - } - - - function handleTouchStartRotate(event) { - rotateStart.set(event.touches[0].pageX, event.touches[0].pageY); - } - - - function handleTouchStartDollyPan(event) { - if (scope.enableZoom) { - var dx = event.touches[0].pageX - event.touches[1].pageX; - var dy = event.touches[0].pageY - event.touches[1].pageY; - var distance = Math.sqrt(dx * dx + dy * dy); - - dollyStart.set(0, distance); + } else { + unknownCamera(); + } } - if (scope.enablePan) { - var x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX); - var y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY); - panStart.set(x, y); - } - } - - - function handleTouchMoveRotate(event) { - rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY); - rotateDelta.subVectors(rotateEnd, rotateStart) - .multiplyScalar(scope.rotateSpeed); - - var element = scope.domElement === document ? - scope.domElement.body : scope.domElement; - - // yes, height - rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight); - rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight); - rotateStart.copy(rotateEnd); - scope.update(); - } - - - function handleTouchMoveDollyPan(event) { - if (scope.enableZoom) { - var dx = event.touches[0].pageX - event.touches[1].pageX; - var dy = event.touches[0].pageY - event.touches[1].pageY; - var distance = Math.sqrt(dx * dx + dy * dy); - - dollyEnd.set(0, distance); - dollyDelta.set(0, Math.pow(dollyEnd.y / dollyStart.y, scope.zoomSpeed)); - dollyIn(dollyDelta.y); - dollyStart.copy(dollyEnd); + // event callbacks - update the object state + function handleMouseDownRotate(event) { + rotateStart.set(event.clientX, event.clientY); } - - if (scope.enablePan) { - var x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX); - var y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY); - - panEnd.set(x, y); - panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed); - pan(panDelta.x, panDelta.y); - panStart.copy(panEnd); + function handleMouseDownDolly(event) { + dollyStart.set(event.clientX, event.clientY); } - scope.update(); - } - - - function handleTouchEnd(event) {} - - - // event handlers - listen for events and reset state - function onMouseDown(event) { - if (!scope.enabled) return; - - event.preventDefault(); - - switch (event.button) { - case scope.mouseButtons.ORBIT: - if (!scope.enableRotate) return; - handleMouseDownRotate(event); - state = STATE.ROTATE; - break; - - case scope.mouseButtons.ZOOM: - if (!scope.enableZoom) return; - handleMouseDownDolly(event); - state = STATE.DOLLY; - break; - - case scope.mouseButtons.PAN: - if (!scope.enablePan) return; - handleMouseDownPan(event); - state = STATE.PAN; - break; + function handleMouseDownPan(event) { + panStart.set(event.clientX, event.clientY); } - if (state != STATE.NONE) { - document.addEventListener('mousemove', onMouseMove, false); - document.addEventListener('mouseup', onMouseUp, false); - scope.dispatchEvent(startEvent); - } - } + function handleMouseMoveRotate(event) { + rotateEnd.set(event.clientX, event.clientY); + rotateDelta.subVectors(rotateEnd, rotateStart) + .multiplyScalar(scope.rotateSpeed); + const element = scope.domElement === document ? + scope.domElement.body : scope.domElement; - function onMouseMove(event) { - if (!scope.enabled) return; + // yes, height + rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight); + rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight); - event.preventDefault(); + rotateStart.copy(rotateEnd); - switch (state) { - case STATE.ROTATE: - if (!scope.enableRotate) return; - handleMouseMoveRotate(event); - break; - - case STATE.DOLLY: - if (!scope.enableZoom) return; - handleMouseMoveDolly(event); - break; - - case STATE.PAN: - if (!scope.enablePan) return; - handleMouseMovePan(event); - break; - } - } - - - function onMouseUp(event) { - if (!scope.enabled) return; - - handleMouseUp(event); - document.removeEventListener('mousemove', onMouseMove, false); - document.removeEventListener('mouseup', onMouseUp, false); - scope.dispatchEvent(endEvent); - state = STATE.NONE; - } - - - function onMouseWheel(event) { - if (!scope.enabled || !scope.enableZoom || - (state != STATE.NONE && state != STATE.ROTATE)) return; - - event.preventDefault(); - event.stopPropagation(); - scope.dispatchEvent(startEvent); - handleMouseWheel(event); - scope.dispatchEvent(endEvent); - } - - - function onKeyDown(event) { - if (!scope.enabled || !scope.enableKeys || !scope.enablePan) return; - - handleKeyDown(event); - } - - - function onTouchStart(event) { - if (!scope.enabled) return; - - event.preventDefault(); - - switch (event.touches.length) { - case 1: // one-fingered touch: rotate - if (!scope.enableRotate) return; - handleTouchStartRotate(event); - state = STATE.TOUCH_ROTATE; - break; - - case 2: // two-fingered touch: dolly-pan - if (!scope.enableZoom && !scope.enablePan) return; - handleTouchStartDollyPan(event); - state = STATE.TOUCH_DOLLY_PAN; - break; - - default: state = STATE.NONE; + scope.update(); } - if (state != STATE.NONE) scope.dispatchEvent(startEvent); - } + function handleMouseMoveDolly(event) { + dollyEnd.set(event.clientX, event.clientY); + dollyDelta.subVectors(dollyEnd, dollyStart); + if (dollyDelta.y > 0) { + dollyIn(getZoomScale()); + } else if (dollyDelta.y < 0) { + dollyOut(getZoomScale()); + } - function onTouchMove(event) { - if (!scope.enabled) return; - - event.preventDefault(); - event.stopPropagation(); - - switch (event.touches.length) { - case 1: // one-fingered touch: rotate - if (!scope.enableRotate) return; - if (state != STATE.TOUCH_ROTATE) return; // is this needed? - - handleTouchMoveRotate(event); - break; - - case 2: // two-fingered touch: dolly-pan - if (!scope.enableZoom && !scope.enablePan) return; - if (state != STATE.TOUCH_DOLLY_PAN) return; // is this needed? - - handleTouchMoveDollyPan(event); - break; - - default: state = STATE.NONE; + dollyStart.copy(dollyEnd); + scope.update(); } - } + function handleMouseMovePan(event) { + panEnd.set(event.clientX, event.clientY); + panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed); + pan(panDelta.x, panDelta.y); + panStart.copy(panEnd); + scope.update(); + } - function onTouchEnd(event) { - if (!scope.enabled) return; + function handleMouseWheel(event) { + if (event.deltaY < 0) { + dollyOut(getZoomScale()); + } else if (event.deltaY > 0) { + dollyIn(getZoomScale()); + } - handleTouchEnd(event); - scope.dispatchEvent(endEvent); - state = STATE.NONE; - } + scope.update(); + } + function handleKeyDown(event) { + switch (event.keyCode) { + case scope.keys.UP: + pan(0, scope.keyPanSpeed); + scope.update(); + break; - function onContextMenu(event) { - if (!scope.enabled) return; - event.preventDefault(); - } + case scope.keys.BOTTOM: + pan(0, -scope.keyPanSpeed); + scope.update(); + break; + case scope.keys.LEFT: + pan(scope.keyPanSpeed, 0); + scope.update(); + break; - scope.domElement.addEventListener('contextmenu', onContextMenu, false); - scope.domElement.addEventListener('mousedown', onMouseDown, false); - scope.domElement.addEventListener('wheel', onMouseWheel, false); - scope.domElement.addEventListener('touchstart', onTouchStart, false); - scope.domElement.addEventListener('touchend', onTouchEnd, false); - scope.domElement.addEventListener('touchmove', onTouchMove, false); - window .addEventListener('keydown', onKeyDown, false); + case scope.keys.RIGHT: + pan(-scope.keyPanSpeed, 0); + scope.update(); + break; + } + } - this.update(); // force an update at start -} + function handleTouchStartRotate(event) { + rotateStart.set(event.touches[0].pageX, event.touches[0].pageY); + } + function handleTouchStartDollyPan(event) { + if (scope.enableZoom) { + const dx = event.touches[0].pageX - event.touches[1].pageX; + const dy = event.touches[0].pageY - event.touches[1].pageY; + const distance = Math.sqrt(dx * dx + dy * dy); + + dollyStart.set(0, distance); + } + + if (scope.enablePan) { + const x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX); + const y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY); + panStart.set(x, y); + } + } + + function handleTouchMoveRotate(event) { + rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY); + rotateDelta.subVectors(rotateEnd, rotateStart) + .multiplyScalar(scope.rotateSpeed); + + const element = scope.domElement === document ? + scope.domElement.body : scope.domElement; + + // yes, height + rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight); + rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight); + rotateStart.copy(rotateEnd); + scope.update(); + } + + function handleTouchMoveDollyPan(event) { + if (scope.enableZoom) { + const dx = event.touches[0].pageX - event.touches[1].pageX; + const dy = event.touches[0].pageY - event.touches[1].pageY; + const distance = Math.sqrt(dx * dx + dy * dy); + + dollyEnd.set(0, distance); + dollyDelta.set(0, Math.pow(dollyEnd.y / dollyStart.y, scope.zoomSpeed)); + dollyIn(dollyDelta.y); + dollyStart.copy(dollyEnd); + } + + if (scope.enablePan) { + const x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX); + const y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY); + + panEnd.set(x, y); + panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed); + pan(panDelta.x, panDelta.y); + panStart.copy(panEnd); + } + + scope.update(); + } + + // event handlers - listen for events and reset state + function onMouseDown(event) { + if (!scope.enabled) { + return; + } + + event.preventDefault(); + + switch (event.button) { + case scope.mouseButtons.ORBIT: + if (!scope.enableRotate) { + return; + } + handleMouseDownRotate(event); + state = STATE.ROTATE; + break; + + case scope.mouseButtons.ZOOM: + if (!scope.enableZoom) { + return; + } + handleMouseDownDolly(event); + state = STATE.DOLLY; + break; + + case scope.mouseButtons.PAN: + if (!scope.enablePan) { + return; + } + handleMouseDownPan(event); + state = STATE.PAN; + break; + } + + if (state != STATE.NONE) { + document.addEventListener("mousemove", onMouseMove, false); + document.addEventListener("mouseup", onMouseUp, false); + scope.dispatchEvent(startEvent); + } + } + + function onMouseMove(event) { + if (!scope.enabled) { + return; + } + + event.preventDefault(); + + switch (state) { + case STATE.ROTATE: + if (!scope.enableRotate) { + return; + } + handleMouseMoveRotate(event); + break; + + case STATE.DOLLY: + if (!scope.enableZoom) { + return; + } + handleMouseMoveDolly(event); + break; + + case STATE.PAN: + if (!scope.enablePan) { + return; + } + handleMouseMovePan(event); + break; + } + } + + function onMouseUp() { + if (!scope.enabled) { + return; + } + + document.removeEventListener("mousemove", onMouseMove, false); + document.removeEventListener("mouseup", onMouseUp, false); + scope.dispatchEvent(endEvent); + state = STATE.NONE; + } + + function onMouseWheel(event) { + if (!scope.enabled || !scope.enableZoom || + (state != STATE.NONE && state != STATE.ROTATE)) { + return; + } + + event.preventDefault(); + event.stopPropagation(); + scope.dispatchEvent(startEvent); + handleMouseWheel(event); + scope.dispatchEvent(endEvent); + } + + function onKeyDown(event) { + if (!scope.enabled || !scope.enableKeys || !scope.enablePan) { + return; + } + + handleKeyDown(event); + } + + function onTouchStart(event) { + if (!scope.enabled) { + return; + } + + event.preventDefault(); + + switch (event.touches.length) { + case 1: // one-fingered touch: rotate + if (!scope.enableRotate) { + return; + } + handleTouchStartRotate(event); + state = STATE.TOUCH_ROTATE; + break; + + case 2: // two-fingered touch: dolly-pan + if (!scope.enableZoom && !scope.enablePan) { + return; + } + handleTouchStartDollyPan(event); + state = STATE.TOUCH_DOLLY_PAN; + break; + + default: state = STATE.NONE; + } + + if (state != STATE.NONE) { + scope.dispatchEvent(startEvent); + } + } + + function onTouchMove(event) { + if (!scope.enabled) { + return; + } + + event.preventDefault(); + event.stopPropagation(); + + switch (event.touches.length) { + case 1: // one-fingered touch: rotate + if (!scope.enableRotate) { + return; + } + if (state != STATE.TOUCH_ROTATE) { + return; + } // is this needed? + + handleTouchMoveRotate(event); + break; + + case 2: // two-fingered touch: dolly-pan + if (!scope.enableZoom && !scope.enablePan) { + return; + } + if (state != STATE.TOUCH_DOLLY_PAN) { + return; + } // is this needed? + + handleTouchMoveDollyPan(event); + break; + + default: state = STATE.NONE; + } + } + + function onTouchEnd() { + if (!scope.enabled) { + return; + } + + scope.dispatchEvent(endEvent); + state = STATE.NONE; + } + + function onContextMenu(event) { + if (!scope.enabled) { + return; + } + event.preventDefault(); + } + + scope.domElement.addEventListener("contextmenu", onContextMenu, false); + scope.domElement.addEventListener("mousedown", onMouseDown, false); + scope.domElement.addEventListener("wheel", onMouseWheel, false); + scope.domElement.addEventListener("touchstart", onTouchStart, false); + scope.domElement.addEventListener("touchend", onTouchEnd, false); + scope.domElement.addEventListener("touchmove", onTouchMove, false); + window.addEventListener("keydown", onKeyDown, false); + + this.update(); // force an update at start +}; OrbitControls.prototype = Object.create(THREE.EventDispatcher.prototype); OrbitControls.prototype.constructor = OrbitControls; diff --git a/src/js/path-viewer.js b/src/js/path-viewer.js index f790af0..6240a5b 100644 --- a/src/js/path-viewer.js +++ b/src/js/path-viewer.js @@ -1,766 +1,773 @@ -/******************************************************************************\ +"use strict"; - Copyright 2018. Buildbotics LLC - All Rights Reserved. - - For information regarding this software email: - Joseph Coffland - joseph@buildbotics.com - - This software is free software: you clan redistribute it and/or - modify it under the terms of the GNU Lesser General Public License - as published by the Free Software Foundation, either version 2.1 of - the License, or (at your option) any later version. - - This software is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the C! library. If not, see - . - -\******************************************************************************/ - -'use strict' - -var orbit = require('./orbit'); -var cookie = require('./cookie')('bbctrl-'); -var font = require('./helvetiker_regular.typeface.json') +const orbit = require("./orbit"); +const cookie = require("./cookie")("bbctrl-"); +const font = require("./helvetiker_regular.typeface.json"); module.exports = { - template: '#path-viewer-template', - props: ['toolpath'], + template: "#path-viewer-template", + props: [ "toolpath" ], - data: function () { - return { - enabled: false, - loading: false, - dirty: true, - snapView: cookie.get('snap-view', 'isometric'), - small: cookie.get_bool('small-path-view', true), - surfaceMode: 'cut', - showPath: cookie.get_bool('show-path', true), - showTool: cookie.get_bool('show-tool', true), - showBBox: cookie.get_bool('show-bbox', true), - showAxes: cookie.get_bool('show-axes', true), - showIntensity: cookie.get_bool('show-intensity', false) - } - }, - - - computed: { - target: function () { - return $(this.$el).find('.path-viewer-content')[0] + data: function() { + return { + enabled: false, + loading: false, + dirty: true, + snapView: cookie.get("snap-view", "isometric"), + small: cookie.get_bool("small-path-view", true), + surfaceMode: "cut", + showPath: cookie.get_bool("show-path", true), + showTool: cookie.get_bool("show-tool", true), + showBBox: cookie.get_bool("show-bbox", true), + showAxes: cookie.get_bool("show-axes", true), + showIntensity: cookie.get_bool("show-intensity", false) + }; }, - webglAvailable: function() { - // Create canvas element. The canvas is not added to the - // document itself, so it is never displayed in the - // browser window. - const canvas = document.createElement("canvas"); - - // Get WebGLRenderingContext from canvas element. - const gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); - - // Report the result. - return gl && gl instanceof WebGLRenderingContext; - } - }, - - - watch: { - toolpath: function () {Vue.nextTick(this.update)}, - surfaceMode: function (mode) {this.update_surface_mode(mode)}, - - - small: function (enable) { - cookie.set_bool('small-path-view', enable); - Vue.nextTick(this.update_view) - }, - - - showPath: function (enable) { - cookie.set_bool('show-path', enable); - this.set_visible(this.pathView, enable) - }, - - - showTool: function (enable) { - cookie.set_bool('show-tool', enable); - this.set_visible(this.toolView, enable) - }, - - - showAxes: function (enable) { - cookie.set_bool('show-axes', enable); - this.set_visible(this.axesView, enable) - }, - - - showIntensity: function (enable) { - cookie.set_bool('show-intensity', enable); - Vue.nextTick(this.update) - }, - - - showBBox: function (enable) { - cookie.set_bool('show-bbox', enable); - this.set_visible(this.bboxView, enable); - this.set_visible(this.envelopeView, enable); - }, - - - x: function () {this.axis_changed()}, - y: function () {this.axis_changed()}, - z: function () {this.axis_changed()} - }, - - - ready: function () { - this.graphics(); - Vue.nextTick(this.update); - }, - - - methods: { - update: async function () { - if (!this.webglAvailable) { - return; - } - - if (!this.state.selected) { - this.dirty = true; - this.scene = new THREE.Scene(); - - } else if (!this.toolpath.filename && !this.loading) { - this.loading = true; - this.dirty = true; - this.draw_loading(); - } - - if (!this.enabled || !this.toolpath.filename) return; - - async function get(url) { - const response = await fetch(`${url}?${Math.random()}`); - const arrayBuffer = await response.arrayBuffer(); - - return new Float32Array(arrayBuffer); - } - - const [positions, speeds] = await Promise.all([ - get('/api/path/' + this.toolpath.filename + '/positions'), - get('/api/path/' + this.toolpath.filename + '/speeds') - ]); - - this.positions = positions - this.speeds = speeds; - this.loading = false; - - // Update scene - this.scene = new THREE.Scene(); - this.draw(this.scene); - this.snap(this.snapView); - - this.update_view(); - }, - - - update_surface_mode: function (mode) { - if (!this.enabled) return; - - if (typeof this.surfaceMaterial != 'undefined') { - this.surfaceMaterial.wireframe = mode == 'wire'; - this.surfaceMaterial.needsUpdate = true; - } - - this.set_visible(this.surfaceMesh, mode == 'cut' || mode == 'wire'); - this.set_visible(this.workpieceMesh, mode == 'solid'); - }, - - - load_surface: function (surface) { - if (typeof surface == 'undefined') { - this.vertices = undefined; - this.normals = undefined; - return; - } - - this.vertices = surface.vertices; - - // Expand normals - this.normals = []; - for (var i = 0; i < surface.normals.length / 3; i++) - for (var j = 0; j < 3; j++) - for (var k = 0; k < 3; k++) - this.normals.push(surface.normals[i * 3 + k]); - }, - - - set_visible: function (target, visible) { - if (typeof target != 'undefined') target.visible = visible; - this.dirty = true; - }, - - - get_dims: function () { - var t = $(this.target); - var width = t.innerWidth(); - var height = t.innerHeight(); - return {width: width, height: height}; - }, - - - update_view: function () { - if (!this.enabled) return; - var dims = this.get_dims(); - - this.camera.aspect = dims.width / dims.height; - this.camera.updateProjectionMatrix(); - this.renderer.setSize(dims.width, dims.height); - - if (this.loading) { - this.controls.reset(); - this.camera.position.copy(new THREE.Vector3(0, 0, 600)); - this.camera.lookAt(new THREE.Vector3(0, 0, 0)); - } - - this.dirty = true; - }, - - - update_tool: function (tool) { - if (!this.enabled) return; - if (typeof tool == 'undefined') tool = this.toolView; - if (typeof tool == 'undefined') return; - tool.position.x = this.x.pos; - tool.position.y = this.y.pos; - tool.position.z = this.z.pos; - }, - - - update_envelope: function (envelope) { - if (!this.enabled || !this.axes.homed) return; - if (typeof envelope == 'undefined') envelope = this.envelopeView; - if (typeof envelope == 'undefined') return; - - var min = new THREE.Vector3(); - var max = new THREE.Vector3(); - - for (var axis of 'xyz') { - min[axis] = this[axis].min - this[axis].off; - max[axis] = this[axis].max - this[axis].off; - } - - var bounds = new THREE.Box3(min, max); - if (bounds.isEmpty()) { - envelope.geometry = this.create_empty_geom(); - } - else { - envelope.geometry = this.create_bbox_geom(bounds); - } - }, - - - axis_changed: function () { - this.update_tool(); - this.update_envelope(); - this.dirty = true; - }, - - - graphics: function () { - if (!this.webglAvailable) { - return; - } - - try { - // Renderer - this.renderer = new THREE.WebGLRenderer({antialias: true, alpha: true}); - this.renderer.setPixelRatio(window.devicePixelRatio); - this.renderer.setClearColor(0, 0); - this.target.appendChild(this.renderer.domElement); - - } catch (e) { - console.log('WebGL not supported: ', e); - return; - } - - this.enabled = true; - - // Camera - this.camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 10000); - - // Lighting - this.ambient = new THREE.AmbientLight(0xffffff, 0.5); - - var keyLight = new THREE.DirectionalLight - (new THREE.Color('hsl(30, 100%, 75%)'), 0.75); - keyLight.position.set(-100, 0, 100); - - var fillLight = new THREE.DirectionalLight - (new THREE.Color('hsl(240, 100%, 75%)'), 0.25); - fillLight.position.set(100, 0, 100); - - var backLight = new THREE.DirectionalLight(0xffffff, 0.5); - backLight.position.set(100, 0, -100).normalize(); - - this.lights = new THREE.Group(); - this.lights.add(keyLight); - this.lights.add(fillLight); - this.lights.add(backLight); - - // Surface material - this.surfaceMaterial = this.create_surface_material(); - - // Controls - this.controls = new orbit(this.camera, this.renderer.domElement); - this.controls.enableDamping = true; - this.controls.dampingFactor = 0.2; - this.controls.rotateSpeed = 0.25; - this.controls.enableZoom = true; - - // Move lights with scene - this.controls.addEventListener('change', function (scope) { - return function () { - keyLight.position.copy(scope.camera.position); - fillLight.position.copy(scope.camera.position); - backLight.position.copy(scope.camera.position); - keyLight.lookAt(scope.controls.target); - fillLight.lookAt(scope.controls.target); - backLight.lookAt(scope.controls.target); - scope.dirty = true; + computed: { + target: function() { + return this.$el.querySelector(".path-viewer-content"); + }, + + webglAvailable: function() { + // Create canvas element. The canvas is not added to the + // document itself, so it is never displayed in the + // browser window. + const canvas = document.createElement("canvas"); + + // Get WebGLRenderingContext from canvas element. + const gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); + + // Report the result. + return gl && gl instanceof WebGLRenderingContext; } - }(this)) - - // Events - window.addEventListener('resize', this.update_view, false); - - // Start it - this.render(); }, - - create_surface_material: function () { - return new THREE.MeshPhongMaterial({ - specular: 0x111111, - shininess: 10, - side: THREE.FrontSide, - color: 0x0c2d53 - }); - }, - - - draw_loading: function () { - this.scene = new THREE.Scene(); - - var geometry = new THREE.TextGeometry('Loading 3D View...', { - font: new THREE.Font(font), - size: 40, - height: 5, - curveSegments: 12, - bevelEnabled: true, - bevelThickness: 10, - bevelSize: 8, - bevelSegments: 5 - }); - geometry.computeBoundingBox(); - - var center = geometry.center(); - var mesh = new THREE.Mesh(geometry, this.surfaceMaterial); - - this.scene.add(mesh); - this.scene.add(this.ambient); - this.scene.add(this.lights); - this.update_view(); - }, - - - draw_workpiece: function (scene, material) { - if (typeof this.workpiece == 'undefined') return; - - var min = this.workpiece.min; - var max = this.workpiece.max; - - min = new THREE.Vector3(min[0], min[1], min[2]); - max = new THREE.Vector3(max[0], max[1], max[2]); - var dims = max.clone().sub(min); - - var geometry = new THREE.BoxGeometry(dims.x, dims.y, dims.z) - var mesh = new THREE.Mesh(geometry, material); - - var offset = dims.clone(); - offset.divideScalar(2); - offset.add(min); - - mesh.position.add(offset); - - geometry.computeBoundingBox(); - - scene.add(mesh); - - return mesh; - }, - - - draw_surface: function (scene, material) { - if (typeof this.vertices == 'undefined') return; - - var geometry = new THREE.BufferGeometry(); - - geometry.addAttribute - ('position', new THREE.Float32BufferAttribute(this.vertices, 3)); - geometry.addAttribute - ('normal', new THREE.Float32BufferAttribute(this.normals, 3)); - - geometry.computeBoundingSphere(); - geometry.computeBoundingBox(); - - return new THREE.Mesh(geometry, material); - }, - - - draw_tool: function (scene, bbox) { - // Tool size is relative to bounds - var size = bbox.getSize(new THREE.Vector3()); - var length = (size.x + size.y + size.z) / 24; - - if (length < 1) length = 1; - - var material = new THREE.MeshPhongMaterial({ - transparent: true, - opacity: 0.75, - specular: 0x161616, - shininess: 10, - color: 0xffa500 // Orange - }); - - var geometry = new THREE.CylinderGeometry(length / 2, 0, length, 128); - geometry.translate(0, length / 2, 0); - geometry.rotateX(0.5 * Math.PI); - - var mesh = new THREE.Mesh(geometry, material); - this.update_tool(mesh); - mesh.visible = this.showTool; - scene.add(mesh); - return mesh; - }, - - - draw_axis: function (axis, up, length, radius) { - var color; - - if (axis == 0) color = 0xff0000; // Red - else if (axis == 1) color = 0x00ff00; // Green - else if (axis == 2) color = 0x0000ff; // Blue - - var group = new THREE.Group(); - var material = new THREE.MeshPhongMaterial({ - specular: 0x161616, shininess: 10, color: color - }); - var geometry = new THREE.CylinderGeometry(radius, radius, length, 128); - geometry.translate(0, -length / 2, 0); - group.add(new THREE.Mesh(geometry, material)); - - geometry = new THREE.CylinderGeometry(1.5 * radius, 0, 2 * radius, 128); - geometry.translate(0, -length - radius, 0); - group.add(new THREE.Mesh(geometry, material)); - - if (axis == 0) group.rotateZ((up ? 0.5 : 1.5) * Math.PI); - else if (axis == 1) group.rotateX((up ? 0 : 1 ) * Math.PI); - else if (axis == 2) group.rotateX((up ? 1.5 : 0.5) * Math.PI); - - return group; - }, - - - draw_axes: function (scene, bbox) { - var size = bbox.getSize(new THREE.Vector3()); - var length = (size.x + size.y + size.z) / 3; - length /= 10; - - if (length < 1) length = 1; - - var radius = length / 20; - - var group = new THREE.Group(); - - for (var axis = 0; axis < 3; axis++) - for (var up = 0; up < 2; up++) - group.add(this.draw_axis(axis, up, length, radius)); - - group.visible = this.showAxes; - scene.add(group); - - return group; - }, - - - get_color: function (speed) { - if (isNaN(speed)) return [255, 0, 0]; // Rapid - - var intensity = speed / this.toolpath.maxSpeed; - if (typeof speed == 'undefined' || !this.showIntensity) intensity = 1; - return [0, 255 * intensity, 127 * (1 - intensity)]; - }, - - - draw_path: function (scene) { - var geometry = new THREE.BufferGeometry(); - var material = - new THREE.LineBasicMaterial({ - vertexColors: THREE.VertexColors, - linewidth: 1.5 - }); - - var positions = new THREE.Float32BufferAttribute(this.positions, 3); - geometry.addAttribute('position', positions); - - var colors = []; - for (var i = 0; i < this.speeds.length; i++) { - var color = this.get_color(this.speeds[i]); - Array.prototype.push.apply(colors, color); - } - - colors = new THREE.Uint8BufferAttribute(colors, 3, true); - geometry.addAttribute('color', colors); - - geometry.computeBoundingSphere(); - geometry.computeBoundingBox(); - - var line = new THREE.Line(geometry, material); - - line.visible = this.showPath; - scene.add(line); - - return line; - }, - - - create_empty_geom: function () { - var geometry = new THREE.BufferGeometry(); - geometry.addAttribute('position', - new THREE.Float32BufferAttribute([], 3)); - return geometry; - }, - - - create_bbox_geom: function (bbox) { - var vertices = []; - - if (!bbox.isEmpty()) { - // Top - vertices.push(bbox.min.x, bbox.min.y, bbox.min.z); - vertices.push(bbox.max.x, bbox.min.y, bbox.min.z); - vertices.push(bbox.max.x, bbox.min.y, bbox.min.z); - vertices.push(bbox.max.x, bbox.min.y, bbox.max.z); - vertices.push(bbox.max.x, bbox.min.y, bbox.max.z); - vertices.push(bbox.min.x, bbox.min.y, bbox.max.z); - vertices.push(bbox.min.x, bbox.min.y, bbox.max.z); - vertices.push(bbox.min.x, bbox.min.y, bbox.min.z); - - // Bottom - vertices.push(bbox.min.x, bbox.max.y, bbox.min.z); - vertices.push(bbox.max.x, bbox.max.y, bbox.min.z); - vertices.push(bbox.max.x, bbox.max.y, bbox.min.z); - vertices.push(bbox.max.x, bbox.max.y, bbox.max.z); - vertices.push(bbox.max.x, bbox.max.y, bbox.max.z); - vertices.push(bbox.min.x, bbox.max.y, bbox.max.z); - vertices.push(bbox.min.x, bbox.max.y, bbox.max.z); - vertices.push(bbox.min.x, bbox.max.y, bbox.min.z); - - // Sides - vertices.push(bbox.min.x, bbox.min.y, bbox.min.z); - vertices.push(bbox.min.x, bbox.max.y, bbox.min.z); - vertices.push(bbox.max.x, bbox.min.y, bbox.min.z); - vertices.push(bbox.max.x, bbox.max.y, bbox.min.z); - vertices.push(bbox.max.x, bbox.min.y, bbox.max.z); - vertices.push(bbox.max.x, bbox.max.y, bbox.max.z); - vertices.push(bbox.min.x, bbox.min.y, bbox.max.z); - vertices.push(bbox.min.x, bbox.max.y, bbox.max.z); - } - - var geometry = new THREE.BufferGeometry(); - - geometry.addAttribute('position', - new THREE.Float32BufferAttribute(vertices, 3)); - - return geometry; - }, - - - draw_bbox: function (scene, bbox) { - var geometry = this.create_bbox_geom(bbox); - var material = new THREE.LineBasicMaterial({color: 0xffffff}); - var line = new THREE.LineSegments(geometry, material); - - line.visible = this.showBBox; - - scene.add(line); - - return line; - }, - - - draw_envelope: function (scene) { - var geometry = this.create_empty_geom(); - var material = new THREE.LineBasicMaterial({color: 0x00f7ff}); - var line = new THREE.LineSegments(geometry, material); - - line.visible = this.showBBox; - - scene.add(line); - this.update_envelope(line); - - return line; - }, - - - draw: function (scene) { - // Lights - scene.add(this.ambient); - scene.add(this.lights); - - // Model - this.pathView = this.draw_path(scene); - this.surfaceMesh = this.draw_surface(scene, this.surfaceMaterial); - this.workpieceMesh = this.draw_workpiece(scene, this.surfaceMaterial); - this.update_surface_mode(this.surfaceMode); - - // Compute bounding box - var bbox = this.get_model_bounds(); - - // Tool, axes & bounds - this.toolView = this.draw_tool(scene, bbox); - this.axesView = this.draw_axes(scene, bbox); - this.bboxView = this.draw_bbox(scene, bbox); - this.envelopeView = this.draw_envelope(scene); - }, - - - render: function () { - window.requestAnimationFrame(this.render); - if (typeof this.scene == 'undefined') return; - - if (this.controls.update() || this.dirty) { - this.dirty = false; - this.renderer.render(this.scene, this.camera); - } - }, - - - get_model_bounds: function () { - var bbox = new THREE.Box3(new THREE.Vector3(0, 0, 0), - new THREE.Vector3(0.00001, 0.00001, 0.00001)); - - function add(o) { - if (typeof o != 'undefined') { - var oBBox = new THREE.Box3(); - oBBox.setFromObject(o); - bbox.union(oBBox); + watch: { + toolpath: function() { + Vue.nextTick(this.update); + }, + + surfaceMode: function(mode) { + this.update_surface_mode(mode); + }, + + small: function(enable) { + cookie.set_bool("small-path-view", enable); + Vue.nextTick(this.update_view); + }, + + showPath: function(enable) { + cookie.set_bool("show-path", enable); + this.set_visible(this.pathView, enable); + }, + + showTool: function(enable) { + cookie.set_bool("show-tool", enable); + this.set_visible(this.toolView, enable); + }, + + showAxes: function(enable) { + cookie.set_bool("show-axes", enable); + this.set_visible(this.axesView, enable); + }, + + showIntensity: function(enable) { + cookie.set_bool("show-intensity", enable); + Vue.nextTick(this.update); + }, + + showBBox: function(enable) { + cookie.set_bool("show-bbox", enable); + this.set_visible(this.bboxView, enable); + this.set_visible(this.envelopeView, enable); + }, + + x: function() { + this.axis_changed(); + }, + + y: function() { + this.axis_changed(); + }, + + z: function() { + this.axis_changed(); } - } - - add(this.pathView); - add(this.surfaceMesh); - add(this.workpieceMesh); - - return bbox; }, + ready: function() { + this.graphics(); + Vue.nextTick(this.update); + }, - snap: function (view) { - if (this.loading) return; - if (view != this.snapView) { - this.snapView = view; - cookie.set('snap-view', view); - } + methods: { + update: async function() { + if (!this.webglAvailable) { + return; + } - var bbox = this.get_model_bounds(); - this.controls.reset(); - bbox.getCenter(this.controls.target); - this.update_view(); + if (!this.state.selected) { + this.dirty = true; + this.scene = new THREE.Scene(); - // Compute new camera position - var center = bbox.getCenter(new THREE.Vector3()); - var offset = new THREE.Vector3(); + } else if (!this.toolpath.filename && !this.loading) { + this.loading = true; + this.dirty = true; + this.draw_loading(); + } - if (view == 'isometric') {offset.y -= 1; offset.z += 1;} - if (view == 'front') offset.y -= 1; - if (view == 'back') offset.y += 1; - if (view == 'left') offset.x -= 1; - if (view == 'right') offset.x += 1; - if (view == 'top') offset.z += 1; - if (view == 'bottom') offset.z -= 1; - offset.normalize(); + if (!this.enabled || !this.toolpath.filename) { + return; + } - // Initial camera position - var position = new THREE.Vector3().copy(center).add(offset); - this.camera.position.copy(position); - this.camera.lookAt(center); // Get correct camera orientation + async function get(url) { + const response = await fetch(`${url}`, { cache: "no-cache" }); + const arrayBuffer = await response.arrayBuffer(); - var theta = this.camera.fov / 180 * Math.PI; // View angle - var cameraLine = new THREE.Line3(center, position); - var cameraUp = new THREE.Vector3().copy(this.camera.up) - .applyQuaternion(this.camera.quaternion); - var cameraLeft = - new THREE.Vector3().copy(offset).cross(cameraUp).normalize(); + return new Float32Array(arrayBuffer); + } - var corners = [ - new THREE.Vector3(bbox.min.x, bbox.min.y, bbox.min.z), - new THREE.Vector3(bbox.min.x, bbox.min.y, bbox.max.z), - new THREE.Vector3(bbox.min.x, bbox.max.y, bbox.min.z), - new THREE.Vector3(bbox.min.x, bbox.max.y, bbox.max.z), - new THREE.Vector3(bbox.max.x, bbox.min.y, bbox.min.z), - new THREE.Vector3(bbox.max.x, bbox.min.y, bbox.max.z), - new THREE.Vector3(bbox.max.x, bbox.max.y, bbox.min.z), - new THREE.Vector3(bbox.max.x, bbox.max.y, bbox.max.z), - ] + const [ positions, speeds ] = await Promise.all([ + get(`/api/path/${this.toolpath.filename}/positions`), + get(`/api/path/${this.toolpath.filename}/speeds`) + ]); - var dist = this.camera.near; // Min camera dist + this.positions = positions; + this.speeds = speeds; + this.loading = false; - for (var i = 0; i < corners.length; i++) { - // Project on to camera line - var p1 = cameraLine - .closestPointToPoint(corners[i], false, new THREE.Vector3()); + // Update scene + this.scene = new THREE.Scene(); + this.draw(this.scene); + this.snap(this.snapView); - // Compute distance from projection to center - var d = p1.distanceTo(center); - if (cameraLine.closestPointToPointParameter(p1, false) < 0) d = -d; + this.update_view(); + }, - // Compute up line - var up = - new THREE.Line3(p1, new THREE.Vector3().copy(p1).add(cameraUp)); + update_surface_mode: function(mode) { + if (!this.enabled) { + return; + } - // Project on to up line - var p2 = up.closestPointToPoint(corners[i], false, new THREE.Vector3()); + if (typeof this.surfaceMaterial != "undefined") { + this.surfaceMaterial.wireframe = mode == "wire"; + this.surfaceMaterial.needsUpdate = true; + } - // Compute length - var l = p1.distanceTo(p2); + this.set_visible(this.surfaceMesh, mode == "cut" || mode == "wire"); + this.set_visible(this.workpieceMesh, mode == "solid"); + }, - // Update min camera distance - dist = Math.max(dist, d + l / Math.tan(theta / 2)); + load_surface: function(surface) { + if (typeof surface == "undefined") { + this.vertices = undefined; + this.normals = undefined; + return; + } - // Compute left line - var left = - new THREE.Line3(p1, new THREE.Vector3().copy(p1).add(cameraLeft)); + this.vertices = surface.vertices; - // Project on to left line - var p3 = - left.closestPointToPoint(corners[i], false, new THREE.Vector3()); + // Expand normals + this.normals = []; + for (let i = 0; i < surface.normals.length / 3; i++) { + for (let j = 0; j < 3; j++) { + for (let k = 0; k < 3; k++) { + this.normals.push(surface.normals[i * 3 + k]); + } + } + } + }, - // Compute length - l = p1.distanceTo(p3); + set_visible: function(target, visible) { + if (typeof target != "undefined") { + target.visible = visible; + } + this.dirty = true; + }, - // Update min camera distance - dist = Math.max(dist, d + l / Math.tan(theta / 2) / this.camera.aspect); - } + get_dims: function() { + const computedStyle = window.getComputedStyle(this.target); - this.camera.position.copy(offset.multiplyScalar(dist * 1.2).add(center)); - } - }, + return { + width: parseInt(computedStyle.width), + height: parseInt(computedStyle.height) + }; + }, + update_view: function() { + if (!this.enabled) { + return; + } - mixins: [require('./axis-vars')] -} + const dims = this.get_dims(); + + this.camera.aspect = dims.width / dims.height; + this.camera.updateProjectionMatrix(); + this.renderer.setSize(dims.width, dims.height); + + if (this.loading) { + this.controls.reset(); + this.camera.position.copy(new THREE.Vector3(0, 0, 600)); + this.camera.lookAt(new THREE.Vector3(0, 0, 0)); + } + + this.dirty = true; + }, + + update_tool: function(tool) { + if (!this.enabled) { + return; + } + + if (typeof tool == "undefined") { + tool = this.toolView; + } + + if (typeof tool == "undefined") { + return; + } + + tool.position.x = this.x.pos; + tool.position.y = this.y.pos; + tool.position.z = this.z.pos; + }, + + update_envelope: function(envelope) { + if (!this.enabled || !this.axes.homed) { + return; + } + + if (typeof envelope == "undefined") { + envelope = this.envelopeView; + } + + if (typeof envelope == "undefined") { + return; + } + + const min = new THREE.Vector3(); + const max = new THREE.Vector3(); + + for (const axis of "xyz") { + min[axis] = this[axis].min - this[axis].off; + max[axis] = this[axis].max - this[axis].off; + } + + const bounds = new THREE.Box3(min, max); + if (bounds.isEmpty()) { + envelope.geometry = this.create_empty_geom(); + } else { + envelope.geometry = this.create_bbox_geom(bounds); + } + }, + + axis_changed: function() { + this.update_tool(); + this.update_envelope(); + this.dirty = true; + }, + + graphics: function() { + if (!this.webglAvailable) { + return; + } + + try { + // Renderer + this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); + this.renderer.setPixelRatio(window.devicePixelRatio); + this.renderer.setClearColor(0, 0); + this.target.appendChild(this.renderer.domElement); + + } catch (e) { + console.log("WebGL not supported: ", e); + return; + } + + this.enabled = true; + + // Camera + this.camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 10000); + + // Lighting + this.ambient = new THREE.AmbientLight(0xffffff, 0.5); + + const keyLight = new THREE.DirectionalLight(new THREE.Color("hsl(30, 100%, 75%)"), 0.75); + keyLight.position.set(-100, 0, 100); + + const fillLight = new THREE.DirectionalLight(new THREE.Color("hsl(240, 100%, 75%)"), 0.25); + fillLight.position.set(100, 0, 100); + + const backLight = new THREE.DirectionalLight(0xffffff, 0.5); + backLight.position.set(100, 0, -100).normalize(); + + this.lights = new THREE.Group(); + this.lights.add(keyLight); + this.lights.add(fillLight); + this.lights.add(backLight); + + // Surface material + this.surfaceMaterial = this.create_surface_material(); + + // Controls + this.controls = new orbit(this.camera, this.renderer.domElement); + this.controls.enableDamping = true; + this.controls.dampingFactor = 0.2; + this.controls.rotateSpeed = 0.25; + this.controls.enableZoom = true; + + // Move lights with scene + this.controls.addEventListener("change", function(scope) { + return function() { + keyLight.position.copy(scope.camera.position); + fillLight.position.copy(scope.camera.position); + backLight.position.copy(scope.camera.position); + keyLight.lookAt(scope.controls.target); + fillLight.lookAt(scope.controls.target); + backLight.lookAt(scope.controls.target); + scope.dirty = true; + }; + }(this)); + + // Events + window.addEventListener("resize", this.update_view, false); + + // Start it + this.render(); + }, + + create_surface_material: function() { + return new THREE.MeshPhongMaterial({ + specular: 0x111111, + shininess: 10, + side: THREE.FrontSide, + color: 0x0c2d53 + }); + }, + + draw_loading: function() { + this.scene = new THREE.Scene(); + + const geometry = new THREE.TextGeometry("Loading 3D View...", { + font: new THREE.Font(font), + size: 40, + height: 5, + curveSegments: 12, + bevelEnabled: true, + bevelThickness: 10, + bevelSize: 8, + bevelSegments: 5 + }); + geometry.computeBoundingBox(); + + const mesh = new THREE.Mesh(geometry, this.surfaceMaterial); + + this.scene.add(mesh); + this.scene.add(this.ambient); + this.scene.add(this.lights); + this.update_view(); + }, + + draw_workpiece: function(scene, material) { + if (typeof this.workpiece == "undefined") { + return; + } + + let min = this.workpiece.min; + let max = this.workpiece.max; + + min = new THREE.Vector3(min[0], min[1], min[2]); + max = new THREE.Vector3(max[0], max[1], max[2]); + const dims = max.clone().sub(min); + + const geometry = new THREE.BoxGeometry(dims.x, dims.y, dims.z); + const mesh = new THREE.Mesh(geometry, material); + + const offset = dims.clone(); + offset.divideScalar(2); + offset.add(min); + + mesh.position.add(offset); + + geometry.computeBoundingBox(); + + scene.add(mesh); + + return mesh; + }, + + draw_surface: function(scene, material) { + if (typeof this.vertices == "undefined") { + return; + } + + const geometry = new THREE.BufferGeometry(); + + geometry.addAttribute("position", new THREE.Float32BufferAttribute(this.vertices, 3)); + geometry.addAttribute("normal", new THREE.Float32BufferAttribute(this.normals, 3)); + + geometry.computeBoundingSphere(); + geometry.computeBoundingBox(); + + return new THREE.Mesh(geometry, material); + }, + + draw_tool: function(scene, bbox) { + // Tool size is relative to bounds + const size = bbox.getSize(new THREE.Vector3()); + let length = (size.x + size.y + size.z) / 24; + + if (length < 1) { + length = 1; + } + + const material = new THREE.MeshPhongMaterial({ + transparent: true, + opacity: 0.75, + specular: 0x161616, + shininess: 10, + color: 0xffa500 // Orange + }); + + const geometry = new THREE.CylinderGeometry(length / 2, 0, length, 128); + geometry.translate(0, length / 2, 0); + geometry.rotateX(0.5 * Math.PI); + + const mesh = new THREE.Mesh(geometry, material); + this.update_tool(mesh); + mesh.visible = this.showTool; + scene.add(mesh); + return mesh; + }, + + draw_axis: function(axis, up, length, radius) { + let color; + + if (axis == 0) { + color = 0xff0000; + } else if (axis == 1) { + color = 0x00ff00; + } else if (axis == 2) { + color = 0x0000ff; + } + + const group = new THREE.Group(); + const material = new THREE.MeshPhongMaterial({ + specular: 0x161616, shininess: 10, color: color + }); + let geometry = new THREE.CylinderGeometry(radius, radius, length, 128); + geometry.translate(0, -length / 2, 0); + group.add(new THREE.Mesh(geometry, material)); + + geometry = new THREE.CylinderGeometry(1.5 * radius, 0, 2 * radius, 128); + geometry.translate(0, -length - radius, 0); + group.add(new THREE.Mesh(geometry, material)); + + if (axis == 0) { + group.rotateZ((up ? 0.5 : 1.5) * Math.PI); + } else if (axis == 1) { + group.rotateX((up ? 0 : 1 ) * Math.PI); + } else if (axis == 2) { + group.rotateX((up ? 1.5 : 0.5) * Math.PI); + } + + return group; + }, + + draw_axes: function(scene, bbox) { + const size = bbox.getSize(new THREE.Vector3()); + let length = (size.x + size.y + size.z) / 3; + length /= 10; + + if (length < 1) { + length = 1; + } + + const radius = length / 20; + + const group = new THREE.Group(); + + for (let axis = 0; axis < 3; axis++) { + for (let up = 0; up < 2; up++) { + group.add(this.draw_axis(axis, up, length, radius)); + } + } + + group.visible = this.showAxes; + scene.add(group); + + return group; + }, + + get_color: function(speed) { + if (isNaN(speed)) { + return [ 255, 0, 0 ]; + } // Rapid + + let intensity = speed / this.toolpath.maxSpeed; + if (typeof speed == "undefined" || !this.showIntensity) { + intensity = 1; + } + + return [ 0, 255 * intensity, 127 * (1 - intensity) ]; + }, + + draw_path: function(scene) { + const geometry = new THREE.BufferGeometry(); + const material = new THREE.LineBasicMaterial({ + vertexColors: THREE.VertexColors, + linewidth: 1.5 + }); + + const positions = new THREE.Float32BufferAttribute(this.positions, 3); + geometry.addAttribute("position", positions); + + let colors = []; + for (let i = 0; i < this.speeds.length; i++) { + const color = this.get_color(this.speeds[i]); + Array.prototype.push.apply(colors, color); + } + + colors = new THREE.Uint8BufferAttribute(colors, 3, true); + geometry.addAttribute("color", colors); + + geometry.computeBoundingSphere(); + geometry.computeBoundingBox(); + + const line = new THREE.Line(geometry, material); + + line.visible = this.showPath; + scene.add(line); + + return line; + }, + + create_empty_geom: function() { + const geometry = new THREE.BufferGeometry(); + geometry.addAttribute("position", + new THREE.Float32BufferAttribute([], 3)); + return geometry; + }, + + create_bbox_geom: function(bbox) { + const vertices = []; + + if (!bbox.isEmpty()) { + // Top + vertices.push(bbox.min.x, bbox.min.y, bbox.min.z); + vertices.push(bbox.max.x, bbox.min.y, bbox.min.z); + vertices.push(bbox.max.x, bbox.min.y, bbox.min.z); + vertices.push(bbox.max.x, bbox.min.y, bbox.max.z); + vertices.push(bbox.max.x, bbox.min.y, bbox.max.z); + vertices.push(bbox.min.x, bbox.min.y, bbox.max.z); + vertices.push(bbox.min.x, bbox.min.y, bbox.max.z); + vertices.push(bbox.min.x, bbox.min.y, bbox.min.z); + + // Bottom + vertices.push(bbox.min.x, bbox.max.y, bbox.min.z); + vertices.push(bbox.max.x, bbox.max.y, bbox.min.z); + vertices.push(bbox.max.x, bbox.max.y, bbox.min.z); + vertices.push(bbox.max.x, bbox.max.y, bbox.max.z); + vertices.push(bbox.max.x, bbox.max.y, bbox.max.z); + vertices.push(bbox.min.x, bbox.max.y, bbox.max.z); + vertices.push(bbox.min.x, bbox.max.y, bbox.max.z); + vertices.push(bbox.min.x, bbox.max.y, bbox.min.z); + + // Sides + vertices.push(bbox.min.x, bbox.min.y, bbox.min.z); + vertices.push(bbox.min.x, bbox.max.y, bbox.min.z); + vertices.push(bbox.max.x, bbox.min.y, bbox.min.z); + vertices.push(bbox.max.x, bbox.max.y, bbox.min.z); + vertices.push(bbox.max.x, bbox.min.y, bbox.max.z); + vertices.push(bbox.max.x, bbox.max.y, bbox.max.z); + vertices.push(bbox.min.x, bbox.min.y, bbox.max.z); + vertices.push(bbox.min.x, bbox.max.y, bbox.max.z); + } + + const geometry = new THREE.BufferGeometry(); + + geometry.addAttribute("position", + new THREE.Float32BufferAttribute(vertices, 3)); + + return geometry; + }, + + draw_bbox: function(scene, bbox) { + const geometry = this.create_bbox_geom(bbox); + const material = new THREE.LineBasicMaterial({ color: 0xffffff }); + const line = new THREE.LineSegments(geometry, material); + + line.visible = this.showBBox; + + scene.add(line); + + return line; + }, + + draw_envelope: function(scene) { + const geometry = this.create_empty_geom(); + const material = new THREE.LineBasicMaterial({ color: 0x00f7ff }); + const line = new THREE.LineSegments(geometry, material); + + line.visible = this.showBBox; + + scene.add(line); + this.update_envelope(line); + + return line; + }, + + draw: function(scene) { + // Lights + scene.add(this.ambient); + scene.add(this.lights); + + // Model + this.pathView = this.draw_path(scene); + this.surfaceMesh = this.draw_surface(scene, this.surfaceMaterial); + this.workpieceMesh = this.draw_workpiece(scene, this.surfaceMaterial); + this.update_surface_mode(this.surfaceMode); + + // Compute bounding box + const bbox = this.get_model_bounds(); + + // Tool, axes & bounds + this.toolView = this.draw_tool(scene, bbox); + this.axesView = this.draw_axes(scene, bbox); + this.bboxView = this.draw_bbox(scene, bbox); + this.envelopeView = this.draw_envelope(scene); + }, + + render: function() { + window.requestAnimationFrame(this.render); + + if (typeof this.scene == "undefined") { + return; + } + + if (this.controls.update() || this.dirty) { + this.dirty = false; + this.renderer.render(this.scene, this.camera); + } + }, + + get_model_bounds: function() { + const bbox = new THREE.Box3(new THREE.Vector3(0, 0, 0), + new THREE.Vector3(0.00001, 0.00001, 0.00001)); + + function add(o) { + if (typeof o != "undefined") { + const oBBox = new THREE.Box3(); + oBBox.setFromObject(o); + bbox.union(oBBox); + } + } + + add(this.pathView); + add(this.surfaceMesh); + add(this.workpieceMesh); + + return bbox; + }, + + snap: function(view) { + if (this.loading) { + return; + } + + if (view != this.snapView) { + this.snapView = view; + cookie.set("snap-view", view); + } + + const bbox = this.get_model_bounds(); + this.controls.reset(); + bbox.getCenter(this.controls.target); + this.update_view(); + + // Compute new camera position + const center = bbox.getCenter(new THREE.Vector3()); + const offset = new THREE.Vector3(); + + switch (view) { + case "isometric": offset.y -= 1; offset.z += 1; break; + case "front": offset.y -= 1; break; + case "back": offset.y += 1; break; + case "left": offset.x -= 1; break; + case "right": offset.x += 1; break; + case "top": offset.z += 1; break; + case "bottom": offset.z -= 1; break; + } + + offset.normalize(); + + // Initial camera position + const position = new THREE.Vector3().copy(center).add(offset); + this.camera.position.copy(position); + this.camera.lookAt(center); // Get correct camera orientation + + const theta = this.camera.fov / 180 * Math.PI; // View angle + const cameraLine = new THREE.Line3(center, position); + const cameraUp = new THREE.Vector3() + .copy(this.camera.up) + .applyQuaternion(this.camera.quaternion); + const cameraLeft = new THREE.Vector3() + .copy(offset) + .cross(cameraUp) + .normalize(); + + const corners = [ + new THREE.Vector3(bbox.min.x, bbox.min.y, bbox.min.z), + new THREE.Vector3(bbox.min.x, bbox.min.y, bbox.max.z), + new THREE.Vector3(bbox.min.x, bbox.max.y, bbox.min.z), + new THREE.Vector3(bbox.min.x, bbox.max.y, bbox.max.z), + new THREE.Vector3(bbox.max.x, bbox.min.y, bbox.min.z), + new THREE.Vector3(bbox.max.x, bbox.min.y, bbox.max.z), + new THREE.Vector3(bbox.max.x, bbox.max.y, bbox.min.z), + new THREE.Vector3(bbox.max.x, bbox.max.y, bbox.max.z), + ]; + + let dist = this.camera.near; // Min camera dist + + for (let i = 0; i < corners.length; i++) { + // Project on to camera line + const p1 = cameraLine.closestPointToPoint(corners[i], false, new THREE.Vector3()); + + // Compute distance from projection to center + let d = p1.distanceTo(center); + if (cameraLine.closestPointToPointParameter(p1, false) < 0) { + d = -d; + } + + // Compute up line + const up = new THREE.Line3(p1, new THREE.Vector3().copy(p1).add(cameraUp)); + + // Project on to up line + const p2 = up.closestPointToPoint(corners[i], false, new THREE.Vector3()); + + // Compute length + let l = p1.distanceTo(p2); + + // Update min camera distance + dist = Math.max(dist, d + l / Math.tan(theta / 2)); + + // Compute left line + const left = new THREE.Line3(p1, new THREE.Vector3().copy(p1).add(cameraLeft)); + + // Project on to left line + const p3 = left.closestPointToPoint(corners[i], false, new THREE.Vector3()); + + // Compute length + l = p1.distanceTo(p3); + + // Update min camera distance + dist = Math.max(dist, d + l / Math.tan(theta / 2) / this.camera.aspect); + } + + this.camera.position.copy(offset.multiplyScalar(dist * 1.2).add(center)); + } + }, + + mixins: [ require("./axis-vars") ] +}; diff --git a/src/js/settings-view.js b/src/js/settings-view.js index 599aea8..514b42b 100644 --- a/src/js/settings-view.js +++ b/src/js/settings-view.js @@ -1,42 +1,14 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict' - - module.exports = { - template: '#settings-view-template', - props: ['config', 'template'], + template: "#settings-view-template", + attached: function() { + this.svelteComponent = SvelteComponents.createComponent( + "SettingsView", + document.getElementById("settings") + ); + }, - events: { - 'input-changed': function() { - this.$dispatch('config-changed'); - return false; + detached: function() { + this.svelteComponent.$destroy(); } - } -} +}; diff --git a/src/js/sock.js b/src/js/sock.js index 5c274cd..1a248dc 100644 --- a/src/js/sock.js +++ b/src/js/sock.js @@ -1,127 +1,106 @@ -/******************************************************************************\ +"use strict"; - This file is part of the Buildbotics firmware. +const Sock = function(url, retry, timeout) { + if (!(this instanceof Sock)) { + return new Sock(url, retry); + } - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. + if (typeof retry == "undefined") { + retry = 2000; + } + if (typeof timeout == "undefined") { + timeout = 16000; + } - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . + this.url = url; + this.retry = retry; + this.timeout = timeout; + this.divisions = 4; + this.count = 0; - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. + this.connect(); +}; - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . +Sock.prototype.onmessage = function() { + // Ignore +}; - For information regarding this software email: - "Joseph Coffland" +Sock.prototype.onopen = function() { + // Ignore +}; -\******************************************************************************/ +Sock.prototype.onclose = function() { + // Ignore +}; -'use strict' +Sock.prototype.connect = function() { + console.debug("connecting to", this.url); + this.close(); + this._sock = new SockJS(this.url); -var Sock = function (url, retry, timeout) { - if (!(this instanceof Sock)) return new Sock(url, retry); + this._sock.onmessage = function(e) { + console.debug("msg:", e.data); + this.heartbeat("msg"); + this.onmessage(e); + }.bind(this); - if (typeof retry == 'undefined') retry = 2000; - if (typeof timeout == 'undefined') timeout = 16000; + this._sock.onopen = function() { + console.debug("connected"); + this.heartbeat("open"); + this.onopen(); + }.bind(this); - this.url = url; - this.retry = retry; - this.timeout = timeout; - this.divisions = 4; - this.count = 0; + this._sock.onclose = function() { + console.debug("disconnected"); + this._cancel_timeout(); - this.connect(); -} + this.onclose(); + if (typeof this._sock != "undefined") { + setTimeout(this.connect.bind(this), this.retry); + } + }.bind(this); +}; +Sock.prototype._timedout = function() { + // Divide timeout so slow browser doesn't trigger timeouts when the + // connection is good. + if (this.divisions <= ++this.count) { + console.debug("connection timedout"); + this._timeout = undefined; + this._sock.close(); -Sock.prototype.onmessage = function () {} -Sock.prototype.onopen = function () {} -Sock.prototype.onclose = function () {} + } else { + this._set_timeout(); + } +}; - -Sock.prototype.connect = function () { - console.debug('connecting to', this.url); - this.close(); - - this._sock = new SockJS(this.url); - - this._sock.onmessage = function (e) { - console.debug('msg:', e.data); - this.heartbeat('msg'); - this.onmessage(e); - }.bind(this); - - - this._sock.onopen = function () { - console.debug('connected'); - this.heartbeat('open'); - this.onopen(); - }.bind(this); - - - this._sock.onclose = function () { - console.debug('disconnected'); - this._cancel_timeout(); - - this.onclose(); - if (typeof this._sock != 'undefined') - setTimeout(this.connect.bind(this), this.retry); - }.bind(this); -} - - -Sock.prototype._timedout = function () { - // Divide timeout so slow browser doesn't trigger timeouts when the - // connection is good. - if (this.divisions <= ++this.count) { - console.debug('connection timedout'); +Sock.prototype._cancel_timeout = function() { + clearTimeout(this._timeout); this._timeout = undefined; - this._sock.close(); + this.count = 0; +}; - } else this._set_timeout(); -} +Sock.prototype._set_timeout = function() { + this._timeout = setTimeout(this._timedout.bind(this), + this.timeout / this.divisions); +}; +Sock.prototype.heartbeat = function() { + this._cancel_timeout(); + this._set_timeout(); +}; -Sock.prototype._cancel_timeout = function () { - clearTimeout(this._timeout); - this._timeout = undefined; - this.count = 0; -} +Sock.prototype.close = function() { + if (typeof this._sock != "undefined") { + const sock = this._sock; + this._sock = undefined; + sock.close(); + } +}; +Sock.prototype.send = function(msg) { + this._sock.send(msg); +}; -Sock.prototype._set_timeout = function () { - this._timeout = setTimeout(this._timedout.bind(this), - this.timeout / this.divisions); -} - - -Sock.prototype.heartbeat = function (msg) { - //console.debug('heartbeat ' + new Date().toLocaleTimeString() + ' ' + msg); - this._cancel_timeout(); - this._set_timeout(); -} - - -Sock.prototype.close = function () { - if (typeof this._sock != 'undefined') { - var sock = this._sock; - this._sock = undefined; - sock.close(); - } -} - - -Sock.prototype.send = function (msg) {this._sock.send(msg)} - - -module.exports = Sock +module.exports = Sock; diff --git a/src/js/templated-input.js b/src/js/templated-input.js index 32d80eb..a168b6e 100644 --- a/src/js/templated-input.js +++ b/src/js/templated-input.js @@ -1,89 +1,69 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict' - +"use strict"; module.exports = { - replace: true, - template: '#templated-input-template', - props: ['name', 'model', 'template'], + replace: true, + template: "#templated-input-template", + props: [ "name", "model", "template" ], - - data: function () {return {view: ''}}, - - - computed: { - metric: function () {return this.$root.metric()}, - - - _view: function () { - if (this.template.scale) { - if (this.metric) return 1 * this.model.toFixed(3); - - return 1 * (this.model / this.template.scale).toFixed(4); - } - - return this.model; + data: function() { + return { view: "" }; }, + computed: { + metric: function() { + return this.$root.display_units === "METRIC"; + }, - units: function () { - return (this.metric || !this.template.iunit) ? - this.template.unit : this.template.iunit; + _view: function() { + if (this.template.scale) { + if (this.metric) { + return 1 * this.model.toFixed(3); + } + + return 1 * (this.model / this.template.scale).toFixed(4); + } + + return this.model; + }, + + units: function() { + return (this.metric || !this.template.iunit) + ? this.template.unit + : this.template.iunit; + }, + + title: function() { + let s = `Default :${this.template.default} ${(this.template.unit || "")}`; + + if (typeof this.template.help != "undefined") { + s = `${this.template.help}\n${s}`; + } + + return s; + } }, + watch: { + _view: function() { + this.view = this._view; + }, - title: function () { - var s = 'Default ' + this.template.default + ' ' + - (this.template.unit || ''); - if (typeof this.template.help != 'undefined') - s = this.template.help + '\n' + s; - return s; + view: function() { + if (this.template.scale && !this.metric) { + this.model = this.view * this.template.scale; + } else { + this.model = this.view; + } + } + }, + + ready: function() { + this.view = this._view; + }, + + methods: { + change: function() { + this.$dispatch("input-changed"); + } } - }, - - - watch: { - _view: function () {this.view = this._view}, - - - view: function () { - if (this.template.scale && !this.metric) - this.model = this.view * this.template.scale; - else this.model = this.view; - } - }, - - - ready: function () {this.view = this._view}, - - - methods: { - change: function () {this.$dispatch('input-changed')} - } -} +}; diff --git a/src/js/tool-view.js b/src/js/tool-view.js index e4bc390..ae29365 100644 --- a/src/js/tool-view.js +++ b/src/js/tool-view.js @@ -1,277 +1,252 @@ -/******************************************************************************\ +"use strict"; - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict'; - -const api = require('./api'); -const modbus = require('./modbus.js'); +const api = require("./api"); +const modbus = require("./modbus.js"); const merge = require("lodash.merge"); module.exports = { - template: '#tool-view-template', - props: ['config', 'template', 'state'], + template: "#tool-view-template", + props: [ "config", "template", "state" ], - data: function () { - return { - address: 0, - value: 0, - toolList: [ - { - id: "disabled", - name: "Disabled" - }, - { - id: "router", - type: "PWM Spindle", - name: "Router (Makita, etc)" - }, - { - id: "laser", - type: "PWM Spindle", - name: "Laser (J Tech, etc)" - }, - { - id: "pwm", - name: "PWM Spindle" - }, - { - id: "unsupported-separator", - name: "Unsupported Tools", - disabled: true, - unsupported: true - }, - { - id: "huanyang-vfd", - name: "Huanyang VFD", - unsupported: true - }, - { - id: "custom-modbus-vfd", - name: "Custom Modbus VFD", - unsupported: true - }, - { - id: "ac-tech-vfd", - name: "AC-Tech VFD", - unsupported: true - }, - { - id: "nowforever-vfd", - name: "Nowforever VFD", - unsupported: true - }, - { - id: "delta-vfd", - name: "Delta VFD015M21A (Beta)", - unsupported: true - }, - { - id: "yl600-vfd", - name: "YL600, YL620, YL620-A VFD (Beta)", - unsupported: true - }, - { - id: "fr-d700-vfd", - name: "FR-D700 (Beta)", - unsupported: true - }, - { - id: "sunfar-e300-vfd", - name: "Sunfar E300 (Beta)", - unsupported: true - }, - { - id: "omron-mx2-vfd", - name: "OMRON MX2", - unsupported: true + data: function() { + return { + address: 0, + value: 0, + toolList: [ + { + id: "disabled", + name: "Disabled" + }, + { + id: "router", + type: "PWM Spindle", + name: "Router (Makita, etc)" + }, + { + id: "laser", + type: "PWM Spindle", + name: "Laser (J Tech, etc)" + }, + { + id: "pwm", + name: "PWM Spindle" + }, + { + id: "unsupported-separator", + name: "Unsupported Tools", + disabled: true, + unsupported: true + }, + { + id: "huanyang-vfd", + name: "Huanyang VFD", + unsupported: true + }, + { + id: "custom-modbus-vfd", + name: "Custom Modbus VFD", + unsupported: true + }, + { + id: "ac-tech-vfd", + name: "AC-Tech VFD", + unsupported: true + }, + { + id: "nowforever-vfd", + name: "Nowforever VFD", + unsupported: true + }, + { + id: "delta-vfd", + name: "Delta VFD015M21A (Beta)", + unsupported: true + }, + { + id: "yl600-vfd", + name: "YL600, YL620, YL620-A VFD (Beta)", + unsupported: true + }, + { + id: "fr-d700-vfd", + name: "FR-D700 (Beta)", + unsupported: true + }, + { + id: "sunfar-e300-vfd", + name: "Sunfar E300 (Beta)", + unsupported: true + }, + { + id: "omron-mx2-vfd", + name: "OMRON MX2", + unsupported: true + } + ] + }; + }, + + components: { + "modbus-reg": require("./modbus-reg.js") + }, + + watch: { + "state.mr": function() { + this.value = this.state.mr; + } + }, + + events: { + "input-changed": function() { + this.$dispatch("config-changed"); + + return false; + }, + }, + + ready: function() { + this.value = this.state.mr; + }, + + computed: { + regs_tmpl: function() { + return this.template["modbus-spindle"].regs; + }, + + tool_type: function() { + return this.config.tool["tool-type"].toUpperCase(); + }, + + selected_tool: function() { + return this.config.tool["selected-tool"]; + }, + + is_pwm_spindle: function() { + return this.selected_tool == "pwm"; + }, + + is_modbus: function() { + switch (this.selected_tool) { + case "disabled": + case "laser": + case "router": + case "pwm": + return false; + + default: + return true; + } + }, + + modbus_status: function() { + return modbus.status_to_string(this.state.mx); + } + }, + + methods: { + change_selected_tool: function() { + const selectedToolSettings = this.config["selected-tool-settings"] || {}; + const settings = selectedToolSettings[this.selected_tool] || {}; + this.config.tool = merge({}, this.config.tool, settings["tool"]); + this.config["pwm-spindle"] = merge({}, this.config["pwm-spindle"], settings["pwm-spindle"]); + this.config["modbus-spindle"] = merge({}, this.config["modbus-spindle"], settings["modbus-spindle"]); + + const tool = this.toolList.find(tool => tool.id == this.config.tool["selected-tool"]); + this.config.tool["tool-type"] = tool.type || tool.name; + + this.$dispatch("config-changed"); + }, + + show_tool_settings: function(key) { + switch (true) { + case key === "tool-type": + case key === "selected-tool": + return false; + + case this.selected_tool === "disabled": + return false; + + case this.selected_tool === "laser": + case this.selected_tool === "router": + switch (key) { + case "tool-enable-mode": + return true; + + default: + return false; + } + + default: + return true; + } + }, + + get_reg_type: function(reg) { + return this.regs_tmpl.template["reg-type"].values[this.state[`${reg}vt`]]; + }, + + get_reg_addr: function(reg) { + return this.state[`${reg}va`]; + }, + + get_reg_value: function(reg) { + return this.state[`${reg}vv`]; + }, + + get_reg_fails: function(reg) { + const fails = this.state[`${reg}vr`]; + return fails == 255 ? "Max" : fails; + }, + + show_modbus_field: function(key) { + return key != "regs" && (key != "multi-write" || this.tool_type == "CUSTOM MODBUS VFD"); + }, + + read: function(e) { + e.preventDefault(); + api.put("modbus/read", { address: this.address }); + }, + + write: function(e) { + e.preventDefault(); + api.put("modbus/write", { address: this.address, value: this.value }); + }, + + customize: function(e) { + e.preventDefault(); + this.config.tool["tool-type"] = "Custom Modbus VFD"; + + const regs = this.config["modbus-spindle"].regs; + for (let i = 0; i < regs.length; i++) { + const reg = this.regs_tmpl.index[i]; + regs[i]["reg-type"] = this.get_reg_type(reg); + regs[i]["reg-addr"] = this.get_reg_addr(reg); + regs[i]["reg-value"] = this.get_reg_value(reg); + } + + this.$dispatch("config-changed"); + }, + + clear: function(e) { + e.preventDefault(); + this.config.tool["tool-type"] = "Custom Modbus VFD"; + + const regs = this.config["modbus-spindle"].regs; + for (let i = 0; i < regs.length; i++) { + regs[i]["reg-type"] = "disabled"; + regs[i]["reg-addr"] = 0; + regs[i]["reg-value"] = 0; + } + + this.$dispatch("config-changed"); + }, + + reset_failures: function(e) { + e.preventDefault(); + const regs = this.config["modbus-spindle"].regs; + for (let reg = 0; reg < regs.length; reg++) { + this.$dispatch("send", `$${reg}vr=0`); + } } - ] } - }, - - components: { - 'modbus-reg': require('./modbus-reg.js') - }, - - watch: { - 'state.mr': function () { this.value = this.state.mr } - }, - - events: { - 'input-changed': function () { - this.$dispatch('config-changed'); - - return false; - }, - }, - - ready: function () { - this.value = this.state.mr; - }, - - computed: { - regs_tmpl: function () { - return this.template['modbus-spindle'].regs; - }, - - tool_type: function () { - return this.config.tool['tool-type'].toUpperCase(); - }, - - selected_tool: function () { - return this.config.tool['selected-tool']; - }, - - is_pwm_spindle: function () { - return this.selected_tool == 'pwm'; - }, - - is_modbus: function () { - switch (this.selected_tool) { - case "disabled": - case "laser": - case "router": - case "pwm": - return false; - - default: - return true; - } - }, - - modbus_status: function () { - return modbus.status_to_string(this.state.mx); - } - }, - - methods: { - change_selected_tool: function () { - const selectedToolSettings = this.config['selected-tool-settings'] || {}; - const settings = selectedToolSettings[this.selected_tool] || {}; - this.config.tool = merge({}, this.config.tool, settings['tool']); - this.config['pwm-spindle'] = merge({}, this.config['pwm-spindle'], settings['pwm-spindle']); - this.config['modbus-spindle'] = merge({}, this.config['modbus-spindle'], settings['modbus-spindle']); - - const tool = this.toolList.find(tool => tool.id == this.config.tool['selected-tool']); - this.config.tool["tool-type"] = tool.type || tool.name; - - this.$dispatch("config-changed"); - }, - - show_tool_settings: function (key) { - switch (true) { - case key === "tool-type": - case key === "selected-tool": - return false; - - case this.selected_tool === "disabled": - return false; - - case this.selected_tool === "laser": - case this.selected_tool === "router": - switch (key) { - case "tool-enable-mode": - return true; - - default: - return false; - } - - default: - return true; - } - }, - - get_reg_type: function (reg) { - return this.regs_tmpl.template['reg-type'].values[this.state[reg + 'vt']]; - }, - - get_reg_addr: function (reg) { - return this.state[reg + 'va']; - }, - - get_reg_value: function (reg) { - return this.state[reg + 'vv']; - }, - - get_reg_fails: function (reg) { - const fails = this.state[reg + 'vr'] - return fails == 255 ? 'Max' : fails; - }, - - show_modbus_field: function (key) { - return key != 'regs' && - (key != 'multi-write' || this.tool_type == 'CUSTOM MODBUS VFD'); - }, - - read: function (e) { - e.preventDefault(); - api.put('modbus/read', { address: this.address }); - }, - - write: function (e) { - e.preventDefault(); - api.put('modbus/write', { address: this.address, value: this.value }); - }, - - customize: function (e) { - e.preventDefault(); - this.config.tool['tool-type'] = 'Custom Modbus VFD'; - - const regs = this.config['modbus-spindle'].regs; - for (let i = 0; i < regs.length; i++) { - const reg = this.regs_tmpl.index[i]; - regs[i]['reg-type'] = this.get_reg_type(reg); - regs[i]['reg-addr'] = this.get_reg_addr(reg); - regs[i]['reg-value'] = this.get_reg_value(reg); - } - - this.$dispatch('config-changed'); - }, - - clear: function (e) { - e.preventDefault(); - this.config.tool['tool-type'] = 'Custom Modbus VFD'; - - const regs = this.config['modbus-spindle'].regs; - for (let i = 0; i < regs.length; i++) { - regs[i]['reg-type'] = 'disabled'; - regs[i]['reg-addr'] = 0; - regs[i]['reg-value'] = 0; - } - - this.$dispatch('config-changed'); - }, - - reset_failures: function (e) { - e.preventDefault(); - const regs = this.config['modbus-spindle'].regs; - for (let reg = 0; reg < regs.length; reg++) - this.$dispatch('send', '\$' + reg + 'vr=0'); - } - } -} +}; diff --git a/src/js/unit-value.js b/src/js/unit-value.js index d4d6ee0..cb0dcb3 100644 --- a/src/js/unit-value.js +++ b/src/js/unit-value.js @@ -1,58 +1,47 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -'use strict' - +"use strict"; module.exports = { - replace: true, - template: '{{text}}{{metric ? unit : iunit}}', - props: ['value', 'precision', 'unit', 'iunit', 'scale'], + replace: true, + template: '{{text}}{{metric ? unit : iunit}}', + props: [ "value", "precision", "unit", "iunit", "scale" ], + computed: { + metric: { + cache: false, + get: function() { + return this.$root.display_units === "METRIC"; + } + }, - computed: { - metric: function () {return !this.$root.state.imperial}, + text: function() { + let value = this.value; + if (typeof value == "undefined") { + return ""; + } + if (!this.metric) { + value /= this.scale; + } - text: function () { - var value = this.value; - if (typeof value == 'undefined') return ''; + return (1 * value.toFixed(this.precision)).toLocaleString(); + } + }, - if (!this.metric) value /= this.scale; + ready: function() { + if (typeof this.precision == "undefined") { + this.precision = 0; + } - return (1 * value.toFixed(this.precision)).toLocaleString(); + if (typeof this.unit == "undefined") { + this.unit = "mm"; + } + + if (typeof this.iunit == "undefined") { + this.iunit = "in"; + } + + if (typeof this.scale == "undefined") { + this.scale = 25.4; + } } - }, - - - ready: function () { - if (typeof this.precision == 'undefined') this.precision = 0; - if (typeof this.unit == 'undefined') this.unit = 'mm'; - if (typeof this.iunit == 'undefined') this.iunit = 'in'; - if (typeof this.scale == 'undefined') this.scale = 25.4; - } -} +}; diff --git a/src/js/utils.js b/src/js/utils.js new file mode 100644 index 0000000..f21b9e9 --- /dev/null +++ b/src/js/utils.js @@ -0,0 +1,9 @@ +function clickFileInput(formClass) { + const form = document.querySelector(`.${formClass}`); + form.reset(); + form.querySelector("input").click(); +} + +module.exports = { + clickFileInput +}; diff --git a/src/pug/index.pug b/src/pug/index.pug index 1eedc13..d5ba622 100644 --- a/src/pug/index.pug +++ b/src/pug/index.pug @@ -3,7 +3,6 @@ html(lang="en") head meta(charset="utf-8") meta(name="viewport", content="width=device-width, initial-scale=1.0") - link(rel="preload" href="/fonts/material-symbols-outlined.woff2" as="font" type="font/woff2" crossorigin) title Onefinity CNC - Web interface @@ -16,10 +15,11 @@ html(lang="en") style: include ../svelte-components/node_modules/svelte-material-ui/bare.css style: include ../../build/http/svelte-components/smui.css style: include ../../build/http/svelte-components/style.css - style: include ../../build/http/svelte-components/material-symbols-outlined.css style: include:stylus ../stylus/style.styl body(v-cloak) + #svelte-dialog-host + #overlay(v-if="status != 'connected'") span {{status}} @@ -65,19 +65,11 @@ html(lang="en") li.pure-menu-heading a.pure-menu-link(href="#help") Help - button.pure-button.pure-button-primary(@click="confirmShutdown = true", style="width: 100%") - .fa.fa-power-off - message(:show.sync="confirmShutdown") - h3(slot="header") Confirm shutdown? - p(slot="body") Please wait for black screen before switching off power. - div(slot="footer") - button.pure-button(@click="confirmShutdown = false") Cancel - button.pure-button.button-success(@click="shutdown") Shutdown - button.pure-button.button-success(@click="reboot") Restart - + button.pure-button.pure-button-primary(@click="showShutdownDialog", style="width: 100%") + .fa.fa-power-off #main - .header + .nav-header .brand img(src="/images/onefinity_logo.png") .version @@ -181,7 +173,6 @@ html(lang="en") #templates: include ../../build/templates.pug iframe#download-target(style="display:none") - script: include ../static/js/jquery-1.11.3.min.js script: include ../static/js/vue.js script: include ../static/js/sockjs.min.js script: include ../static/js/clusterize.min.js diff --git a/src/pug/templates/admin-general-view.pug b/src/pug/templates/admin-general-view.pug index d90a20c..8eb358a 100644 --- a/src/pug/templates/admin-general-view.pug +++ b/src/pug/templates/admin-general-view.pug @@ -45,9 +45,6 @@ script#admin-general-view-template(type="text/x-template") label.pure-button.pure-button-primary(@click="restore_config") Restore form.restore-config.file-upload input(type="file", accept=".json", @change="restore") - message(:show.sync="configRestored") - h3(slot="header") Success - p(slot="body") Configuration restored. button.pure-button.pure-button-primary(@click="confirmReset = true") Reset message(:show.sync="confirmReset") @@ -70,10 +67,6 @@ script#admin-general-view-template(type="text/x-template") button.pure-button(@click="confirmReset = false") Cancel button.pure-button.pure-button-primary(@click="reset") Reset - message(:show.sync="configReset") - h3(slot="header") Success - p(slot="body") Configuration reset. - h2 Debugging a(href="/api/log", target="_blank") button.pure-button.pure-button-primary View Log diff --git a/src/pug/templates/admin-network-view.pug b/src/pug/templates/admin-network-view.pug index dd57264..dd7d4a9 100644 --- a/src/pug/templates/admin-network-view.pug +++ b/src/pug/templates/admin-network-view.pug @@ -1,3 +1,2 @@ script#admin-network-view-template(type="text/x-template") - #admin-network - #svelte-root + #admin-network \ No newline at end of file diff --git a/src/pug/templates/control-view.pug b/src/pug/templates/control-view.pug index 7c08bf5..6f5887d 100644 --- a/src/pug/templates/control-view.pug +++ b/src/pug/templates/control-view.pug @@ -1,30 +1,3 @@ -//-///////////////////////////////////////////////////////////////////////////// -//- // -//- This file is part of the Buildbotics firmware. // -//- // -//- Copyright (c) 2015 - 2018, Buildbotics LLC // -//- All rights reserved. // -//- // -//- This file ("the software") is free software: you can redistribute it // -//- and/or modify it under the terms of the GNU General Public License, // -//- version 2 as published by the Free Software Foundation. You should // -//- have received a copy of the GNU General Public License, version 2 // -//- along with the software. If not, see . // -//- // -//- The software is distributed in the hope that it will be useful, but // -//- WITHOUT ANY WARRANTY; without even the implied warranty of // -//- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // -//- Lesser General Public License for more details. // -//- // -//- You should have received a copy of the GNU Lesser General Public // -//- License along with the software. If not, see // -//- . // -//- // -//- For information regarding this software email: // -//- "Joseph Coffland" // -//- // -//-///////////////////////////////////////////////////////////////////////////// - script#control-view-template(type="text/x-template") #control message(:show.sync="showGcodeMessage") @@ -36,109 +9,6 @@ script#control-view-template(type="text/x-template") div(slot="footer") label Simulating {{(toolpath_progress || 0) | percent}} - - message(:show.sync=`ask_home_msg`) - h3(slot="header") Home Machine - - div(slot="body") - p Home the machine? - - div(slot="footer") - button.pure-button(@click="home()") - | OK - - button.pure-button(@click='ask_home_msg = false; ask_home = false') - | Cancel - - message(:show.sync=`ask_zero_xy_msg`) - h3(slot="header") XY Origin - - div(slot="body") - p Move to XY origin? - - div(slot="footer") - button.pure-button(@click="goto_zero(1,1,0,0)") - | Confirm - - button.pure-button(@click='ask_zero_xy_msg = false') - | Cancel - - message(:show.sync=`ask_zero_z_msg`) - h3(slot="header") Z Origin - - div(slot="body") - p Move to Z origin? - - div(slot="footer") - button.pure-button(@click="goto_zero(0,0,1,0)") - | Confirm - - button.pure-button(@click='ask_zero_z_msg = false') - | Cancel - - message(:show.sync=`show_probe_test_modal`) - - h3(slot="header") Test probe connection - - div(slot="body") - .pure-form - p Attach the probe magnet to the collet. - p Touch the probe block to the bit. - - div(slot="footer") - button.pure-button(@click=`show_probe_test_modal = false`) - | Cancel - - button.pure-button.button-success( - :disabled=`!state.saw_probe_connected` - @click=`finish_probe_test()`) Continue - - message(:show.sync=`show_tool_diameter_modal`) - h3(slot="header") Enter probe tool information - - div(slot="body") - .pure-form - .pure-control-group - label="{{metric ? 'Diameter (mm)' : 'Diameter (inches)'}}" - input(v-model="tool_diameter_for_prompt", size="8") - p - - div(slot="footer") - button.pure-button(@click=`show_tool_diameter_modal = false`) - | Cancel - - button.pure-button.button-success( - @click=`set_tool_diameter`) - | Set - - message(:show.sync=`state.show_probe_complete_modal`) - h3(slot="header") Probing complete! - - div(slot="body") - .pure-form - p Don't forget to put away the probe! - div(v-if="state.goto_xy_zero_after_probe") - p - | The machine will now move - br - | to the X-Y zero point. - p Watch your hands! - - div(slot="footer") - button.pure-button.button-success(@click=`$emit("finalize_probe")`) - | Done - - message(:show.sync=`state.show_probe_failed_modal`) - h3(slot="header") Probing failed! - - div(slot="body") - .pure-form - p Could not find the probe block during probing! - p Make sure the tip of the bit is about 1/4" (~6mm) above the probe block, and try again. - - div(slot="footer") - button.pure-button.button-success(@click=`hide_probe_failed_modal()`) - | OK table(style="table-layout: fixed; width: 100%;") tr(style="height: fit-content;") @@ -151,55 +21,60 @@ script#control-view-template(type="text/x-template") col(style="width:100px") tr td(style="height:100px",align="center") - button(style="height:100px;width:100px",@click="jog_fn(-1,1,0,0)") + button(@click="jog_fn(-1,1,0,0)") .fa.fa-arrow-right(style="transform: rotate(-135deg);") td(style="height:100px",align="center") - button(style="height:100px;width:100px",@click="jog_fn(0,1,0,0)") Y+ + button(@click="jog_fn(0,1,0,0)") Y+ td(style="height:100px",align="center") - button(style="height:100px;width:100px",@click="jog_fn(1,1,0,0)") + button(@click="jog_fn(1,1,0,0)") .fa.fa-arrow-right(style="transform: rotate(-45deg);") td(style="height:100px",align="center") - button(style="height:100px;width:100px",,@click="jog_fn(0,0,1,0)") Z+ + button(,@click="jog_fn(0,0,1,0)") Z+ tr td(style="height:100px",align="center") - button(style="height:100px;width:100px",@click="jog_fn(-1,0,0,0)") X- + button(@click="jog_fn(-1,0,0,0)") X- td(style="height:100px",align="center") - button(style="height:100px;width:100px",@click="ask_zero_xy_msg = true") - .fa.fa-bullseye(style="font-size: 172%") + button(@click="showMoveToZeroDialog('xy')") + .fa.fa-bullseye(style="font-size: 173%") td(style="height:100px",align="center") - button(style="height:100px;width:100px",@click="jog_fn(1,0,0,0)") X+ + button(@click="jog_fn(1,0,0,0)") X+ td(style="height:100px",align="center") - button(style="height:100px;width:100px",@click='ask_zero_z_msg = true') Z0 + button(@click="showMoveToZeroDialog('z')") Z0 tr td(style="height:100px",align="center") - button(style="height:100px;width:100px",@click="jog_fn(-1,-1,0,0)") + button(@click="jog_fn(-1,-1,0,0)") .fa.fa-arrow-right(style="transform: rotate(135deg);") td(style="height:100px",align="center") - button(style="height:100px;width:100px",@click="jog_fn(0,-1,0,0)") Y- + button(@click="jog_fn(0,-1,0,0)") Y- td(style="height:100px",align="center") - button(style="height:100px;width:100px",@click="jog_fn(1,-1,0,0)") + button(@click="jog_fn(1,-1,0,0)") .fa.fa-arrow-right(style="transform: rotate(45deg);") td(style="height:100px",align="center") - button(style="height:100px;width:100px",@click="jog_fn(0,0,-1,0)") Z- + button(@click="jog_fn(0,0,-1,0)") Z- tr td(style="height:100px",align="center") - button#jog_button_fine(style="height:100px;width:100px", @click=`set_jog_incr('fine')`) 0.1 + button(:style="getJogIncrStyle('fine')", @click="jog_incr = 'fine'") + span {{jog_incr_amounts[display_units].fine}}#[span.jog-units {{metric ? 'mm' : 'in'}}] td(style="height:100px",align="center") - button#jog_button_small(style="height:100px;width:100px", @click=`set_jog_incr('small')`) 1.0 + button(:style="getJogIncrStyle('small')", @click="jog_incr = 'small'") + span {{jog_incr_amounts[display_units].small}}#[span.jog-units {{metric ? 'mm' : 'in'}}] td(style="height:100px",align="center") - button#jog_button_medium(style="height:100px;width:100px", @click=`set_jog_incr('medium')`) 10 + button(:style="getJogIncrStyle('medium')", @click="jog_incr = 'medium'") + span {{jog_incr_amounts[display_units].medium}}#[span.jog-units {{metric ? 'mm' : 'in'}}] td(style="height:100px",align="center") - button#jog_button_large(style="height:100px;width:100px", @click=`set_jog_incr('large')`) 100 + button(:style="getJogIncrStyle('large')", @click="jog_incr = 'large'") + span {{jog_incr_amounts[display_units].large}}#[span.jog-units {{metric ? 'mm' : 'in'}}] tr td(style="height:100px", align="center", colspan="2") button(:class="state['pw'] ? '' : 'load-on'", style="height:100px;width:200px", - @click=`start_probe_test(prep_and_show_tool_diameter_modal)`) + @click="showProbeDialog('xyz')") | Probe XYZ + td(style="height:100px", align="center", colspan="2") button(:class="state['pw'] ? '' : 'load-on'", style="height:100px;width:200px", - @click=`start_probe_test(probe_z)`) + @click="showProbeDialog('z')") | Probe Z td(style="vertical-align: top;") @@ -211,8 +86,6 @@ script#control-view-template(type="text/x-template") th.offset Offset th.state State th.tstate Toolpath - //th.tstate Min - //th.tstate Max th.actions button.pure-button(disabled, style="height:60px;width:60px;display:none;") @@ -234,79 +107,25 @@ script#control-view-template(type="text/x-template") td.state .fa(:class=`'fa-' + ${axis}.icon`) | {{#{axis}.state}} - td.tstate(:class=`${axis}.tklass`, :title=`${axis}.toolmsg`, @click=`show_toolpath_msg('${axis}')`) + td.tstate(:class=`${axis}.tklass`, :title=`${axis}.toolmsg`, @click=`showToolpathMessageDialog('${axis}')`) .fa(:class=`'fa-' + ${axis}.ticon`) | {{#{axis}.tstate}} - //td.tstate: unit-value(:value=`${axis}.pathMin`, precision=4) - //td.tstate: unit-value(:value=`${axis}.pathMax`, precision=4) - - message(:show.sync=`toolpath_msg['${axis}']`) - h3(slot="header") Tool path info {{'#{axis}' | upper}} axis - - div(slot="body") - p {{#{axis}.toolmsg}} - - div(slot="footer") - button.pure-button(@click=`toolpath_msg['${axis}'] = false`) - | OK - + th.actions button.pure-button(:disabled="!can_set_axis", title=`Set {{'${axis}' | upper}} axis position.`, - @click=`show_set_position('${axis}')`,style="height:60px;width:60px") + @click=`show_set_position('${axis}')`, style="height:60px;width:60px") .fa.fa-cog button.pure-button(:disabled="!can_set_axis", title=`Zero {{'${axis}' | upper}} axis offset.`, - @click=`zero('${axis}')`,style="height:60px;width:60px") + @click=`zero('${axis}')`, style="height:60px;width:60px") .fa.fa-map-marker button.pure-button(:disabled="!is_idle", @click=`home('${axis}')`, - title=`Home {{'${axis}' | upper}} axis.`,style="height:60px;width:60px") + title=`Home {{'${axis}' | upper}} axis.`, style="height:60px;width:60px") .fa.fa-home - message(:show.sync=`position_msg['${axis}']`) - h3(slot="header") Set {{'#{axis}' | upper}} axis position - - div(slot="body") - .pure-form - .pure-control-group - label Position - input(v-model="axis_position", - @keyup.enter=`set_position('${axis}', axis_position)`) - p - - div(slot="footer") - button.pure-button(@click=`position_msg['${axis}'] = false`) - | Cancel - - button.pure-button(v-if=`${axis}.homed`, - @click=`unhome('${axis}')`) Unhome - - button.pure-button.button-success( - @click=`set_position('${axis}', axis_position)`) Set - - message(:show.sync=`manual_home['${axis}']`) - h3(slot="header") Manually home {{'#{axis}' | upper}} axis - - div(slot="body") - p Set axis absolute position. - - .pure-form - .pure-control-group - label Absolute - input(v-model="axis_position", - @keyup.enter=`set_home('${axis}', axis_position)`) - - p - - div(slot="footer") - button.pure-button(@click=`manual_home['${axis}'] = false`) - | Cancel - - button.pure-button.button-success( - title=`Home {{'${axis}' | upper}} axis.`, - @click=`set_home('${axis}', axis_position)`) Set tr(style="vertical-align: top;") td @@ -323,10 +142,10 @@ script#control-view-template(type="text/x-template") td.message(:class="{attention: highlight_state}") | {{message.replace(/^#/, '')}} - tr(title="Active machine units") - th Units - td.mach_units - select(v-model="mach_units", :disabled="!is_idle") + tr + th Display Units + td.units + select(v-model="display_units") option(value="METRIC") METRIC option(value="IMPERIAL") IMPERIAL @@ -368,6 +187,11 @@ script#control-view-template(type="text/x-template") td table.info + tr + th Current Time + td + span {{current_time}} + tr th Remaining td(title="Total run time (days:hours:mins:secs)"). @@ -376,12 +200,7 @@ script#control-view-template(type="text/x-template") tr th ETA td.eta {{eta}} - tr - th Line - td - | {{0 <= state.line ? state.line : 0 | number}} - span(v-if="toolpath.lines") - |  of {{toolpath.lines | number}} + tr th Progress td.progress @@ -484,6 +303,9 @@ script#control-view-template(type="text/x-template") input(v-model="mdi", :disabled="!can_mdi", @keyup.enter="submit_mdi") + div + em The machine is currently operating in #[strong {{mach_units}}] units. Use G20/G21 to switch units. + .history(:class="{placeholder: !history}") span(v-if="!history.length") MDI history displays here. ul @@ -497,9 +319,6 @@ script#control-view-template(type="text/x-template") section#content4.tab-content indicators(:state="state", :template="template") - - - .override(title="Feed rate override.") label Feed input(type="range", min="0", max="2", step="0.01", diff --git a/src/pug/templates/help-view.pug b/src/pug/templates/help-view.pug index 4c1b677..cb68321 100644 --- a/src/pug/templates/help-view.pug +++ b/src/pug/templates/help-view.pug @@ -1,75 +1,43 @@ -//-///////////////////////////////////////////////////////////////////////////// -//- // -//- This file is part of the Buildbotics firmware. // -//- // -//- Copyright (c) 2015 - 2018, Buildbotics LLC // -//- All rights reserved. // -//- // -//- This file ("the software") is free software: you can redistribute it // -//- and/or modify it under the terms of the GNU General Public License, // -//- version 2 as published by the Free Software Foundation. You should // -//- have received a copy of the GNU General Public License, version 2 // -//- along with the software. If not, see . // -//- // -//- The software is distributed in the hope that it will be useful, but // -//- WITHOUT ANY WARRANTY; without even the implied warranty of // -//- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // -//- Lesser General Public License for more details. // -//- // -//- You should have received a copy of the GNU Lesser General Public // -//- License along with the software. If not, see // -//- . // -//- // -//- For information regarding this software email: // -//- "Joseph Coffland" // -//- // -//-///////////////////////////////////////////////////////////////////////////// - script#help-view-template(type="text/x-template") - #help - h2 Contact - p - | You can contact us here - | - a(href="https://onefinitycnc.com/support", target="_blank") - | onefinitycnc.com/support - |. + #help + h2 Support & Contact Info + p + | Please visit + | + a(href="https://onefinitycnc.com/support", target="_blank") + | onefinitycnc.com/support + | + | for a variety of support resources, and to find our contact information. - h2 Discussion Forum - p - | Check out our support and discussion forum. - | - a(href="https://forum.onefinitycnc.com", target="_blank") - | forum.onefinitycnc.com - |. Register on the site and post a message. We can't wait to hear from you. + h2 Discussion Forum + p + | Check out our support and discussion forum at + | + a(href="https://forum.onefinitycnc.com", target="_blank") + | forum.onefinitycnc.com + | . Register on the site and post a message. We can't wait to hear from you. + p + | We also maintain a list of + | + a(href="https://forum.onefinitycnc.com/t/what-cad-cam-software-can-be-used-to-make-gcode-files-for-the-onefinity-cnc/10253", target="_blank") + | recommended software packages + | + | on the forum. - h2 Buildbotics - p - | This controller is based on the Buildbotics CNC Controller. - | We encourage you to check out the - a(href="http://buildbotics.com", target="_blank") Buildbotics Website - |. + h2 Credits & Acknowledgements + h4(style="margin-bottom: 0;") Artwork + p(style="margin-top: 0;") + | Special thanks to + | + a(href="https://www.instagram.com/fierysquirrelart/", target="_blank") + | @fierysquirrelart + | + | for many of the graphics used in the controller. - h2 CAD/CAM Software - p - a(href="http://wikipedia.com/wiki/Computer-aided_manufacturing", - target="_blank") CAM - | - | software can be used to create GCode - | automatically from - | - a(href="http://wikipedia.com/wiki/Computer-aided_design", - target="_blank") CAD - | - | models. Here are a few CAD/CAM resources: - ul - li: a(href="http://camotics.org/", target="_blank") - | CAMotics - Open-Source CNC Simulator - li: a(href="http://librecad.org/", target="_blank") - | LibreCAD - Open-Source 2D CAD - li: a(href="https://www.freecadweb.org/", target="_blank") - | FreeCAD - Open-Source 3D CAD - li: a(href="http://www.openscad.org/", target="_blank") - | OpenSCAD - Open-Source 3D CAD for programmers - li: a(href="http://wiki.linuxcnc.org/cgi-bin/wiki.pl?Cam", - target="_blank") LinuxCNC CAM resources + h4(style="margin-bottom: 0;") Buildbotics + p(style="margin-top: 0;") + | This controller is based on the + | + a(href="http://buildbotics.com", target="_blank") + | Buildbotics CNC Controller + | . diff --git a/src/pug/templates/settings-view.pug b/src/pug/templates/settings-view.pug index 058e043..4b6cf85 100644 --- a/src/pug/templates/settings-view.pug +++ b/src/pug/templates/settings-view.pug @@ -1,85 +1,2 @@ -//- All rights reserved. // -//- // -//- This file ("the software") is free software: you can redistribute it // -//- and/or modify it under the terms of the GNU General Public License, // -//- version 2 as published by the Free Software Foundation. You should // -//- have received a copy of the GNU General Public License, version 2 // -//- along with the software. If not, see . // -//- // -//- The software is distributed in the hope that it will be useful, but // -//- WITHOUT ANY WARRANTY; without even the implied warranty of // -//- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // -//- Lesser General Public License for more details. // -//- // -//- You should have received a copy of the GNU Lesser General Public // -//- License along with the software. If not, see // -//- . // -//- // -//- For information regarding this software email: // -//- "Joseph Coffland" // -//- // -//-///////////////////////////////////////////////////////////////////////////// - script#settings-view-template(type="text/x-template") #settings - h1 Settings - - .pure-form.pure-form-aligned - fieldset - h2 Units - templated-input(name="units", :model.sync="config.settings.units", - :template="template.settings.units") - - p - | Note, #[tt units] sets both the machine default units and the - | units used in motor configuration. GCode #[tt program-start], - | set below, may also change the default machine units. - - fieldset - h2 Probing safety prompts - templated-input(name="probing-prompts", - :model.sync="config.settings['probing-prompts']", - :template="template.settings['probing-prompts']") - - fieldset - h2 Probe Dimensions - templated-input(v-for="templ in template.probe", :name="$key", - :model.sync="config.probe[$key]", :template="templ") - - fieldset - h2 GCode - templated-input(v-for="templ in template.gcode", :name="$key", - :model.sync="config.gcode[$key]", :template="templ") - - fieldset - h2 Path Accuracy - templated-input(name="max-deviation", - :model.sync="config.settings['max-deviation']", - :template="template.settings['max-deviation']") - - p. - Lower #[tt max-deviation] to follow the programmed path more precisely - but at a slower speed. - - p. - In order to improve traversal speed, the path planner may merge - consecutive moves or round off sharp corners if doing so would deviate - from the program path by less than #[tt max-deviation]. - - - var base = '//linuxcnc.org/docs/html/gcode/g-code.html' - p. - GCode commands - #[a(href=base + "#gcode:g61", target="_blank") G61, G61.1] and - #[a(href=base + "#gcode:g64", target="_blank") G64] also affect path - planning accuracy. - - h2 Cornering Speed (Advanced) - templated-input(name="junction-accel", - :model.sync="config.settings['junction-accel']", - :template="template.settings['junction-accel']") - - p. - Junction acceleration limits the cornering speed the planner will - allow. Increasing this value will allow for faster traversal of - corners but may cause the planner to violate axis jerk limits and - stall the motors. Use with caution. diff --git a/src/pug/templates/templated-input.pug b/src/pug/templates/templated-input.pug index c4c48ce..7e69979 100644 --- a/src/pug/templates/templated-input.pug +++ b/src/pug/templates/templated-input.pug @@ -1,30 +1,3 @@ -//-///////////////////////////////////////////////////////////////////////////// -//- // -//- This file is part of the Buildbotics firmware. // -//- // -//- Copyright (c) 2015 - 2018, Buildbotics LLC // -//- All rights reserved. // -//- // -//- This file ("the software") is free software: you can redistribute it // -//- and/or modify it under the terms of the GNU General Public License, // -//- version 2 as published by the Free Software Foundation. You should // -//- have received a copy of the GNU General Public License, version 2 // -//- along with the software. If not, see . // -//- // -//- The software is distributed in the hope that it will be useful, but // -//- WITHOUT ANY WARRANTY; without even the implied warranty of // -//- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // -//- Lesser General Public License for more details. // -//- // -//- You should have received a copy of the GNU Lesser General Public // -//- License along with the software. If not, see // -//- . // -//- // -//- For information regarding this software email: // -//- "Joseph Coffland" // -//- // -//-///////////////////////////////////////////////////////////////////////////// - script#templated-input-template(type="text/x-template") .pure-control-group(class="tmpl-input-{{name}}", :title="title") label(:for="name") {{name}} diff --git a/src/py/bbctrl/APIHandler.py b/src/py/bbctrl/APIHandler.py index c21ca56..960ff8f 100644 --- a/src/py/bbctrl/APIHandler.py +++ b/src/py/bbctrl/APIHandler.py @@ -1,54 +1,24 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import json -import traceback -import bbctrl - from tornado.web import HTTPError +import bbctrl +import json import tornado.httpclient class APIHandler(bbctrl.RequestHandler): + def delete(self, *args, **kwargs): self.delete_ok(*args, **kwargs) self.write_json('ok') - - def delete_ok(self): raise HTTPError(405) - + def delete_ok(self): + raise HTTPError(405) def put(self, *args, **kwargs): self.put_ok(*args, **kwargs) self.write_json('ok') - - def put_ok(self): raise HTTPError(405) - + def put_ok(self): + raise HTTPError(405) def prepare(self): self.json = {} @@ -59,11 +29,9 @@ class APIHandler(bbctrl.RequestHandler): except ValueError: raise HTTPError(400, 'Unable to parse JSON') - def set_default_headers(self): self.set_header('Content-Type', 'application/json') - def write_error(self, status_code, **kwargs): e = {} @@ -73,16 +41,17 @@ class APIHandler(bbctrl.RequestHandler): typ, value, tb = kwargs['exc_info'] if isinstance(value, HTTPError) and value.log_message: e['message'] = value.log_message % value.args - else: e['message'] = str(kwargs['exc_info'][1]) + else: + e['message'] = str(kwargs['exc_info'][1]) - else: e['message'] = 'Unknown error' + else: + e['message'] = 'Unknown error' e['code'] = status_code self.write_json(e) - - def write_json(self, data, pretty = False): - if pretty: data = json.dumps(data, indent = 2, separators = (',', ': ')) - else: data = json.dumps(data, separators = (',', ':')) + def write_json(self, data, pretty=False): + if pretty: data = json.dumps(data, indent=2, separators=(',', ': ')) + else: data = json.dumps(data, separators=(',', ':')) self.write(data) diff --git a/src/py/bbctrl/AVR.py b/src/py/bbctrl/AVR.py index 211fe6e..0222ffe 100644 --- a/src/py/bbctrl/AVR.py +++ b/src/py/bbctrl/AVR.py @@ -1,59 +1,29 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - +import ctypes import serial import time import traceback -import ctypes - -import bbctrl -import bbctrl.Cmd as Cmd class serial_struct(ctypes.Structure): _fields_ = [ - ('type', ctypes.c_int), - ('line', ctypes.c_int), - ('port', ctypes.c_uint), - ('irq', ctypes.c_int), - ('flags', ctypes.c_int), - ('xmit_fifo_size', ctypes.c_int), - ('custom_divisor', ctypes.c_int), - ('baud_base', ctypes.c_int), - ('close_delay', ctypes.c_ushort), - ('io_type', ctypes.c_byte), - ('reserved', ctypes.c_byte), - ('hub6', ctypes.c_int), - ('closing_wait', ctypes.c_ushort), - ('closing_wait2', ctypes.c_ushort), - ('iomem_base', ctypes.c_char_p), + ('type', ctypes.c_int), + ('line', ctypes.c_int), + ('port', ctypes.c_uint), + ('irq', ctypes.c_int), + ('flags', ctypes.c_int), + ('xmit_fifo_size', ctypes.c_int), + ('custom_divisor', ctypes.c_int), + ('baud_base', ctypes.c_int), + ('close_delay', ctypes.c_ushort), + ('io_type', ctypes.c_byte), + ('reserved', ctypes.c_byte), + ('hub6', ctypes.c_int), + ('closing_wait', ctypes.c_ushort), + ('closing_wait2', ctypes.c_ushort), + ('iomem_base', ctypes.c_char_p), ('iomem_reg_shift', ctypes.c_ushort), - ('port_high', ctypes.c_uint), - ('iomap_base', ctypes.c_ulong), + ('port_high', ctypes.c_uint), + ('iomap_base', ctypes.c_ulong), ] @@ -65,11 +35,12 @@ def serial_set_low_latency(sp): ss = serial_struct() fcntl.ioctl(sp, termios.TIOCGSERIAL, ss) - ss.flags |= 1 << ASYNCB_LOW_LATENCY # pylint: disable=no-member + ss.flags |= 1 << ASYNCB_LOW_LATENCY # pylint: disable=no-member fcntl.ioctl(sp, termios.TIOCSSERIAL, ss) class AVR(object): + def __init__(self, ctrl): self.ctrl = ctrl self.log = ctrl.log.get('AVR') @@ -79,14 +50,16 @@ class AVR(object): self.read_cb = None self.write_cb = None - - def close(self): pass - + def close(self): + pass def _start(self): try: - self.sp = serial.Serial(self.ctrl.args.serial, self.ctrl.args.baud, - rtscts = 1, timeout = 0, write_timeout = 0) + self.sp = serial.Serial(self.ctrl.args.serial, + self.ctrl.args.baud, + rtscts=1, + timeout=0, + write_timeout=0) self.sp.nonblocking() #serial_set_low_latency(self.sp) @@ -98,7 +71,6 @@ class AVR(object): self.ctrl.ioloop.add_handler(self.sp, self._serial_handler, self.ctrl.ioloop.READ) - def set_handlers(self, read_cb, write_cb): if self.read_cb is not None or self.write_cb is not None: raise Exception('Handler already set') @@ -107,7 +79,6 @@ class AVR(object): self.write_cb = write_cb self._start() - def enable_write(self, enable): if self.sp is None: return @@ -115,11 +86,9 @@ class AVR(object): if enable: flags |= self.ctrl.ioloop.WRITE self.ctrl.ioloop.update_handler(self.sp, flags) - def _serial_write(self): self.write_cb(lambda data: self.sp.write(data)) - def _serial_read(self): try: data = '' @@ -129,17 +98,16 @@ class AVR(object): except Exception as e: self.log.warning('%s: %s', e, data) - def _serial_handler(self, fd, events): try: if self.ctrl.ioloop.READ & events: self._serial_read() if self.ctrl.ioloop.WRITE & events: self._serial_write() except Exception as e: - self.log.warning('Serial handler error: %s', traceback.format_exc()) + self.log.warning('Serial handler error: %s', + traceback.format_exc()) - - def i2c_command(self, cmd, byte = None, word = None, block = None): + def i2c_command(self, cmd, byte=None, word=None, block=None): self.log.info('I2C: %s b=%s w=%s d=%s' % (cmd, byte, word, block)) retry = 10 cmd = ord(cmd[0]) diff --git a/src/py/bbctrl/AVREmu.py b/src/py/bbctrl/AVREmu.py deleted file mode 100644 index 05181af..0000000 --- a/src/py/bbctrl/AVREmu.py +++ /dev/null @@ -1,207 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import os -import sys -import traceback -import signal - -import bbctrl -import bbctrl.Cmd as Cmd - - -class AVREmu(object): - def __init__(self, ctrl): - self.ctrl = ctrl - self.log = ctrl.log.get('AVREmu') - - self.avrOut = None - self.avrIn = None - self.i2cOut = None - self.read_cb = None - self.write_cb = None - self.pid = None - - - def close(self): - # Close pipes - def _close(fd, withHandle): - if fd is None: return - try: - if withHandle: self.ctrl.ioloop.remove_handler(fd) - except: pass - try: - os.close(fd) - except: pass - - _close(self.avrOut, True) - _close(self.avrIn, True) - _close(self.i2cOut, False) - - self.avrOut, self.avrIn, self.i2cOut = None, None, None - - # Kill process and wait for it - if self.pid is not None: - os.kill(self.pid, signal.SIGKILL) - os.waitpid(self.pid, 0) - self.pid = None - - - def _start(self): - try: - self.close() - - # Create pipes - stdinFDs = os.pipe() - stdoutFDs = os.pipe() - i2cFDs = os.pipe() - - self.pid = os.fork() - - if not self.pid: - # Dup child ends - os.dup2(stdinFDs[0], 0) - os.dup2(stdoutFDs[1], 1) - os.dup2(i2cFDs[0], 3) - - # Close orig fds - os.close(stdinFDs[0]) - os.close(stdoutFDs[1]) - os.close(i2cFDs[0]) - - # Close parent ends - os.close(stdinFDs[1]) - os.close(stdoutFDs[0]) - os.close(i2cFDs[1]) - - cmd = ['bbemu'] - if self.ctrl.args.fast_emu: cmd.append('--fast') - - os.execvp(cmd[0], cmd) - os._exit(1) # In case of failure - - # Parent, close child ends - os.close(stdinFDs[0]) - os.close(stdoutFDs[1]) - os.close(i2cFDs[0]) - - # Non-blocking IO - os.set_blocking(stdinFDs[1], False) - os.set_blocking(stdoutFDs[0], False) - os.set_blocking(i2cFDs[1], False) - - self.avrOut = stdinFDs[1] - self.avrIn = stdoutFDs[0] - self.i2cOut = i2cFDs[1] - - ioloop = self.ctrl.ioloop - ioloop.add_handler(self.avrOut, self._avr_write_handler, - ioloop.WRITE | ioloop.ERROR) - ioloop.add_handler(self.avrIn, self._avr_read_handler, - ioloop.READ | ioloop.ERROR) - - self.write_enabled = True - - except Exception: - self.close() - self.log.exception('Internal error: Failed to start bbemu') - - - def set_handlers(self, read_cb, write_cb): - if self.read_cb is not None or self.write_cb is not None: - raise Exception('AVR handler already set') - - self.read_cb = read_cb - self.write_cb = write_cb - self._start() - - - def enable_write(self, enable): - if self.avrOut is None: return - - flags = self.ctrl.ioloop.WRITE if enable else 0 - self.ctrl.ioloop.update_handler(self.avrOut, flags) - self.write_enabled = enable - - - def _avr_write(self, data): - try: - length = os.write(self.avrOut, data) - self.continue_write = length and length == len(data) - return length - - except BlockingIOError: pass - except BrokenPipeError: pass - - return 0 - - - def _avr_write_handler(self, fd, events): - if self.avrOut is None: return - - if events & self.ctrl.ioloop.ERROR: - self._start() - return - - try: - while True: - self.continue_write = False - self.write_cb(self._avr_write) - if not self.continue_write: break - - except Exception as e: - self.log.warning('AVR write handler error: %s', - traceback.format_exc()) - - - def _avr_read_handler(self, fd, events): - if self.avrIn is None: return - - if events & self.ctrl.ioloop.ERROR: - self._start() - return - - try: - data = os.read(self.avrIn, 4096) - if data is not None: self.read_cb(data) - - except Exception as e: - self.log.warning('AVR read handler error: %s %s' % - (data, traceback.format_exc())) - - - def i2c_command(self, cmd, byte = None, word = None, block = None): - if byte is not None: data = chr(byte) - elif word is not None: data = word - elif block is not None: data = block - else: data = '' - - try: - if self.i2cOut is not None: - os.write(self.i2cOut, bytes(cmd + data + '\n', 'utf-8')) - - except BrokenPipeError: pass diff --git a/src/py/bbctrl/Camera.py b/src/py/bbctrl/Camera.py index da42be1..d4fc84f 100644 --- a/src/py/bbctrl/Camera.py +++ b/src/py/bbctrl/Camera.py @@ -1,42 +1,9 @@ -#!/usr/bin/env python3 -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import os -import fcntl -import select -import struct -import mmap -import pyudev -import base64 -import socket -import ctypes -from tornado import gen, web, iostream +from tornado import web, iostream import bbctrl +import fcntl +import mmap +import os +import pyudev try: import v4l2 @@ -45,6 +12,7 @@ except: def array_to_string(a): + def until_zero(a): for c in a: if c == 0: return @@ -61,13 +29,17 @@ def fourcc_to_string(i): chr((i >> 24) & 0xff) -def string_to_fourcc(s): return v4l2.v4l2_fourcc(s[0], s[1], s[2], s[3]) +def string_to_fourcc(s): + return v4l2.v4l2_fourcc(s[0], s[1], s[2], s[3]) def format_frame(frame): - frame = [b'--', VideoHandler.boundary.encode('utf8'), b'\r\n', - b'Content-type: image/jpeg\r\n', - b'Content-length: %d\r\n\r\n' % len(frame), frame] + frame = [ + b'--', + VideoHandler.boundary.encode('utf8'), b'\r\n', + b'Content-type: image/jpeg\r\n', + b'Content-length: %d\r\n\r\n' % len(frame), frame + ] return b''.join(frame) @@ -79,13 +51,13 @@ def get_image_resource(path): class VideoDevice(object): - def __init__(self, path = '/dev/video0'): + + def __init__(self, path='/dev/video0'): self.fd = os.open(path, os.O_RDWR | os.O_NONBLOCK | os.O_CLOEXEC) self.buffers = [] - - def fileno(self): return self.fd - + def fileno(self): + return self.fd def get_audio(self): b = v4l2.v4l2_audio() @@ -99,11 +71,11 @@ class VideoDevice(object): l.append((array_to_string(b.name), b.capability, b.mode)) b.index += 1 - except OSError: break + except OSError: + break return l - def get_formats(self): b = v4l2.v4l2_fmtdesc() b.type = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE @@ -120,11 +92,11 @@ class VideoDevice(object): b.index += 1 - except OSError: break + except OSError: + break return l - def get_frame_sizes(self, fourcc): b = v4l2.v4l2_frmsizeenum() b.type = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE @@ -140,18 +112,18 @@ class VideoDevice(object): sizes.append((b.discrete.width, b.discrete.height)) else: - sizes.append((b.stepwise.min_width, b.stepwise.max_width, - b.stepwise.step_width, b.stepwise.min_height, - b.stepwise.max_height, - b.stepwise.step_height)) + sizes.append( + (b.stepwise.min_width, b.stepwise.max_width, + b.stepwise.step_width, b.stepwise.min_height, + b.stepwise.max_height, b.stepwise.step_height)) - b.index += 1 # pylint: disable=no-member + b.index += 1 # pylint: disable=no-member - except OSError: break + except OSError: + break return sizes - def set_format(self, width, height, fourcc): fmt = v4l2.v4l2_format() fmt.type = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE @@ -163,13 +135,12 @@ class VideoDevice(object): fcntl.ioctl(self, v4l2.VIDIOC_S_FMT, fmt) - def create_buffers(self, count): # Create buffers rbuf = v4l2.v4l2_requestbuffers() - rbuf.count = count; - rbuf.type = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE; - rbuf.memory = v4l2.V4L2_MEMORY_MMAP; + rbuf.count = count + rbuf.type = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE + rbuf.memory = v4l2.V4L2_MEMORY_MMAP fcntl.ioctl(self, v4l2.VIDIOC_REQBUFS, rbuf) @@ -182,15 +153,16 @@ class VideoDevice(object): fcntl.ioctl(self, v4l2.VIDIOC_QUERYBUF, buf) # Mem map buffer - mm = mmap.mmap(self.fileno(), buf.length, mmap.MAP_SHARED, + mm = mmap.mmap(self.fileno(), + buf.length, + mmap.MAP_SHARED, mmap.PROT_READ | mmap.PROT_WRITE, - offset = buf.m.offset) + offset=buf.m.offset) self.buffers.append(mm) # Queue the buffer for capture fcntl.ioctl(self, v4l2.VIDIOC_QBUF, buf) - def _dqbuf(self): buf = v4l2.v4l2_buffer() buf.type = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE @@ -199,11 +171,9 @@ class VideoDevice(object): return buf - def _qbuf(self, buf): fcntl.ioctl(self, v4l2.VIDIOC_QBUF, buf) - def read_frame(self): buf = self._dqbuf() mm = self.buffers[buf.index] @@ -214,16 +184,15 @@ class VideoDevice(object): return frame - - def flush_frame(self): self._qbuf(self._dqbuf()) - + def flush_frame(self): + self._qbuf(self._dqbuf()) def get_info(self): caps = v4l2.v4l2_capability() fcntl.ioctl(self, v4l2.VIDIOC_QUERYCAP, caps) - caps._driver = array_to_string(caps.driver) - caps._card = array_to_string(caps.card) + caps._driver = array_to_string(caps.driver) + caps._card = array_to_string(caps.card) caps._bus_info = array_to_string(caps.bus_info) l = [] @@ -251,33 +220,31 @@ class VideoDevice(object): return caps - def set_fps(self, fps): setfps = v4l2.v4l2_streamparm() - setfps.type = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE; + setfps.type = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE setfps.parm.capture.timeperframe.numerator = 1 setfps.parm.capture.timeperframe.denominator = fps fcntl.ioctl(self, v4l2.VIDIOC_S_PARM, setfps) - def start(self): buf_type = v4l2.v4l2_buf_type(v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE) fcntl.ioctl(self, v4l2.VIDIOC_STREAMON, buf_type) - def stop(self): buf_type = v4l2.v4l2_buf_type(v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE) fcntl.ioctl(self, v4l2.VIDIOC_STREAMOFF, buf_type) - def close(self): if self.fd is None: return try: os.close(self.fd) - finally: self.fd = None + finally: + self.fd = None class Camera(object): + def __init__(self, ioloop, args, log): self.ioloop = ioloop self.log = log.get('Camera') @@ -305,11 +272,10 @@ class Camera(object): # Get notifications of camera (un)plug events self.udevCtx = pyudev.Context() self.udevMon = pyudev.Monitor.from_netlink(self.udevCtx) - self.udevMon.filter_by(subsystem = 'video4linux') + self.udevMon.filter_by(subsystem='video4linux') ioloop.add_handler(self.udevMon, self._udev_handler, ioloop.READ) self.udevMon.start() - def _udev_handler(self, fd, events): action, device = self.udevMon.receive_device() if device is None or self.dev is not None: return @@ -324,7 +290,6 @@ class Camera(object): self.have_camera = False self.close() - def _send_frame(self, frame): if not len(self.clients): return @@ -337,14 +302,14 @@ class Camera(object): except Exception as e: self.log.warning('Failed to write frame to client: %s' % e) - def _fd_handler(self, fd, events): try: if len(self.clients): frame = self.dev.read_frame() self._send_frame(frame) - else: self.dev.flush_frame() + else: + self.dev.flush_frame() except Exception as e: if isinstance(e, BlockingIOError): return @@ -353,7 +318,6 @@ class Camera(object): self.ioloop.remove_handler(fd) self.close() - def _update_client_image(self): if self.have_camera and not self.overtemp: return if self.overtemp and self.have_camera: img = 'overtemp' @@ -361,7 +325,6 @@ class Camera(object): if len(self.clients): self.clients[-1].write_img(img) - def open(self, path): try: self._update_client_image() @@ -376,9 +339,9 @@ class Camera(object): if caps.capabilities & v4l2.V4L2_CAP_VIDEO_CAPTURE == 0: raise Exception('Video capture not supported.') - fourcc = string_to_fourcc(self.fourcc) + fourcc = string_to_fourcc(self.fourcc) formats = self.dev.get_formats() - sizes = self.dev.get_frame_sizes(fourcc) + sizes = self.dev.get_frame_sizes(fourcc) self.log.info('Formats: %s', formats) self.log.info('Sizes: %s', sizes) @@ -391,7 +354,7 @@ class Camera(object): if not hasFormat: raise Exception(self.fourcc + ' video format not supported.') - self.dev.set_format(self.width, self.height, fourcc = fourcc) + self.dev.set_format(self.width, self.height, fourcc=fourcc) self.dev.set_fps(self.fps) self.dev.create_buffers(4) self.dev.start() @@ -401,22 +364,20 @@ class Camera(object): self.log.info('Opened camera ' + path) - except Exception as e: self.log.warning('While loading camera: %s' % e) self._close_dev() - def _close_dev(self): if self.dev is None: return try: self.dev.close() - except Exception as e: self.log.warning('While closing camera: %s', e) + except Exception as e: + self.log.warning('While closing camera: %s', e) self.dev = None - - def close(self, overtemp = False): + def close(self, overtemp=False): self._update_client_image() if self.dev is None: return @@ -424,14 +385,17 @@ class Camera(object): self.ioloop.remove_handler(self.dev) try: self.dev.stop() - except: pass + except: + pass self._close_dev() self.log.info('Closed camera') - except: self.log.exception('Internal error: Exception while closing camera') - finally: self.dev = None - + except: + self.log.exception( + 'Internal error: Exception while closing camera') + finally: + self.dev = None def add_client(self, client): self.log.info('Adding camera client: %d' % len(self.clients)) @@ -442,13 +406,12 @@ class Camera(object): self.clients.append(client) self._update_client_image() - def remove_client(self, client): self.log.info('Removing camera client') try: self.clients.remove(client) - except: pass - + except: + pass def set_overtemp(self, overtemp): if self.overtemp == overtemp: return @@ -458,36 +421,32 @@ class Camera(object): elif self.path is not None: self.open(self.path) - class VideoHandler(web.RequestHandler): boundary = '-f36a3a39e5c955484390e0e3a6b031d1---' - def __init__(self, app, request, **kwargs): super().__init__(app, request, **kwargs) self.camera = app.camera - @web.asynchronous def get(self): self.request.connection.stream.max_write_buffer_size = 10000 - self.set_header('Cache-Control', 'no-store, no-cache, must-revalidate, ' - 'pre-check=0, post-check=0, max-age=0') + self.set_header( + 'Cache-Control', 'no-store, no-cache, must-revalidate, ' + 'pre-check=0, post-check=0, max-age=0') self.set_header('Connection', 'close') - self.set_header('Content-Type', 'multipart/x-mixed-replace;boundary=' + - self.boundary) + self.set_header('Content-Type', + 'multipart/x-mixed-replace;boundary=' + self.boundary) self.set_header('Expires', 'Mon, 3 Jan 2000 12:34:56 GMT') self.set_header('Pragma', 'no-cache') if self.camera is None: self.write_img('offline') else: self.camera.add_client(self) - def write_img(self, name): self.write_frame_twice(get_image_resource('http/images/%s.jpg' % name)) - def write_frame(self, frame): # Don't allow too many frames to queue up min_size = len(frame) * 2 @@ -499,12 +458,11 @@ class VideoHandler(web.RequestHandler): self.flush() except iostream.StreamBufferFullError: - pass # Drop frame if buffer is full - + pass # Drop frame if buffer is full def write_frame_twice(self, frame): self.write_frame(frame) self.write_frame(frame) - - def on_connection_close(self): self.camera.remove_client(self) + def on_connection_close(self): + self.camera.remove_client(self) diff --git a/src/py/bbctrl/Cmd.py b/src/py/bbctrl/Cmd.py index 88c111b..df494c1 100644 --- a/src/py/bbctrl/Cmd.py +++ b/src/py/bbctrl/Cmd.py @@ -1,64 +1,35 @@ -#!/usr/bin/env python3 - -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import struct import base64 import json +import struct # Keep this in sync with AVR code command.def -SET = '$' -SET_SYNC = '#' -MODBUS_READ = 'm' +SET = '$' +SET_SYNC = '#' +MODBUS_READ = 'm' MODBUS_WRITE = 'M' -SEEK = 's' -SET_AXIS = 'a' -LINE = 'l' -SYNC_SPEED = '%' -SPEED = 'p' -INPUT = 'I' -DWELL = 'd' -PAUSE = 'P' -STOP = 'S' -UNPAUSE = 'U' -JOG = 'j' -REPORT = 'r' -REBOOT = 'R' -RESUME = 'c' -ESTOP = 'E' -SHUTDOWN = 'X' -CLEAR = 'C' -FLUSH = 'F' -DUMP = 'D' -HELP = 'h' +SEEK = 's' +SET_AXIS = 'a' +LINE = 'l' +SYNC_SPEED = '%' +SPEED = 'p' +INPUT = 'I' +DWELL = 'd' +PAUSE = 'P' +STOP = 'S' +UNPAUSE = 'U' +JOG = 'j' +REPORT = 'r' +REBOOT = 'R' +RESUME = 'c' +ESTOP = 'E' +SHUTDOWN = 'X' +CLEAR = 'C' +FLUSH = 'F' +DUMP = 'D' +HELP = 'h' SEEK_ACTIVE = 1 << 0 -SEEK_ERROR = 1 << 1 +SEEK_ERROR = 1 << 1 def encode_float(x): @@ -95,9 +66,16 @@ def set_float(name, value): return SET_SYNC + '%s=:%s' % (name, encode_float(value)) -def modbus_read(addr): return MODBUS_READ + '%d' % addr -def modbus_write(addr, value): return MODBUS_WRITE + '%d=%d' % (addr, value) -def set_axis(axis, position): return SET_AXIS + axis + encode_float(position) +def modbus_read(addr): + return MODBUS_READ + '%d' % addr + + +def modbus_write(addr, value): + return MODBUS_WRITE + '%d=%d' % (addr, value) + + +def set_axis(axis, position): + return SET_AXIS + axis + encode_float(position) def line(target, exitVel, maxAccel, maxJerk, times, speeds): @@ -111,7 +89,7 @@ def line(target, exitVel, maxAccel, maxJerk, times, speeds): # S-Curve time parameters for i in range(7): if times[i]: - cmd += str(i) + encode_float(times[i] / 60000) # to mins + cmd += str(i) + encode_float(times[i] / 60000) # to mins # Speeds for dist, speed in speeds: @@ -120,7 +98,8 @@ def line(target, exitVel, maxAccel, maxJerk, times, speeds): return cmd -def speed(value): return SPEED + encode_float(value) +def speed(value): + return SPEED + encode_float(value) def sync_speed(dist, speed): @@ -135,28 +114,29 @@ def input(port, mode, timeout): if port == 'digital-in-1': type, index = 'd', 1 if port == 'digital-in-2': type, index = 'd', 2 if port == 'digital-in-3': type, index = 'd', 3 - if port == 'analog-in-0': type, index = 'a', 0 - if port == 'analog-in-1': type, index = 'a', 1 - if port == 'analog-in-2': type, index = 'a', 2 - if port == 'analog-in-3': type, index = 'a', 3 + if port == 'analog-in-0': type, index = 'a', 0 + if port == 'analog-in-1': type, index = 'a', 1 + if port == 'analog-in-2': type, index = 'a', 2 + if port == 'analog-in-3': type, index = 'a', 3 # Mode if mode == 'immediate': m = 0 - if mode == 'rise': m = 1 - if mode == 'fall': m = 2 - if mode == 'high': m = 3 - if mode == 'low': m = 4 + if mode == 'rise': m = 1 + if mode == 'fall': m = 2 + if mode == 'high': m = 3 + if mode == 'low': m = 4 return '%s%s%d%d%s' % (INPUT, type, index, m, encode_float(timeout)) def output(port, value): - if port == 'mist': return '#1oa=' + ('1' if value else '0') + if port == 'mist': return '#1oa=' + ('1' if value else '0') if port == 'flood': return '#2oa=' + ('1' if value else '0') raise Exception('Unsupported output "%s"' % port) -def dwell(seconds): return DWELL + encode_float(seconds) +def dwell(seconds): + return DWELL + encode_float(seconds) def pause(type): @@ -168,7 +148,8 @@ def pause(type): return '%s%d' % (PAUSE, type) -def jog(axes): return JOG + encode_axes(axes) +def jog(axes): + return JOG + encode_axes(axes) def seek(switch, active, error): @@ -177,7 +158,7 @@ def seek(switch, active, error): flags = 0 if active: flags |= SEEK_ACTIVE - if error: flags |= SEEK_ERROR + if error: flags |= SEEK_ERROR cmd += chr(flags + ord('0')) return cmd @@ -213,7 +194,6 @@ def decode_command(cmd): if name in 'xyzabcuvw': data[name] = value - elif cmd[0] == SEEK: data['type'] = 'seek' @@ -225,9 +205,9 @@ def decode_command(cmd): elif cmd[0] == LINE: data['type'] = 'line' - data['exit-vel'] = decode_float(cmd[1:7]) + data['exit-vel'] = decode_float(cmd[1:7]) data['max-accel'] = decode_float(cmd[7:13]) - data['max-jerk'] = decode_float(cmd[13:19]) + data['max-jerk'] = decode_float(cmd[13:19]) data['target'] = {} data['times'] = [0] * 7 @@ -244,16 +224,24 @@ def decode_command(cmd): elif cmd[0] == SYNC_SPEED: data['type'] = 'speed' data['offset'] = decode_float(cmd[1:7]) - data['speed'] = decode_float(cmd[7:13]) + data['speed'] = decode_float(cmd[7:13]) - elif cmd[0] == REPORT: data['type'] = 'report' - elif cmd[0] == PAUSE: data['type'] = 'pause' - elif cmd[0] == UNPAUSE: data['type'] = 'unpause' - elif cmd[0] == ESTOP: data['type'] = 'estop' - elif cmd[0] == SHUTDOWN: data['type'] = 'shutdown' - elif cmd[0] == CLEAR: data['type'] = 'clear' - elif cmd[0] == FLUSH: data['type'] = 'flush' - elif cmd[0] == RESUME: data['type'] = 'resume' + elif cmd[0] == REPORT: + data['type'] = 'report' + elif cmd[0] == PAUSE: + data['type'] = 'pause' + elif cmd[0] == UNPAUSE: + data['type'] = 'unpause' + elif cmd[0] == ESTOP: + data['type'] = 'estop' + elif cmd[0] == SHUTDOWN: + data['type'] = 'shutdown' + elif cmd[0] == CLEAR: + data['type'] = 'clear' + elif cmd[0] == FLUSH: + data['type'] = 'flush' + elif cmd[0] == RESUME: + data['type'] = 'resume' return data diff --git a/src/py/bbctrl/Comm.py b/src/py/bbctrl/Comm.py index b7dc27e..cbed8fd 100644 --- a/src/py/bbctrl/Comm.py +++ b/src/py/bbctrl/Comm.py @@ -1,65 +1,33 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import serial -import json -import time -import traceback from collections import deque - -import bbctrl import bbctrl.Cmd as Cmd - +import json +import traceback # Must be kept in sync with drv8711.h -DRV8711_STATUS_OTS_bm = 1 << 0 -DRV8711_STATUS_AOCP_bm = 1 << 1 -DRV8711_STATUS_BOCP_bm = 1 << 2 -DRV8711_STATUS_APDF_bm = 1 << 3 -DRV8711_STATUS_BPDF_bm = 1 << 4 -DRV8711_STATUS_UVLO_bm = 1 << 5 -DRV8711_STATUS_STD_bm = 1 << 6 +DRV8711_STATUS_OTS_bm = 1 << 0 +DRV8711_STATUS_AOCP_bm = 1 << 1 +DRV8711_STATUS_BOCP_bm = 1 << 2 +DRV8711_STATUS_APDF_bm = 1 << 3 +DRV8711_STATUS_BPDF_bm = 1 << 4 +DRV8711_STATUS_UVLO_bm = 1 << 5 +DRV8711_STATUS_STD_bm = 1 << 6 DRV8711_STATUS_STDLAT_bm = 1 << 7 -DRV8711_COMM_ERROR_bm = 1 << 8 +DRV8711_COMM_ERROR_bm = 1 << 8 # Ignoring stall and stall latch flags for now DRV8711_MASK = ~(DRV8711_STATUS_STD_bm | DRV8711_STATUS_STDLAT_bm) def _driver_flags_to_string(flags): - if DRV8711_STATUS_OTS_bm & flags: yield 'over temp' - if DRV8711_STATUS_AOCP_bm & flags: yield 'over current a' - if DRV8711_STATUS_BOCP_bm & flags: yield 'over current b' - if DRV8711_STATUS_APDF_bm & flags: yield 'driver fault a' - if DRV8711_STATUS_BPDF_bm & flags: yield 'driver fault b' - if DRV8711_STATUS_UVLO_bm & flags: yield 'undervoltage' - if DRV8711_STATUS_STD_bm & flags: yield 'stall' + if DRV8711_STATUS_OTS_bm & flags: yield 'over temp' + if DRV8711_STATUS_AOCP_bm & flags: yield 'over current a' + if DRV8711_STATUS_BOCP_bm & flags: yield 'over current b' + if DRV8711_STATUS_APDF_bm & flags: yield 'driver fault a' + if DRV8711_STATUS_BPDF_bm & flags: yield 'driver fault b' + if DRV8711_STATUS_UVLO_bm & flags: yield 'undervoltage' + if DRV8711_STATUS_STD_bm & flags: yield 'stall' if DRV8711_STATUS_STDLAT_bm & flags: yield 'stall latch' - if DRV8711_COMM_ERROR_bm & flags: yield 'comm error' + if DRV8711_COMM_ERROR_bm & flags: yield 'comm error' def driver_flags_to_string(flags): @@ -67,6 +35,7 @@ def driver_flags_to_string(flags): class Comm(object): + def __init__(self, ctrl, avr): self.ctrl = ctrl self.avr = avr @@ -79,41 +48,38 @@ class Comm(object): avr.set_handlers(self._read, self._write) self._poll_cb(False) + def comm_next(self): + raise Exception('Not implemented') - def comm_next(self): raise Exception('Not implemented') - def comm_error(self): raise Exception('Not implemented') + def comm_error(self): + raise Exception('Not implemented') + def is_active(self): + return len(self.queue) or self.command is not None - def is_active(self): return len(self.queue) or self.command is not None - - - def i2c_command(self, cmd, byte = None, word = None, block = None): + def i2c_command(self, cmd, byte=None, word=None, block=None): self.log.info('I2C: %s b=%s w=%s d=%s' % (cmd, byte, word, block)) self.avr.i2c_command(cmd, byte, word, block) - - def flush(self): self.avr.enable_write(True) - + def flush(self): + self.avr.enable_write(True) def _load_next_command(self, cmd): self.log.info('< ' + json.dumps(cmd).strip('"')) self.command = bytes(cmd.strip() + '\n', 'utf-8') - - def resume(self): self.queue_command(Cmd.RESUME) - + def resume(self): + self.queue_command(Cmd.RESUME) def queue_command(self, cmd): self.queue.append(cmd) self.flush() - - def _poll_cb(self, now = True): + def _poll_cb(self, now=True): # Checks periodically for new commands from planner via comm_next() if now: self.flush() self.ctrl.ioloop.call_later(1, self._poll_cb) - def _write(self, write_cb): # Finish writing current command if self.command is not None: @@ -125,25 +91,25 @@ class Comm(object): raise e self.command = self.command[count:] - if len(self.command): return # There's more + if len(self.command): return # There's more self.command = None # Load next command from queue - if len(self.queue): self._load_next_command(self.queue.popleft()) + if len(self.queue): + self._load_next_command(self.queue.popleft()) - # Load next command from callback + # Load next command from callback else: - cmd = self.comm_next() # pylint: disable=assignment-from-no-return + cmd = self.comm_next() # pylint: disable=assignment-from-no-return - if cmd is None: self.avr.enable_write(False) # Stop writing + if cmd is None: self.avr.enable_write(False) # Stop writing else: self._load_next_command(cmd) - def _update_vars(self, msg): try: self.ctrl.state.set_machine_vars(msg['variables']) self.ctrl.configure() - self.queue_command(Cmd.DUMP) # Refresh all vars + self.queue_command(Cmd.DUMP) # Refresh all vars # Set axis positions for axis in 'xyzabc': @@ -154,16 +120,15 @@ class Comm(object): self.log.warning('AVR reload failed: %s', traceback.format_exc()) self.ctrl.ioloop.call_later(1, self.connect) - def _log_msg(self, msg): level = msg.get('level', 'info') where = msg.get('where') msg = msg['msg'] - if level == 'info': self.log.info(msg, where = where) - elif level == 'debug': self.log.debug(msg, where = where) - elif level == 'warning': self.log.warning(msg, where = where) - elif level == 'error': self.log.error(msg, where = where) + if level == 'info': self.log.info(msg, where=where) + elif level == 'debug': self.log.debug(msg, where=where) + elif level == 'warning': self.log.warning(msg, where=where) + elif level == 'error': self.log.error(msg, where=where) if level == 'error': self.comm_error() @@ -171,7 +136,6 @@ class Comm(object): if level == 'warning' and 'code' in msg and msg['code'] == 11: self.comm_error() - def _log_motor_flags(self, update): for motor in range(3): var = '%ddf' % motor @@ -185,17 +149,15 @@ class Comm(object): flags = driver_flags_to_string(flags) self.log.info('Motor %d flags: %s' % (motor, flags)) - def _update_state(self, update): self.ctrl.state.update(update) - if 'xx' in update: # State change - self.ctrl.ready() # We've received data from AVR - self.flush() # May have more data to send now + if 'xx' in update: # State change + self.ctrl.ready() # We've received data from AVR + self.flush() # May have more data to send now self._log_motor_flags(update) - def _read(self, data): self.in_buf += data.decode('utf-8') @@ -227,29 +189,25 @@ class Comm(object): else: self._update_state(msg) - def estop(self): if self.ctrl.state.get('xx', '') != 'ESTOPPED': self.i2c_command(Cmd.ESTOP) - def clear(self): if self.ctrl.state.get('xx', '') == 'ESTOPPED': self.i2c_command(Cmd.CLEAR) - def pause(self): - self.i2c_command(Cmd.PAUSE, byte = ord('0')) # User pause - - - def reboot(self): self.queue_command(Cmd.REBOOT) + self.i2c_command(Cmd.PAUSE, byte=ord('0')) # User pause + def reboot(self): + self.queue_command(Cmd.REBOOT) def connect(self): try: # Resume once current queue of GCode commands has flushed self.queue_command(Cmd.RESUME) - self.queue_command(Cmd.HELP) # Load AVR commands and variables + self.queue_command(Cmd.HELP) # Load AVR commands and variables except Exception as e: self.log.warning('Connect failed: %s', e) diff --git a/src/py/bbctrl/CommandQueue.py b/src/py/bbctrl/CommandQueue.py index a58eeb6..0524645 100644 --- a/src/py/bbctrl/CommandQueue.py +++ b/src/py/bbctrl/CommandQueue.py @@ -1,39 +1,14 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import bbctrl from collections import deque +import bbctrl # 16-bit less with wrap around -def id_less(a, b): return (1 << 15) < (a - b) & ((1 << 16) - 1) +def id_less(a, b): + return (1 << 15) < (a - b) & ((1 << 16) - 1) class CommandQueue(): + def __init__(self, ctrl): self.log = ctrl.log.get('CmdQ') self.log.set_level(bbctrl.log.WARNING) @@ -42,23 +17,20 @@ class CommandQueue(): self.releaseID = 0 self.q = deque() - - def is_active(self): return len(self.q) - + def is_active(self): + return len(self.q) def clear(self): self.lastEnqueueID = 0 self.releaseID = 0 self.q.clear() - def enqueue(self, id, cb, *args, **kwargs): self.log.info('add(#%d) releaseID=%d', id, self.releaseID) self.lastEnqueueID = id self.q.append([id, cb, args, kwargs]) self._release() - def _release(self): while len(self.q): id, cb, args, kwargs = self.q[0] @@ -72,9 +44,8 @@ class CommandQueue(): try: if cb is not None: cb(*args, **kwargs) except Exception: - self.log.exception('Internal error: Command queue callback error') - - + self.log.exception( + 'Internal error: Command queue callback error') def release(self, id): if id and not id_less(self.releaseID, id): diff --git a/src/py/bbctrl/Config.py b/src/py/bbctrl/Config.py index 2a16b56..3395189 100644 --- a/src/py/bbctrl/Config.py +++ b/src/py/bbctrl/Config.py @@ -1,34 +1,7 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import os -import json -import pkg_resources from pkg_resources import Requirement, resource_filename +import json +import os +import pkg_resources def get_resource(path): @@ -36,6 +9,7 @@ def get_resource(path): class Config(object): + def __init__(self, ctrl): self.ctrl = ctrl self.log = ctrl.log.get('Config') @@ -46,24 +20,29 @@ class Config(object): self.version = pkg_resources.require('bbctrl')[0].version # Load config template - with open(get_resource('http/config-template.json'), 'r', - encoding = 'utf-8') as f: + with open(get_resource('http/config-template.json'), + 'r', + encoding='utf-8') as f: self.template = json.load(f) - except Exception: self.log.exception('Internal error: Failed to load config template') - + except Exception: + self.log.exception( + 'Internal error: Failed to load config template') def load(self): path = self.ctrl.get_path('config.json') try: if os.path.exists(path): - with open(path, 'r') as f: config = json.load(f) - else: config = {'version': self.version} + with open(path, 'r') as f: + config = json.load(f) + else: + config = {'version': self.version} try: self._upgrade(config) - except Exception: self.log.exception('Internal error: Failed to upgrade config') + except Exception: + self.log.exception('Internal error: Failed to upgrade config') except Exception as e: self.log.warning('%s', e) @@ -72,15 +51,12 @@ class Config(object): self._defaults(config) return config - def reload(self): self._update(self.load(), True) - - def get(self, name, default = None): + def get(self, name, default=None): return self.values.get(name, default) - def save(self, config): self._upgrade(config) self._update(config, False) @@ -93,21 +69,19 @@ class Config(object): self.ctrl.preplanner.invalidate_all() self.log.info('Saved') - def reset(self): if os.path.exists('config.json'): os.unlink('config.json') self.reload() self.ctrl.preplanner.invalidate_all() - def _valid_value(self, template, value): type = template['type'] try: - if type == 'int': value = int(value) + if type == 'int': value = int(value) if type == 'float': value = float(value) - if type == 'text': value = str(value) - if type == 'bool': value = bool(value) + if type == 'text': value = str(value) + if type == 'bool': value = bool(value) except: return False @@ -116,11 +90,10 @@ class Config(object): return True - def __defaults(self, config, name, template): if 'type' in template: - if (not name in config or - not self._valid_value(template, config[name])): + if (not name in config + or not self._valid_value(template, config[name])): config[name] = template['default'] elif 'max' in template and template['max'] < config[name]: @@ -142,21 +115,21 @@ class Config(object): for name, tmpl in template.items(): self.__defaults(config, name, tmpl) - def _defaults(self, config): for name, tmpl in self.template.items(): if not 'type' in tmpl: if not name in config: config[name] = {} conf = config[name] - else: conf = config + else: + conf = config self.__defaults(conf, name, tmpl) - def _upgrade(self, config): version = config['version'] - version = version.split('b')[0] # Strip off any "beta" suffix - version = tuple(map(int, version.split('.'))) # Break it into a tuple of integers + version = version.split('b')[0] # Strip off any "beta" suffix + version = tuple(map( + int, version.split('.'))) # Break it into a tuple of integers if version < (1, 0, 7): config['settings']['max-deviation'] = 0.001 @@ -186,21 +159,24 @@ class Config(object): config['settings']['junction-accel'] = 200000 if version < (1, 0, 9): - with open(get_resource('http/onefinity_defaults.json'), 'r', encoding = 'utf-8') as f: + with open(get_resource('http/onefinity_defaults.json'), + 'r', + encoding='utf-8') as f: defaults = json.load(f) - config['selected-tool-settings'] = defaults['selected-tool-settings']; + config['selected-tool-settings'] = defaults[ + 'selected-tool-settings'] config['version'] = self.version.split('b')[0] config['full_version'] = self.version - def _encode(self, name, index, config, tmpl, with_defaults): # Handle category if not 'type' in tmpl: for name, entry in tmpl.items(): if 'type' in entry and config is not None: conf = config.get(name, None) - else: conf = config + else: + conf = config self._encode(name, index, conf, entry, with_defaults) return @@ -223,7 +199,8 @@ class Config(object): if not name in self.values: self.values[name] = {} self.values[name][index] = value - else: self.values[name] = value + else: + self.values[name] = value # Update state variable if not 'code' in tmpl: return @@ -237,7 +214,6 @@ class Config(object): self.ctrl.state.config(index + tmpl['code'], value) - def _update(self, config, with_defaults): for name, tmpl in self.template.items(): conf = config.get(name, None) diff --git a/src/py/bbctrl/Ctrl.py b/src/py/bbctrl/Ctrl.py index 9a46323..f9b8247 100644 --- a/src/py/bbctrl/Ctrl.py +++ b/src/py/bbctrl/Ctrl.py @@ -1,47 +1,23 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import os -import time import bbctrl +import os class Ctrl(object): + def __init__(self, args, ioloop, id): self.args = args self.ioloop = bbctrl.IOLoop(ioloop) self.id = id - self.timeout = None # Used in demo mode + self.timeout = None # Used in demo mode - if id and not os.path.exists(id): os.mkdir(id) + if id and not os.path.exists(id): + os.mkdir(id) # Start log - if args.demo: log_path = self.get_path(filename = 'bbctrl.log') - else: log_path = args.log + if args.demo: + log_path = self.get_path(filename='bbctrl.log') + else: + log_path = args.log self.log = bbctrl.log.Log(args, self.ioloop, log_path) self.state = bbctrl.State(self) @@ -50,65 +26,56 @@ class Ctrl(object): self.log.get('Ctrl').info('Starting %s' % self.id) try: - if args.demo: self.avr = bbctrl.AVREmu(self) - else: self.avr = bbctrl.AVR(self) + self.avr = bbctrl.AVR(self) self.i2c = bbctrl.I2C(args.i2c_port, args.demo) - self.lcd = bbctrl.LCD(self) self.mach = bbctrl.Mach(self, self.avr) self.preplanner = bbctrl.Preplanner(self) - if not args.demo: self.jog = bbctrl.Jog(self) + if not args.demo: + self.jog = bbctrl.Jog(self) self.pwr = bbctrl.Pwr(self) self.mach.connect() - self.lcd.add_new_page(bbctrl.MainLCDPage(self)) - self.lcd.add_new_page(bbctrl.IPLCDPage(self.lcd)) - os.environ['GCODE_SCRIPT_PATH'] = self.get_upload() - except Exception: self.log.get('Ctrl').exception('Internal error: Control initialization failed') - - - def __del__(self): print('Ctrl deleted') + except Exception: + self.log.get('Ctrl').exception( + 'Internal error: Control initialization failed') + def __del__(self): + print('Ctrl deleted') def clear_timeout(self): - if self.timeout is not None: self.ioloop.remove_timeout(self.timeout) + if self.timeout is not None: + self.ioloop.remove_timeout(self.timeout) self.timeout = None - def set_timeout(self, cb, *args, **kwargs): self.clear_timeout() t = self.args.client_timeout self.timeout = self.ioloop.call_later(t, cb, *args, **kwargs) - - def get_path(self, dir = None, filename = None): + def get_path(self, dir=None, filename=None): path = './' + self.id if self.id else '.' path = path if dir is None else (path + '/' + dir) return path if filename is None else (path + '/' + filename) - - def get_upload(self, filename = None): + def get_upload(self, filename=None): return self.get_path('upload', filename) - - def get_plan(self, filename = None): + def get_plan(self, filename=None): return self.get_path('plans', filename) - def configure(self): # Indirectly configures state via calls to config() and the AVR self.config.reload() self.state.init() - def ready(self): # This is used to synchronize the start of the preplanner self.preplanner.start() - def close(self): self.log.get('Ctrl').info('Closing %s' % self.id) self.ioloop.close() diff --git a/src/py/bbctrl/FileHandler.py b/src/py/bbctrl/FileHandler.py index ad6a24e..f267cba 100644 --- a/src/py/bbctrl/FileHandler.py +++ b/src/py/bbctrl/FileHandler.py @@ -1,52 +1,44 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import os +from tornado import gen +from tornado.escape import url_unescape +from tornado.web import HTTPError import bbctrl import glob -import html -from tornado import gen -from tornado.web import HTTPError +import os +import tempfile +import tornado def safe_remove(path): try: os.unlink(path) - except OSError: pass + except OSError: + pass +@tornado.web.stream_request_body class FileHandler(bbctrl.APIHandler): - def prepare(self): pass + def prepare(self): + if self.request.method == 'PUT': + self.request.connection.set_max_body_size(2**30) + + filename = self.request.path.split('/')[-1] + self.uploadFilename = url_unescape(filename) \ + .replace('\\', '/') \ + .replace('#', '-') \ + .replace('?', '-') + + self.uploadFile = tempfile.NamedTemporaryFile("wb") + + def data_received(self, data): + if self.request.method == 'PUT': + self.uploadFile.write(data) def delete_ok(self, filename): if not filename: # Delete everything - for path in glob.glob(self.get_upload('*')): safe_remove(path) + for path in glob.glob(self.get_upload('*')): + safe_remove(path) self.get_ctrl().preplanner.delete_all_plans() self.get_ctrl().state.clear_files() @@ -57,26 +49,29 @@ class FileHandler(bbctrl.APIHandler): self.get_ctrl().preplanner.delete_plans(filename) self.get_ctrl().state.remove_file(filename) - def put_ok(self, *args): - gcode = self.request.files['gcode'][0] - filename = os.path.basename(gcode['filename'].replace('\\', '/')) - filename = filename.replace('#', '-').replace('?', '-') + if not os.path.exists(self.get_upload()): + os.mkdir(self.get_upload()) - if not os.path.exists(self.get_upload()): os.mkdir(self.get_upload()) + filename = self.get_upload(self.uploadFilename).encode('utf8') + safe_remove(filename) + os.link(self.uploadFile.name, filename) - with open(self.get_upload(filename).encode('utf8'), 'wb') as f: - f.write(gcode['body']) - os.sync() + self.uploadFile.close() - self.get_ctrl().preplanner.invalidate(filename) - self.get_ctrl().state.add_file(filename) - self.get_log('FileHandler').info('GCode received: ' + filename) + del (self.uploadFile) + self.get_ctrl().preplanner.invalidate(self.uploadFilename) + self.get_ctrl().state.add_file(self.uploadFilename) + self.get_log('FileHandler').info('GCode received: ' + + self.uploadFilename) + + del (self.uploadFilename) @gen.coroutine def get(self, filename): - if not filename: raise HTTPError(400, 'Missing filename') + if not filename: + raise HTTPError(400, 'Missing filename') filename = os.path.basename(filename) try: @@ -84,6 +79,7 @@ class FileHandler(bbctrl.APIHandler): self.write(f.read()) except Exception: self.get_ctrl().state.select_file('') - raise HTTPError(400, "Unable to read file - doesn't appear to be GCode.") + raise HTTPError( + 400, "Unable to read file - doesn't appear to be GCode.") self.get_ctrl().state.select_file(filename) diff --git a/src/py/bbctrl/I2C.py b/src/py/bbctrl/I2C.py index a97a528..d5889d4 100644 --- a/src/py/bbctrl/I2C.py +++ b/src/py/bbctrl/I2C.py @@ -1,30 +1,3 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - import errno try: @@ -37,12 +10,12 @@ except: class I2C(object): + def __init__(self, port, disabled): self.port = port self.i2c_bus = None self.disabled = disabled or smbus is None - def connect(self): if self.disabled: return if self.i2c_bus is None: @@ -54,7 +27,6 @@ class I2C(object): if e.errno == errno.ENOENT: self.disabled = True else: raise type(e)('I2C failed to open device: %s' % e) - def read_word(self, addr): self.connect() if self.disabled: return @@ -67,8 +39,7 @@ class I2C(object): self.i2c_bus = None raise type(e)('I2C read word failed: %s' % e) - - def write(self, addr, cmd, byte = None, word = None, block = None): + def write(self, addr, cmd, byte=None, word=None, block=None): self.connect() if self.disabled: return @@ -83,7 +54,8 @@ class I2C(object): if isinstance(block, str): block = list(map(ord, block)) self.i2c_bus.write_i2c_block_data(addr, cmd, block) - else: self.i2c_bus.write_byte(addr, cmd) + else: + self.i2c_bus.write_byte(addr, cmd) except IOError as e: self.i2c_bus.close() diff --git a/src/py/bbctrl/IOLoop.py b/src/py/bbctrl/IOLoop.py index c9c614b..e4ec69f 100644 --- a/src/py/bbctrl/IOLoop.py +++ b/src/py/bbctrl/IOLoop.py @@ -1,35 +1,8 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - import tornado.ioloop -import bbctrl class CB(object): + def __init__(self, ioloop, delay, cb, *args, **kwargs): self.ioloop = ioloop self.cb = cb @@ -49,45 +22,41 @@ class IOLoop(object): WRITE = tornado.ioloop.IOLoop.WRITE ERROR = tornado.ioloop.IOLoop.ERROR - def __init__(self, ioloop): self.ioloop = ioloop self.fds = set() self.handles = set() self.callbacks = {} - def close(self): - for fd in list(self.fds): self.ioloop.remove_handler(fd) - for h in list(self.handles): self.ioloop.remove_timeout(h) - for h in list(self.callbacks): self.ioloop.remove_timeout(h) - + for fd in list(self.fds): + self.ioloop.remove_handler(fd) + for h in list(self.handles): + self.ioloop.remove_timeout(h) + for h in list(self.callbacks): + self.ioloop.remove_timeout(h) def add_handler(self, fd, handler, events): self.ioloop.add_handler(fd, handler, events) if hasattr(fd, 'fileno'): fd = fd.fileno() self.fds.add(fd) - def remove_handler(self, h): self.ioloop.remove_handler(h) if hasattr(h, 'fileno'): h = h.fileno() self.fds.remove(h) - - def update_handler(self, fd, events): self.ioloop.update_handler(fd, events) - + def update_handler(self, fd, events): + self.ioloop.update_handler(fd, events) def call_later(self, delay, callback, *args, **kwargs): cb = CB(self, delay, callback, *args, **kwargs) return cb.h - def remove_timeout(self, h): self.ioloop.remove_timeout(h) if h in self.handles: self.handles.remove(h) if h in self.callbacks: del self.callbacks[h] - def add_callback(self, cb, *args, **kwargs): self.ioloop.add_callback(cb, *args, **kwargs) diff --git a/src/py/bbctrl/IPLCDPage.py b/src/py/bbctrl/IPLCDPage.py deleted file mode 100644 index 4f5ee4e..0000000 --- a/src/py/bbctrl/IPLCDPage.py +++ /dev/null @@ -1,48 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import subprocess - -import bbctrl - - -class IPLCDPage(bbctrl.LCDPage): - # From bbctrl.LCDPage - def activate(self): - p = subprocess.Popen(['hostname', '-I'], stdout = subprocess.PIPE) - ips = p.communicate()[0].decode('utf-8').split() - - p = subprocess.Popen(['hostname'], stdout = subprocess.PIPE) - hostname = p.communicate()[0].decode('utf-8').strip() - - self.clear() - - self.text('Host: %s' % hostname[0:14], 0, 0) - - for i in range(min(3, len(ips))): - if len(ips[i]) <= 16: - self.text('IP: %s' % ips[i], 0, i + 1) diff --git a/src/py/bbctrl/Jog.py b/src/py/bbctrl/Jog.py index c4544e2..162602e 100644 --- a/src/py/bbctrl/Jog.py +++ b/src/py/bbctrl/Jog.py @@ -1,93 +1,594 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ +from bbctrl.Ctrl import Ctrl +from bbctrl.Log import Logger +from evdev.ecodes import EV, EV_ABS, EV_KEY +import errno +import evdev +import functools +import hashlib +import json +import os +import pyudev +import re +import traceback +import typing -import inevent -from inevent.Constants import * +userGamepadConfigs = {} + +gamepadConfigs = { + "default": { + "sign-x": 1, + "sign-y": -1, + "sign-z": -1, + "deadband": 0.15, + "debug": False, + }, + "9E2B3A63": { + "description": "Logitech 710, X mode", + "EV_KEY:308": "speed-4", + "EV_KEY:305": "speed-3", + "EV_KEY:304": "speed-2", + "EV_KEY:307": "speed-1", + "EV_ABS:0": "axis-x", + "EV_ABS:16": "axis-x", + "EV_ABS:1": "axis-y", + "EV_ABS:17": "axis-y", + "EV_ABS:4": "axis-z", + "EV_KEY:310": "lock-y", + "EV_KEY:311": "lock-x", + "EV_ABS:2": "lock-y", + "EV_ABS:5": "lock-x", + }, + "B98EF4EC": { + "description": "Logitech 710, D mode", + "EV_KEY:307": "speed-4", + "EV_KEY:306": "speed-3", + "EV_KEY:305": "speed-2", + "EV_KEY:304": "speed-1", + "EV_ABS:0": "axis-x", + "EV_ABS:16": "axis-x", + "EV_ABS:1": "axis-y", + "EV_ABS:17": "axis-y", + "EV_ABS:5": "axis-z", + "EV_KEY:308": "lock-y", + "EV_KEY:309": "lock-x", + "EV_KEY:310": "lock-y", + "EV_KEY:311": "lock-x", + }, + "268256FD": { + "description": "EasySMX ESM-9013, top lights mode", + "EV_KEY:308": "speed-4", + "EV_KEY:305": "speed-3", + "EV_KEY:304": "speed-2", + "EV_KEY:307": "speed-1", + "EV_ABS:0": "axis-x", + "EV_ABS:16": "axis-x", + "EV_ABS:1": "axis-y", + "EV_ABS:17": "axis-y", + "EV_ABS:4": "axis-z", + "EV_KEY:310": "lock-y", + "EV_KEY:311": "lock-x", + "EV_ABS:2": "lock-y", + "EV_ABS:5": "lock-x", + }, + "23CEC0CB": { + "description": "EasySMX ESM-9013, left lights mode", + "EV_KEY:304": "speed-4", + "EV_KEY:305": "speed-3", + "EV_KEY:306": "speed-2", + "EV_KEY:307": "speed-1", + "EV_ABS:0": "axis-x", + "EV_ABS:16": "axis-x", + "EV_ABS:1": "axis-y", + "EV_ABS:17": "axis-y", + "EV_ABS:5": "axis-z", + "EV_KEY:308": "lock-y", + "EV_KEY:309": "lock-x", + "EV_KEY:310": "lock-y", + "EV_KEY:311": "lock-x", + }, + "370DCB72": { + "description": "EasySMX ESM-9013, bottom lights mode", + "EV_KEY:308": "speed-4", + "EV_KEY:305": "speed-3", + "EV_KEY:304": "speed-2", + "EV_KEY:307": "speed-1", + "EV_ABS:0": "axis-x", + "EV_ABS:16": "axis-x", + "EV_ABS:1": "axis-y", + "EV_ABS:17": "axis-y", + "EV_ABS:5": "axis-z", + "EV_KEY:310": "lock-y", + "EV_KEY:311": "lock-x", + "EV_KEY:312": "lock-y", + "EV_KEY:313": "lock-x", + }, + "0BD0841F": { + "description": "Sony Playstation 4 Dual-Shock Controller", + "EV_KEY:307": "speed-4", + "EV_KEY:306": "speed-3", + "EV_KEY:305": "speed-2", + "EV_KEY:304": "speed-1", + "EV_ABS:0": "axis-x", + "EV_ABS:16": "axis-x", + "EV_ABS:1": "axis-y", + "EV_ABS:17": "axis-y", + "EV_ABS:5": "axis-z", + "EV_KEY:308": "lock-y", + "EV_KEY:309": "lock-x", + "EV_KEY:310": "lock-y", + "EV_KEY:311": "lock-x", + }, + "D09463DD": { + "description": "Sony Playstation 5 Controller", + "EV_KEY:307": "speed-4", + "EV_KEY:306": "speed-3", + "EV_KEY:305": "speed-2", + "EV_KEY:304": "speed-1", + "EV_ABS:0": "axis-x", + "EV_ABS:16": "axis-x", + "EV_ABS:1": "axis-y", + "EV_ABS:17": "axis-y", + "EV_ABS:5": "axis-z", + "EV_KEY:308": "lock-y", + "EV_KEY:309": "lock-x", + "EV_KEY:310": "lock-y", + "EV_KEY:311": "lock-x", + }, + "06656EBD": { + "description": "XBox One Controller", + "EV_KEY:308": "speed-4", + "EV_KEY:305": "speed-3", + "EV_KEY:304": "speed-2", + "EV_KEY:307": "speed-1", + "EV_ABS:0": "axis-x", + "EV_ABS:16": "axis-x", + "EV_ABS:1": "axis-y", + "EV_ABS:17": "axis-y", + "EV_ABS:4": "axis-z", + "EV_KEY:310": "lock-y", + "EV_KEY:311": "lock-x", + "EV_ABS:2": "lock-y", + "EV_ABS:5": "lock-x", + }, + "BFF99E89": { + "description": "XBox 360 Controller", + "EV_KEY:308": "speed-4", + "EV_KEY:305": "speed-3", + "EV_KEY:304": "speed-2", + "EV_KEY:307": "speed-1", + "EV_ABS:0": "axis-x", + "EV_ABS:16": "axis-x", + "EV_ABS:1": "axis-y", + "EV_ABS:17": "axis-y", + "EV_ABS:4": "axis-z", + "EV_KEY:310": "lock-y", + "EV_KEY:311": "lock-x", + "EV_ABS:2": "lock-y", + "EV_ABS:5": "lock-x", + }, + "4E0C75F7": { + "description": "EasySMX ESM-9100 XBox Controller, top lights mode", + "EV_KEY:308": "speed-4", + "EV_KEY:305": "speed-3", + "EV_KEY:304": "speed-2", + "EV_KEY:307": "speed-1", + "EV_ABS:0": "axis-x", + "EV_ABS:16": "axis-x", + "EV_ABS:1": "axis-y", + "EV_ABS:17": "axis-y", + "EV_ABS:4": "axis-z", + "EV_KEY:310": "lock-y", + "EV_KEY:311": "lock-x", + "EV_ABS:17": "axis-y", + "EV_ABS:4": "axis-z" + }, + "E310BCC0": { + "description": "EasySMX ESM-9100, left lights mode", + "EV_KEY:304": "speed-4", + "EV_KEY:305": "speed-3", + "EV_KEY:306": "speed-2", + "EV_KEY:307": "speed-1", + "EV_ABS:0": "axis-x", + "EV_ABS:16": "axis-x", + "EV_ABS:1": "axis-y", + "EV_ABS:17": "axis-y", + "EV_ABS:5": "axis-z", + "EV_KEY:308": "lock-y", + "EV_KEY:309": "lock-x", + "EV_KEY:310": "lock-y", + "EV_KEY:311": "lock-x", + }, + "96D2AC48": { + "description": "EasySMX ESM-9100, bottom lights mode", + "EV_KEY:308": "speed-4", + "EV_KEY:305": "speed-3", + "EV_KEY:304": "speed-2", + "EV_KEY:307": "speed-1", + "EV_ABS:0": "axis-x", + "EV_ABS:16": "axis-x", + "EV_ABS:1": "axis-y", + "EV_ABS:17": "axis-y", + "EV_ABS:5": "axis-z", + "EV_KEY:310": "lock-y", + "EV_KEY:311": "lock-x", + "EV_KEY:312": "lock-y", + "EV_KEY:313": "lock-x", + }, +} -# Listen for input events -class Jog(inevent.JogHandler): - def __init__(self, ctrl): - self.ctrl = ctrl - self.log = ctrl.log.get('Jog') +def safe_int(s, base=10, val=None): + try: + return int(s, base) + except ValueError: + return val - config = { - "Logitech Logitech RumblePad 2 USB": { - "deadband": 0.1, - "axes": [ABS_X, ABS_Y, ABS_RZ, ABS_Z], - "dir": [1, -1, -1, 1], - "arrows": [ABS_HAT0X, ABS_HAT0Y], - "speed": [0x120, 0x121, 0x122, 0x123], - "lock": [0x124, 0x125], - }, - "default": { - "deadband": 0.1, - "axes": [ABS_X, ABS_Y, ABS_RY, ABS_RX], - "dir": [1, -1, -1, 1], - "arrows": [ABS_HAT0X, ABS_HAT0Y], - "speed": [0x133, 0x130, 0x131, 0x134], - "lock": [0x136, 0x137], +def get_udev_prop(device: pyudev.Device, propertyName: str): + try: + return device.properties[propertyName] + except: + return None + + +def sorted_json(value): + return json.dumps(value, sort_keys=True) + + +AbsMinMax = typing.NamedTuple('AbsMinMax', [('min', float), ('max', float)]) + + +def processCapabilities(capabilities): + result = {} + + for (type, details) in capabilities.items(): + if type == EV_KEY: + result[type] = details + + if type == EV_ABS: + result[type] = { + code: AbsMinMax(float(info.min), float(info.max)) + for (code, info) in details } + + return result + + +# A forward declaration, so Command can reference it +class Gamepad(object): + pass + + +class Command(object): + + def __init__(self, id: str, event: evdev.InputEvent, value: int, + gamepad: Gamepad): + self.id = id + self.event = event + self.value = value + self.gamepad = gamepad + + def __str__(self): + return "Command({}={}, Event(type={}, code={}, value={}))".format( + self.id, self.value, EV[self.event.type], self.event.code, + self.event.value) + + +class Gamepad(object): + _logOnceRecord = set() + _eventValuesByCode = {} + + def __init__(self, log: Logger, _evdev: evdev.InputDevice, + _udev: pyudev.Device): + self._log = log + self._evdev = _evdev + self._udev = _udev + + self._capabilities = processCapabilities(_evdev.capabilities()) + + self._details = { + "evdev": { + "name": _evdev.name, + "vendor": _evdev.info.vendor, + "product": _evdev.info.product, + "version": _evdev.info.version, + "capabilities": self._capabilities, + }, + "udev": {key: _udev.properties[key] + for key in _udev.properties} } - super().__init__(config) + json = sorted_json(self._details["evdev"]) + self.hash = hashlib.sha256(json.encode()).hexdigest()[-8:].upper() - self.v = [0.0] * 4 - self.lastV = self.v - self.callback() + self.config = { + **gamepadConfigs.get("default"), + **userGamepadConfigs.get("default", {}), + **gamepadConfigs.get(self.hash, {}), + **userGamepadConfigs.get(self.hash, {}) + } - self.processor = inevent.InEvent(ctrl.ioloop, self, types = ['js']) + def read(self): + return self._evdev.read() + + @property + def fd(self): + return self._evdev.fd + + @property + def devicePath(self): + return self._evdev.path + + def getCommandFromEvent(self, event: evdev.InputEvent) -> Command: + if event.type not in [EV_ABS, EV_KEY]: + return + + value = self.scaleAndClampValue(event) + + lastValue = self._eventValuesByCode.get(event.code) + if value == lastValue: + return + + self._eventValuesByCode[event.code] = value + + eventSignature = "{}:{}".format(EV[event.type], event.code) + commandId = self.config.get(eventSignature) + + if not commandId: + self.logOnce("Unmapped event: {}".format(eventSignature)) + return + + command = Command(commandId, event, value, self) + + self.logDebug(command) + + return command + + def scaleAndClampValue(self, event: evdev.InputEvent): + if event.type != EV_ABS: + return event.value + + info = self._capabilities[EV_ABS].get(event.code) # type: AbsMinMax + if not info: + return 0 + + # Clamp the value to the device's min/max range + value = float(max(info.min, min(info.max, event.value))) + + # Remap the value from the device range to -1..1 + value = ((value - info.min) / (info.max - info.min)) * 2.0 - 1.0 + + sign = -1 if value < 0 else 1 + value = abs(value) + + deadband = self.config.get("deadband", 0.15) + if value < deadband: + return 0 + + # Remap the value to use the full range, with the "deadband" range removed + # e.g. if value == deadband, the new value will be zero + delta = value - deadband + range = 1 - deadband + value = (delta * sign) / range + + return round(value, 3) + + def log(self, msg): + self._log.info("{}: {}".format(self.hash, msg)) + + def logOnce(self, msg): + if self.config.get("debug") or msg not in self._logOnceRecord: + self._logOnceRecord.add(msg) + self.log(msg) + + def logDebug(self, msg): + if self.config.get("debug"): + self.log(msg) + + def __str__(self) -> str: + return sorted_json({ + "devicePath": self.devicePath, + "bustype": self._evdev.info.bustype, + "details": self._details, + "hash": self.hash + }) - def up(self): self.ctrl.lcd.page_up() - def down(self): self.ctrl.lcd.page_down() - def left(self): self.ctrl.lcd.page_left() - def right(self): self.ctrl.lcd.page_right() +class Jog(object): + gamepads = {} # type: dict[typing.Union[int, str], Gamepad] + lock = {"x": False, "y": False} + axes = {"x": 0, "y": 0, "z": 0} + speed = 3 # a resonable default speed, not too fast, not too slow + changed = False + def __init__(self, ctrl: Ctrl): + self.ctrl = ctrl + self.ioloop = ctrl.ioloop + self.log = ctrl.log.get('Jog') - def callback(self): - if self.v != self.lastV: - self.lastV = self.v + self._loadUserGamepadConfigs() + self._startMonitoring() + self._discoverGamepads() + self._updateJogging() + + def _loadUserGamepadConfigs(self): + try: + path = self.ctrl.get_path('gamepads.json') + if os.path.exists(path): + with open(path, 'r') as f: + global userGamepadConfigs + userGamepadConfigs = json.load(f) + except: + self.log.info(traceback.format_exc()) + self.log.info("Failed to read 'gamepads.json'") + + def _startMonitoring(self): + self.udev_context = pyudev.Context() + self.monitor = pyudev.Monitor.from_netlink(self.udev_context) + self.monitor.filter_by(subsystem='input') + self.ctrl.ioloop.add_handler(self.monitor, self._udevHandler, + self.ctrl.ioloop.READ) + self.monitor.start() + + def _udevHandler(self, fd, events): + for udev in iter(functools.partial(self.monitor.poll, 0), None): + isEventDevice = re.search(r"/event\d+$", udev.device_node or "") + if not isEventDevice: + continue + + inputJoystick = safe_int(udev.properties["ID_INPUT_JOYSTICK"]) + + if inputJoystick != 1: + self.log.info("Ignoring non-gamepad device: {}".format( + sorted_json( + {key: udev.properties[key] + for key in udev.properties}))) + continue + + if udev.action == 'add': + self._listen(udev.device_node) + elif udev.action == 'remove': + self._forget(udev.device_node) + + def _discoverGamepads(self): + with open("/proc/bus/input/devices", "r") as file: + for line in file: + # Matches lines from '/proc/bus/input/devices' that look like: + # H: Handlers=js1 event0 + if not re.match(r"H:\s*Handlers\s*=.*\bjs\d+\b", line): + continue + + match = re.search(r"\bevent\d+\b", line) + if not match: + continue + + self._listen("/dev/input/{}".format(match.group())) + + def _listen(self, devicePath: str): + gamepad = Gamepad( + self.log, evdev.InputDevice(devicePath), + pyudev.Devices.from_device_file(self.udev_context, devicePath)) + + self.log.info("Found gamepad: {}".format(gamepad)) + + self.gamepads[gamepad.fd] = self.gamepads[devicePath] = gamepad + + self.ioloop.add_handler(gamepad.fd, self._gamepadHandler, + self.ioloop.READ) + + def _forget(self, devicePath: str): + gamepad = self.gamepads.get(devicePath) + if not gamepad: + return + + gamepad.log("Gamepad removed: {}".format(devicePath)) + + self.ioloop.remove_handler(gamepad.fd) + del self.gamepads[gamepad.devicePath] + del self.gamepads[gamepad.fd] + + def _gamepadHandler(self, fd, events): + gamepad = self.gamepads.get(fd) + if not gamepad: + self.log.info("Unknown gamepad? {}".format(fd)) + return + + try: + for event in gamepad.read(): + command = gamepad.getCommandFromEvent(event) + self._processCommand(command) + except BlockingIOError: + pass + except OSError as error: + if error.errno == errno.ENODEV: + self._forget(gamepad.devicePath) + else: + gamepad.log(traceback.format_exc()) + except Exception as error: + gamepad.log(traceback.format_exc()) + + def _processCommand(self, command: Command): + if not command: + return + + processor = self.commandProcessors.get(command.id) + if not processor: + command.gamepad.log("Bad command: {}".format(command)) + return + + processor(self, command) + + def _processSpeedCommand(self, command: Command): + match = re.match(r"^speed-(\d)$", command.id) + speed = int(match.group(1)) if match else 0 + if speed not in [1, 2, 3, 4]: + command.gamepad.log("Bad speed command: {}".format(command)) + + self.changed = self.changed or self.speed != speed + self.speed = speed + + def _processAxisCommand(self, command: Command): + match = re.match(r"^axis-(.)$", command.id) + axis = match.group(1) if match else "" + if axis not in ["x", "y", "z"]: + command.gamepad.log("Bad axis command: {}".format(command)) + + sign = command.gamepad.config.get("sign-{}".format(axis), 1) + oldValue = self.axes[axis] + locked = self.lock.get(axis, False) + + self.axes[axis] = 0 if locked else command.value * sign + self.changed = self.changed or oldValue != self.axes[axis] + + command.gamepad.logDebug( + "{}(value={}, oldValue={}, sign={}, locked={})".format( + command.id, self.axes[axis], oldValue, sign, locked)) + + def _processLockCommand(self, command: Command): + match = re.match(r"^lock-(.)$", command.id) + axis = match.group(1) if match else "" + if axis not in ["x", "y"]: + command.gamepad.log("Bad lock command: {}".format(command)) + + if command.event.type == EV_ABS: + self.lock[axis] = bool(command.value > -0.9) + else: + self.lock[axis] = bool(command.value) + + def _processDisabled(self, command: Command): + pass + + def _updateJogging(self): + try: + if not self.changed: + return + + self.changed = False + + if self.speed == 1: scale = 1.0 / 128.0 + if self.speed == 2: scale = 1.0 / 32.0 + if self.speed == 3: scale = 1.0 / 4.0 + if self.speed == 4: scale = 1.0 + + axes = {axis: value * scale for (axis, value) in self.axes.items()} try: - axes = {} - for i in range(len(self.v)): axes["xyzabc"[i]] = self.v[i] self.ctrl.mach.jog(axes) + except: + self.log.info(traceback.format_exc()) + finally: + # We only update 4 times a second, to keep from overwhelming the system + # EV_ABS events can happen hundreds of times a second. + self.ctrl.ioloop.call_later(0.25, self._updateJogging) - except Exception as e: - self.log.warning('Jog: %s', e) - - self.ctrl.ioloop.call_later(0.25, self.callback) - - - def changed(self): - scale = 1.0 - if self.speed == 1: scale = 1.0 / 128.0 - if self.speed == 2: scale = 1.0 / 32.0 - if self.speed == 3: scale = 1.0 / 4.0 - - self.v = [x * scale for x in self.axes] + commandProcessors = { + "speed-1": _processSpeedCommand, + "speed-2": _processSpeedCommand, + "speed-3": _processSpeedCommand, + "speed-4": _processSpeedCommand, + "axis-x": _processAxisCommand, + "axis-y": _processAxisCommand, + "axis-z": _processAxisCommand, + "lock-x": _processLockCommand, + "lock-y": _processLockCommand, + "disabled": _processDisabled + } # type: dict[str, typing.Callable[[Command], None]] diff --git a/src/py/bbctrl/LCD.py b/src/py/bbctrl/LCD.py deleted file mode 100644 index 38f6adb..0000000 --- a/src/py/bbctrl/LCD.py +++ /dev/null @@ -1,207 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import lcd -import atexit - - -class LCDPage: - def __init__(self, lcd, text = None): - self.lcd = lcd - self.data = lcd.new_screen() - - if text is not None: - self.text(text, (lcd.width - len(text)) // 2, 1) - - - def activate(self): pass - def deactivate(self): pass - - - def put(self, c, x, y): - y += x // self.lcd.width - x %= self.lcd.width - y %= self.lcd.height - - if self.data[x][y] != c: - self.data[x][y] = c - if self == self.lcd.page: self.lcd.update() - - - def text(self, s, x, y): - for c in s: - self.put(c, x, y) - x += 1 - - - def clear(self): - self.data = self.lcd.new_screen() - self.lcd.redraw = True - - - def shift_left(self): pass - def shift_right(self): pass - def shift_up(self): pass - def shift_down(self): pass - - -class LCD: - def __init__(self, ctrl): - self.ctrl = ctrl - self.log = ctrl.log.get('LCD') - - self.addrs = self.ctrl.args.lcd_addr - self.addr = self.addrs[0] - self.addr_num = 0 - - self.width = 20 - self.height = 4 - self.lcd = None - self.timeout = None - self.reset = False - self.page = None - self.pages = [] - self.current_page = 0 - self.screen = self.new_screen() - self.set_message('Loading...') - - self._redraw(False) - if not ctrl.args.demo: atexit.register(self.goodbye) - - - def set_message(self, msg): - try: - self.load_page(LCDPage(self, msg)) - self._update() - except IOError as e: - self.log.warning('LCD communication failed: %s' % e) - - - def new_screen(self): - return [[' ' for y in range(self.height)] for x in range(self.width)] - - - def new_page(self): return LCDPage(self) - def add_page(self, page): self.pages.append(page) - - - def add_new_page(self, page = None): - if page is None: page = self.new_page() - page.id = len(self.pages) - self.add_page(page) - return page - - - def load_page(self, page): - if self.page != page: - if self.page is not None: self.page.deactivate() - page.activate() - self.page = page - self.redraw = True - self.update() - - - def set_current_page(self, current_page): - self.current_page = current_page % len(self.pages) - self.load_page(self.pages[self.current_page]) - - - def page_up(self): pass - def page_down(self): pass - def page_right(self): self.set_current_page(self.current_page + 1) - def page_left(self): self.set_current_page(self.current_page - 1) - - - def update(self): - if self.timeout is None: - self.timeout = self.ctrl.ioloop.call_later(0.25, self._update) - - - def _redraw(self, now = True): - if now: - self.redraw = True - self.update() - self.redraw_timer = self.ctrl.ioloop.call_later(5, self._redraw) - - - def _update(self): - self.timeout = None - - try: - if self.lcd is None: - self.lcd = lcd.LCD(self.ctrl.i2c, self.addr, self.height, - self.width) - - if self.reset: - self.lcd.reset() - self.redraw = True - self.reset = False - - cursorX, cursorY = -1, -1 - - for y in range(self.height): - for x in range(self.width): - c = self.page.data[x][y] - - if self.redraw or self.screen[x][y] != c: - if cursorX != x or cursorY != y: - self.lcd.goto(x, y) - cursorX, cursorY = x, y - - self.lcd.put_char(c) - cursorX += 1 - self.screen[x][y] = c - - self.redraw = False - - except IOError as e: - # Try next address - #self.addr_num += 1 - #if len(self.addrs) <= self.addr_num: self.addr_num = 0 - #self.addr = self.addrs[self.addr_num] - #self.lcd = None - - #self.log.warning('LCD communication failed, ' + - # 'retrying on address 0x%02x: %s' % (self.addr, e)) - - #self.log.warning('LCD not present.') - - #self.reset = True - self.reset = False - #self.timeout = self.ctrl.ioloop.call_later(1, self._update) - - - def goodbye(self, message = ''): - if self.timeout: - self.ctrl.ioloop.remove_timeout(self.timeout) - self.timeout = None - - if self.redraw_timer: - self.ctrl.ioloop.remove_timeout(self.redraw_timer) - self.redraw_timer = None - - if self.lcd is not None: self.set_message(message) diff --git a/src/py/bbctrl/Log.py b/src/py/bbctrl/Log.py index 87f694f..f034650 100644 --- a/src/py/bbctrl/Log.py +++ b/src/py/bbctrl/Log.py @@ -1,50 +1,20 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import os -import sys -import io import datetime -import traceback +import os import pkg_resources -from inspect import getframeinfo, stack -import bbctrl - - -DEBUG = 0 -INFO = 1 -MESSAGE = 2 -WARNING = 3 -ERROR = 4 +import sys +import traceback +DEBUG = 0 +INFO = 1 +MESSAGE = 2 +WARNING = 3 +ERROR = 4 level_names = 'debug info message warning error'.split() -def get_level_name(level): return level_names[level] + +def get_level_name(level): + return level_names[level] # Get this file's name @@ -52,15 +22,17 @@ _srcfile = os.path.normcase(get_level_name.__code__.co_filename) class Logger(object): + def __init__(self, log, name, level): self.log = log self.name = name self.level = level + def set_level(self, level): + self.level = level - def set_level(self, level): self.level = level - def _enabled(self, level): return self.level <= level and level <= ERROR - + def _enabled(self, level): + return self.level <= level and level <= ERROR def _find_caller(self): f = sys._getframe() @@ -78,7 +50,6 @@ class Logger(object): return '(unknown file)', 0, '(unknown function)' - def _log(self, level, msg, *args, **kwargs): if not self._enabled(level): return @@ -88,15 +59,22 @@ class Logger(object): if len(args): msg %= args - self.log._log(msg, level = level, prefix = self.name, **kwargs) + self.log._log(msg, level=level, prefix=self.name, **kwargs) + def debug(self, *args, **kwargs): + self._log(DEBUG, *args, **kwargs) - def debug (self, *args, **kwargs): self._log(DEBUG, *args, **kwargs) - def message(self, *args, **kwargs): self._log(MESSAGE, *args, **kwargs) - def info (self, *args, **kwargs): self._log(INFO, *args, **kwargs) - def warning(self, *args, **kwargs): self._log(WARNING, *args, **kwargs) - def error (self, *args, **kwargs): self._log(ERROR, *args, **kwargs) + def message(self, *args, **kwargs): + self._log(MESSAGE, *args, **kwargs) + def info(self, *args, **kwargs): + self._log(INFO, *args, **kwargs) + + def warning(self, *args, **kwargs): + self._log(WARNING, *args, **kwargs) + + def error(self, *args, **kwargs): + self._log(ERROR, *args, **kwargs) def exception(self, *args, **kwargs): msg = traceback.format_exc() @@ -104,7 +82,9 @@ class Logger(object): self._log(INFO, msg, **kwargs) self._log(ERROR, *args, **kwargs) + class Log(object): + def __init__(self, args, ioloop, path): self.path = path self.listeners = [] @@ -121,29 +101,29 @@ class Log(object): self._log('Log started v%s' % version) self._log_time(ioloop) + def get_path(self): + return self.path - def get_path(self): return self.path + def add_listener(self, listener): + self.listeners.append(listener) - def add_listener(self, listener): self.listeners.append(listener) - def remove_listener(self, listener): self.listeners.remove(listener) + def remove_listener(self, listener): + self.listeners.remove(listener) - - def get(self, name, level = None): + def get(self, name, level=None) -> Logger: if not name in self.loggers: self.loggers[name] = Logger(self, name, self.level) return self.loggers[name] - def _log_time(self, ioloop): self._log(datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')) ioloop.call_later(60 * 60, self._log_time, ioloop) - def broadcast(self, msg): - for listener in self.listeners: listener(msg) + for listener in self.listeners: + listener(msg) - - def _log(self, msg, level = INFO, prefix = '', where = None): + def _log(self, msg, level=INFO, prefix='', where=None): if not msg: return hdr = '%s:%s:' % ('DIMWE'[level], prefix) @@ -160,11 +140,10 @@ class Log(object): # Broadcast to log listeners if level == INFO: return - msg = dict(level = get_level_name(level), source = prefix, msg = msg) + msg = dict(level=get_level_name(level), source=prefix, msg=msg) if where is not None: msg['where'] = where - self.broadcast(dict(log = msg)) - + self.broadcast(dict(log=msg)) def _open(self): if self.path is None: return @@ -173,8 +152,7 @@ class Log(object): self.f = open(self.path, 'a') self.bytes_written = 0 - - def _rotate(self, path, n = None): + def _rotate(self, path, n=None): fullpath = '%s.%d' % (path, n) if n is not None else path nextN = (0 if n is None else n) + 1 diff --git a/src/py/bbctrl/Mach.py b/src/py/bbctrl/Mach.py index 677c160..a9a6943 100644 --- a/src/py/bbctrl/Mach.py +++ b/src/py/bbctrl/Mach.py @@ -1,35 +1,7 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import bbctrl from bbctrl.Comm import Comm +import bbctrl import bbctrl.Cmd as Cmd - # Axis homing procedure: # # Mark axis unhomed @@ -74,11 +46,13 @@ and check your motor cabling. See the "Motor Faults" table on the "Indicators" \ for more information.\ ''' + def overrides(interface_class): + def overrider(method): if not method.__name__ in dir(interface_class): - raise Exception('%s does not override %s' % ( - method.__name__, interface_class.__name__)) + raise Exception('%s does not override %s' % + (method.__name__, interface_class.__name__)) return method @@ -86,6 +60,7 @@ def overrides(interface_class): class Mach(Comm): + def __init__(self, ctrl, avr): super().__init__(ctrl, avr) @@ -102,27 +77,37 @@ class Mach(Comm): super().reboot() + def _get_state(self): + return self.ctrl.state.get('xx', '') - def _get_state(self): return self.ctrl.state.get('xx', '') - def _is_estopped(self): return self._get_state() == 'ESTOPPED' - def _is_holding(self): return self._get_state() == 'HOLDING' - def _is_ready(self): return self._get_state() == 'READY' - def _get_pause_reason(self): return self.ctrl.state.get('pr', '') - def _get_cycle(self): return self.ctrl.state.get('cycle', 'idle') + def _is_estopped(self): + return self._get_state() == 'ESTOPPED' + def _is_holding(self): + return self._get_state() == 'HOLDING' + + def _is_ready(self): + return self._get_state() == 'READY' + + def _get_pause_reason(self): + return self.ctrl.state.get('pr', '') + + def _get_cycle(self): + return self.ctrl.state.get('cycle', 'idle') def _is_paused(self): - if not self._is_holding() or self.unpausing: return False - return self._get_pause_reason() in ( - 'User pause', 'Program pause', 'Optional pause') - - - def _set_cycle(self, cycle): self.ctrl.state.set('cycle', cycle) + if not self._is_holding() or self.unpausing: + return False + return self._get_pause_reason() in ('User pause', 'Program pause', + 'Optional pause') + def _set_cycle(self, cycle): + self.ctrl.state.set('cycle', cycle) def _begin_cycle(self, cycle): current = self._get_cycle() - if current == cycle: return # No change + if current == cycle: + return # No change if current != 'idle': raise Exception('Cannot enter %s cycle while in %s cycle' % @@ -132,13 +117,17 @@ class Mach(Comm): # if current == 'idle' or (cycle == 'jogging' and self._is_paused()): self._set_cycle(cycle) - def process_log(self, log): # When a probe has failed, we have to e-stop or things # end up in a bad state, where positions and offsets are incorrect if log['msg'] == 'Switch not found': self.estop() + def _end_cycle(self): + if (self._get_cycle() != 'idle' and self._is_ready() + and not self.planner.is_busy() and not super().is_active()): + self.planner.position_change() + self._set_cycle('idle') def _update(self, update): # Detect motor faults @@ -153,14 +142,11 @@ class Mach(Comm): # Handle EStop if state_changed and state == 'ESTOPPED': - self.planner.reset(stop = False) + self.planner.reset(stop=False) - # Exit cycle if state changed to READY - if (state_changed and self._get_cycle() != 'idle' and - self._is_ready() and not self.planner.is_busy() and - not super().is_active()): - self.planner.position_change() - self._set_cycle('idle') + # Check if cycle has ended + if state_changed: + self._end_cycle() # Planner stop if state == 'READY' and self.stopping: @@ -182,12 +168,11 @@ class Mach(Comm): # Must be after holding commands above op = self.ctrl.state.get('optional_pause', False) pr = self._get_pause_reason() - if ((state_changed or 'pr' in update) and self._is_holding() and - (pr in ('Switch found', 'User stop') or - (pr == 'Optional pause' and not op))): + if ((state_changed or 'pr' in update) and self._is_holding() + and (pr in ('Switch found', 'User stop') or + (pr == 'Optional pause' and not op))): self._unpause() - def _unpause(self): pause_reason = self._get_pause_reason() self.mlog.info('Unpause: ' + pause_reason) @@ -196,36 +181,37 @@ class Mach(Comm): self.planner.stop() self.ctrl.state.set('line', 0) - else: self.planner.restart() + else: + self.planner.restart() super().i2c_command(Cmd.UNPAUSE) self.unpausing = True - def _i2c_block(self, block): - super().i2c_command(block[0], block = block[1:]) - - - def _i2c_set(self, name, value): self._i2c_block(Cmd.set(name, value)) + super().i2c_command(block[0], block=block[1:]) + def _i2c_set(self, name, value): + self._i2c_block(Cmd.set(name, value)) @overrides(Comm) def comm_next(self): - if self.planner.is_running() and not self._is_holding(): - return self.planner.next() + shouldFetch = self.planner.is_running() and not self._is_holding() + cmd = self.planner.next() if shouldFetch else None + if cmd is None: + self._end_cycle() + + return cmd @overrides(Comm) def comm_error(self): self.planner.reset() - @overrides(Comm) def connect(self): self.planner.reset() super().connect() - def _query_var(self, cmd): equal = cmd.find('=') if equal == -1: @@ -234,21 +220,26 @@ class Mach(Comm): else: name, value = cmd[1:equal], cmd[equal + 1:] - if value.lower() == 'true': value = True - elif value.lower() == 'false': value = False + if value.lower() == 'true': + value = True + elif value.lower() == 'false': + value = False else: try: value = float(value) - except: pass + except: + pass self.ctrl.state.config(name, value) - - def mdi(self, cmd, with_limits = True): + def mdi(self, cmd, with_limits=True): try: - if not len(cmd): return - if cmd[0] == '$': self._query_var(cmd) - elif cmd[0] == '\\': super().queue_command(cmd[1:]) + if not len(cmd): + return + if cmd[0] == '$': + self._query_var(cmd) + elif cmd[0] == '\\': + super().queue_command(cmd[1:]) else: self._begin_cycle('mdi') self.planner.mdi(cmd, with_limits) @@ -260,18 +251,18 @@ class Mach(Comm): def set(self, code, value): super().queue_command('${}={}'.format(code, value)) - def jog(self, axes): self._begin_cycle('jogging') self.planner.position_change() super().queue_command(Cmd.jog(axes)) - - def home(self, axis, position = None): + def home(self, axis, position=None): state = self.ctrl.state - if axis is None: axes = 'zxyabc' # TODO This should be configurable - else: axes = '%c' % axis + if axis is None: + axes = 'zxyabc' # TODO This should be configurable + else: + axes = '%c' % axis for axis in axes: enabled = state.is_axis_enabled(axis) @@ -286,12 +277,13 @@ class Mach(Comm): # Error when axes cannot be homed reason = state.axis_home_fail_reason(axis) if reason is not None: - self.mlog.error('Cannot home %s axis: %s' % ( - axis.upper(), reason)) + self.mlog.error('Cannot home %s axis: %s' % + (axis.upper(), reason)) continue if mode == 'manual': - if position is None: raise Exception('Position not set') + if position is None: + raise Exception('Position not set') self.mdi('G28.3 %c%f' % (axis, position)) continue @@ -299,56 +291,68 @@ class Mach(Comm): self.mlog.info('Homing %s axis' % axis) self._begin_cycle('homing') - if mode.startswith('stall-'): procedure = stall_homing_procedure - else: procedure = axis_homing_procedure + if mode.startswith('stall-'): + procedure = stall_homing_procedure + else: + procedure = axis_homing_procedure gcode = procedure % {'axis': axis} self.planner.mdi(gcode, False) super().resume() + def unhome(self, axis): + self.mdi('G28.2 %c0' % axis) - def unhome(self, axis): self.mdi('G28.2 %c0' % axis) - def estop(self): super().estop() - + def estop(self): + super().estop() def clear(self): if self._is_estopped(): self.planner.reset() super().clear() + def fake_probe_contact(self): + self._i2c_set('pt', 2) + self.ctrl.state.set('pw', 0) + self.timer = self.ctrl.ioloop.call_later(0.5, + self.clear_fake_probe_contact) + + def clear_fake_probe_contact(self): + self._i2c_set('pt', 1) + self.ctrl.state.set('pw', 1) def start(self): filename = self.ctrl.state.get('selected', '') - if not filename: return + if not filename: + return self._begin_cycle('running') self.planner.load(filename) super().resume() - def step(self): - raise Exception('NYI') # TODO - if self._get_cycle() != 'running': self.start() - else: super().i2c_command(Cmd.UNPAUSE) - + raise Exception('NYI') # TODO + if self._get_cycle() != 'running': + self.start() + else: + super().i2c_command(Cmd.UNPAUSE) def stop(self): - if self._get_state() != 'jogging': self.stopping = True + if self._get_state() != 'jogging': + self.stopping = True super().i2c_command(Cmd.STOP) - - def pause(self): super().pause() + def pause(self): + super().pause() def unpause(self): if self._is_paused(): self.ctrl.state.set('optional_pause', False) self._unpause() - - def optional_pause(self, enable = True): + def optional_pause(self, enable=True): self.ctrl.state.set('optional_pause', enable) - def set_position(self, axis, position): axis = axis.lower() state = self.ctrl.state @@ -367,17 +371,14 @@ class Mach(Comm): state.set(axis + 'p', target) super().queue_command(Cmd.set_axis(axis, target)) - def override_feed(self, override): self._i2c_set('fo', int(1000 * override)) - def override_speed(self, override): self._i2c_set('so', int(1000 * override)) - - def modbus_read(self, addr): self._i2c_block(Cmd.modbus_read(addr)) - + def modbus_read(self, addr): + self._i2c_block(Cmd.modbus_read(addr)) def modbus_write(self, addr, value): self._i2c_block(Cmd.modbus_write(addr, value)) diff --git a/src/py/bbctrl/MainLCDPage.py b/src/py/bbctrl/MainLCDPage.py deleted file mode 100644 index ba17391..0000000 --- a/src/py/bbctrl/MainLCDPage.py +++ /dev/null @@ -1,76 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import bbctrl - - -class MainLCDPage(bbctrl.LCDPage): - def __init__(self, ctrl): - bbctrl.LCDPage.__init__(self, ctrl.lcd) - - self.ctrl = ctrl - self.install = True - - ctrl.state.add_listener(self.update) - - - def update(self, update): - state = self.ctrl.state - - # Must be after machine vars have loaded - if self.install and hasattr(self, 'id'): - self.install = False - self.ctrl.lcd.set_current_page(self.id) - - self.text('%-9s' % state.get('xx', ''), 0, 0) - - metric = not state.get('imperial', False) - scale = 1 if metric else 25.4 - - # Show enabled axes - row = 0 - for axis in 'xyzabc': - if state.is_axis_faulted(axis): - self.text(' FAULT %s' % axis.upper(), 9, row) - row += 1 - - elif state.is_axis_enabled(axis): - position = state.get(axis + 'p', 0) - position += state.get('offset_' + axis, 0) - position /= scale - self.text('% 10.3f%s' % (position, axis.upper()), 9, row) - row += 1 - - while row < 4: - self.text(' ' * 11, 9, row) - row += 1 - - # Show tool, units, feed and speed - self.text('%2uT' % state.get('tool', 0), 6, 1) - self.text('%-6s' % 'MM' if metric else 'INCH', 0, 1) - self.text('%8uF' % (state.get('feed', 0) / scale), 0, 2) - self.text('%8dS' % state.get('speed', 0), 0, 3) diff --git a/src/py/bbctrl/MonitorTemp.py b/src/py/bbctrl/MonitorTemp.py index d208cd2..34d9226 100644 --- a/src/py/bbctrl/MonitorTemp.py +++ b/src/py/bbctrl/MonitorTemp.py @@ -1,30 +1,3 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - import time @@ -35,10 +8,12 @@ def read_temp(): def set_max_freq(freq): filename = '/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq' - with open(filename, 'w') as f: f.write('%d\n' % freq) + with open(filename, 'w') as f: + f.write('%d\n' % freq) class MonitorTemp(object): + def __init__(self, app): self.app = app @@ -57,7 +32,6 @@ class MonitorTemp(object): self.callback() - # Scale max CPU based on temperature def scale_cpu(self, temp): if temp < self.min_temp: cpu_freq = self.max_freq @@ -69,7 +43,6 @@ class MonitorTemp(object): set_max_freq(cpu_freq) - def update_camera(self, temp): if self.app.camera is None: return @@ -78,7 +51,6 @@ class MonitorTemp(object): elif self.high_camera_temp < temp: self.app.camera.set_overtemp(True) - def log_warnings(self, temp): # Reset temperature warning threshold after timeout if time.time() < self.last_temp_warn + 60: self.temp_thresh = 80 @@ -89,7 +61,6 @@ class MonitorTemp(object): self.log.info('Hot RaspberryPi at %d°C' % temp) - def callback(self): try: temp = read_temp() @@ -99,6 +70,7 @@ class MonitorTemp(object): self.update_camera(temp) self.log_warnings(temp) - except: self.log.exception('Internal error: Temperature status') + except: + self.log.exception('Internal error: Temperature status') self.ioloop.call_later(5, self.callback) diff --git a/src/py/bbctrl/ObjGraph.py b/src/py/bbctrl/ObjGraph.py deleted file mode 100644 index 7957bbb..0000000 --- a/src/py/bbctrl/ObjGraph.py +++ /dev/null @@ -1,1223 +0,0 @@ -""" -Tools for drawing Python object reference graphs with graphviz. - -You can find documentation online at https://mg.pov.lt/objgraph/ - -Copyright (c) 2008-2017 Marius Gedminas and contributors - -Released under the MIT licence. -""" -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -from __future__ import print_function - -import codecs -import collections -import gc -import re -import inspect -import types -import operator -import os -import subprocess -import tempfile -import sys -import itertools - -try: - # Python 2.x compatibility - from StringIO import StringIO -except ImportError: - from io import StringIO - -try: - from types import InstanceType -except ImportError: - # Python 3.x compatibility - InstanceType = None - - -__author__ = "Marius Gedminas (marius@gedmin.as)" -__copyright__ = "Copyright (c) 2008-2017 Marius Gedminas and contributors" -__license__ = "MIT" -__version__ = '3.4.1.dev0' -__date__ = '2018-02-13' - - -try: - basestring -except NameError: - # Python 3.x compatibility - basestring = str - -try: - iteritems = dict.iteritems -except AttributeError: - # Python 3.x compatibility - iteritems = dict.items - -IS_INTERACTIVE = False -try: # pragma: nocover - import graphviz - if get_ipython().__class__.__name__ != 'TerminalInteractiveShell': - IS_INTERACTIVE = True -except (NameError, ImportError): - pass - - -def _isinstance(object, classinfo): - """Return whether an object is an instance of a class or its subclass. - - Differs from the builtin isinstance() implementation in that it does not - depend on the ``__class__`` attribute which is proxied by - mock.Mock(spec=...). - """ - return issubclass(type(object), classinfo) - - -def count(typename, objects=None): - """Count objects tracked by the garbage collector with a given class name. - - The class name can optionally be fully qualified. - - Example: - - >>> count('dict') - 42 - >>> count('mymodule.MyClass') - 2 - - .. note:: - - The Python garbage collector does not track simple - objects like int or str. See - https://docs.python.org/3/library/gc.html#gc.is_tracked - for more information. - - Instead of looking through all objects tracked by the GC, you may - specify your own collection, e.g. - - >>> count('MyClass', get_leaking_objects()) - 3 - - See also: :func:`get_leaking_objects`. - - .. versionchanged:: 1.7 - New parameter: ``objects``. - - .. versionchanged:: 1.8 - Accepts fully-qualified type names (i.e. 'package.module.ClassName') - as well as short type names (i.e. 'ClassName'). - - """ - if objects is None: - objects = gc.get_objects() - try: - if '.' in typename: - return sum(1 for o in objects if _long_typename(o) == typename) - else: - return sum(1 for o in objects if _short_typename(o) == typename) - finally: - del objects # clear cyclic references to frame - - -def typestats(objects=None, shortnames=True, filter=None): - """Count the number of instances for each type tracked by the GC. - - Note that the GC does not track simple objects like int or str. - - Note that classes with the same name but defined in different modules - will be lumped together if ``shortnames`` is True. - - If ``filter`` is specified, it should be a function taking one argument and - returning a boolean. Objects for which ``filter(obj)`` returns ``False`` - will be ignored. - - Example: - - >>> typestats() - {'list': 12041, 'tuple': 10245, ...} - >>> typestats(get_leaking_objects()) - {'MemoryError': 1, 'tuple': 2795, 'RuntimeError': 1, 'list': 47, ...} - - .. versionadded:: 1.1 - - .. versionchanged:: 1.7 - New parameter: ``objects``. - - .. versionchanged:: 1.8 - New parameter: ``shortnames``. - - .. versionchanged:: 3.1.3 - New parameter: ``filter``. - - """ - if objects is None: - objects = gc.get_objects() - try: - if shortnames: - typename = _short_typename - else: - typename = _long_typename - stats = {} - for o in objects: - if filter and not filter(o): - continue - n = typename(o) - stats[n] = stats.get(n, 0) + 1 - return stats - finally: - del objects # clear cyclic references to frame - - -def most_common_types(limit=10, objects=None, shortnames=True, filter=None): - """Count the names of types with the most instances. - - Returns a list of (type_name, count), sorted most-frequent-first. - - Limits the return value to at most ``limit`` items. You may set ``limit`` - to None to avoid that. - - If ``filter`` is specified, it should be a function taking one argument and - returning a boolean. Objects for which ``filter(obj)`` returns ``False`` - will be ignored. - - The caveats documented in :func:`typestats` apply. - - Example: - - >>> most_common_types(limit=2) - [('list', 12041), ('tuple', 10245)] - - .. versionadded:: 1.4 - - .. versionchanged:: 1.7 - New parameter: ``objects``. - - .. versionchanged:: 1.8 - New parameter: ``shortnames``. - - .. versionchanged:: 3.1.3 - New parameter: ``filter``. - - """ - stats = sorted( - typestats(objects, shortnames=shortnames, filter=filter).items(), - key=operator.itemgetter(1), reverse=True) - if limit: - stats = stats[:limit] - return stats - - -def show_most_common_types( - limit=10, - objects=None, - shortnames=True, - file=None, - filter=None): - """Print the table of types of most common instances. - - If ``filter`` is specified, it should be a function taking one argument and - returning a boolean. Objects for which ``filter(obj)`` returns ``False`` - will be ignored. - - The caveats documented in :func:`typestats` apply. - - Example: - - >>> show_most_common_types(limit=5) - tuple 8959 - function 2442 - wrapper_descriptor 1048 - dict 953 - builtin_function_or_method 800 - - .. versionadded:: 1.1 - - .. versionchanged:: 1.7 - New parameter: ``objects``. - - .. versionchanged:: 1.8 - New parameter: ``shortnames``. - - .. versionchanged:: 3.0 - New parameter: ``file``. - - .. versionchanged:: 3.1.3 - New parameter: ``filter``. - - """ - if file is None: - file = sys.stdout - stats = most_common_types(limit, objects, shortnames=shortnames, - filter=filter) - width = max(len(name) for name, count in stats) - for name, count in stats: - file.write('%-*s %i\n' % (width, name, count)) - - -def growth(limit=10, peak_stats={}, shortnames=True, filter=None): - """Count the increase in peak object since last call. - - Returns a list of (type_name, total_count, increase_delta), - descending order by increase_delta. - - Limits the output to ``limit`` largest deltas. You may set ``limit`` to - None to see all of them. - - Uses and updates ``peak_stats``, a dictionary from type names to previously - seen peak object counts. Usually you don't need to pay attention to this - argument. - - If ``filter`` is specified, it should be a function taking one argument and - returning a boolean. Objects for which ``filter(obj)`` returns ``False`` - will be ignored. - - The caveats documented in :func:`typestats` apply. - - Example: - - >>> growth(2) - [(tuple, 12282, 10), (dict, 1922, 7)] - - .. versionadded:: 3.3.0 - - """ - gc.collect() - stats = typestats(shortnames=shortnames, filter=filter) - deltas = {} - for name, count in iteritems(stats): - old_count = peak_stats.get(name, 0) - if count > old_count: - deltas[name] = count - old_count - peak_stats[name] = count - deltas = sorted(deltas.items(), key=operator.itemgetter(1), - reverse=True) - if limit: - deltas = deltas[:limit] - - return [(name, stats[name], delta) for name, delta in deltas] - - -def show_growth(limit=10, peak_stats=None, shortnames=True, file=None, - filter=None): - """Show the increase in peak object counts since last call. - - if ``peak_stats`` is None, peak object counts will recorded in - func `growth`, and your can record the counts by yourself with set - ``peak_stats`` to a dictionary. - - The caveats documented in :func:`growth` apply. - - Example: - - >>> show_growth() - wrapper_descriptor 970 +14 - tuple 12282 +10 - dict 1922 +7 - ... - - .. versionadded:: 1.5 - - .. versionchanged:: 1.8 - New parameter: ``shortnames``. - - .. versionchanged:: 2.1 - New parameter: ``file``. - - .. versionchanged:: 3.1.3 - New parameter: ``filter``. - - """ - if peak_stats is None: - result = growth(limit, shortnames=shortnames, filter=filter) - else: - result = growth(limit, peak_stats, shortnames, filter) - if result: - if file is None: - file = sys.stdout - width = max(len(name) for name, _, _ in result) - for name, count, delta in result: - file.write('%-*s%9d %+9d\n' % (width, name, count, delta)) - - -def get_new_ids(skip_update=False, limit=10, sortby='deltas', - shortnames=None, file=None, _state={}): - """Find and display new objects allocated since last call. - - Shows the increase in object counts since last call to this - function and returns the memory address ids for new objects. - - Returns a dictionary mapping object type names to sets of object IDs - that have been created since the last time this function was called. - - ``skip_update`` (bool): If True, returns the same dictionary that - was returned during the previous call without updating the internal - state or examining the objects currently in memory. - - ``limit`` (int): The maximum number of rows that you want to print - data for. Use 0 to suppress the printing. Use None to print everything. - - ``sortby`` (str): This is the column that you want to sort by in - descending order. Possible values are: 'old', 'current', 'new', - 'deltas' - - ``shortnames`` (bool): If True, classes with the same name but - defined in different modules will be lumped together. If False, - all type names will be qualified with the module name. If None (default), - ``get_new_ids`` will remember the value from previous calls, so it's - enough to prime this once. By default the primed value is True. - - ``_state`` (dict): Stores old, current, and new_ids in memory. - It is used by the function to store the internal state between calls. - Never pass in this argument unless you know what you're doing. - - The caveats documented in :func:`growth` apply. - - When one gets new_ids from :func:`get_new_ids`, one can use - :func:`at_addrs` to get a list of those objects. Then one can iterate over - the new objects, print out what they are, and call :func:`show_backrefs` or - :func:`show_chain` to see where they are referenced. - - Example: - - >>> _ = get_new_ids() # store current objects in _state - >>> _ = get_new_ids() # current_ids become old_ids in _state - >>> a = [0, 1, 2] # list we don't know about - >>> b = [3, 4, 5] # list we don't know about - >>> new_ids = get_new_ids(limit=3) # we see new lists - ====================================================================== - Type Old_ids Current_ids New_ids Count_Deltas - ====================================================================== - list 324 326 +3 +2 - dict 1125 1125 +0 +0 - wrapper_descriptor 1001 1001 +0 +0 - ====================================================================== - >>> new_lists = at_addrs(new_ids['list']) - >>> a in new_lists - True - >>> b in new_lists - True - - .. versionadded:: 3.4 - """ - if not _state: - _state['old'] = collections.defaultdict(set) - _state['current'] = collections.defaultdict(set) - _state['new'] = collections.defaultdict(set) - _state['shortnames'] = True - new_ids = _state['new'] - if skip_update: - return new_ids - old_ids = _state['old'] - current_ids = _state['current'] - if shortnames is None: - shortnames = _state['shortnames'] - else: - _state['shortnames'] = shortnames - gc.collect() - objects = gc.get_objects() - for class_name in old_ids: - old_ids[class_name].clear() - for class_name, ids_set in current_ids.items(): - old_ids[class_name].update(ids_set) - for class_name in current_ids: - current_ids[class_name].clear() - for o in objects: - if shortnames: - class_name = _short_typename(o) - else: - class_name = _long_typename(o) - id_number = id(o) - current_ids[class_name].add(id_number) - for class_name in new_ids: - new_ids[class_name].clear() - rows = [] - keys_to_remove = [] - for class_name in current_ids: - num_old = len(old_ids[class_name]) - num_current = len(current_ids[class_name]) - if num_old == 0 and num_current == 0: - # remove the key from our dicts if we don't have any old or - # current class_name objects - keys_to_remove.append(class_name) - continue - new_ids_set = current_ids[class_name] - old_ids[class_name] - new_ids[class_name].update(new_ids_set) - num_new = len(new_ids_set) - num_delta = num_current - num_old - row = (class_name, num_old, num_current, num_new, num_delta) - rows.append(row) - for key in keys_to_remove: - del old_ids[key] - del current_ids[key] - del new_ids[key] - index_by_sortby = {'old': 1, 'current': 2, 'new': 3, 'deltas': 4} - rows.sort(key=operator.itemgetter(index_by_sortby[sortby], 0), - reverse=True) - if limit is not None: - rows = rows[:limit] - if not rows: - return new_ids - if file is None: - file = sys.stdout - width = max(len(row[0]) for row in rows) - print('='*(width+13*4), file=file) - print('%-*s%13s%13s%13s%13s' % - (width, 'Type', 'Old_ids', 'Current_ids', 'New_ids', 'Count_Deltas'), - file=file) - print('='*(width+13*4), file=file) - for row_class, old, current, new, delta in rows: - print('%-*s%13d%13d%+13d%+13d' % - (width, row_class, old, current, new, delta), file=file) - print('='*(width+13*4), file=file) - return new_ids - - -def get_leaking_objects(objects=None): - """Return objects that do not have any referents. - - These could indicate reference-counting bugs in C code. Or they could - be legitimate. - - Note that the GC does not track simple objects like int or str. - - .. versionadded:: 1.7 - """ - if objects is None: - gc.collect() - objects = gc.get_objects() - try: - ids = set(id(i) for i in objects) - for i in objects: - ids.difference_update(id(j) for j in gc.get_referents(i)) - # this then is our set of objects without referrers - return [i for i in objects if id(i) in ids] - finally: - del objects, i # clear cyclic references to frame - - -def by_type(typename, objects=None): - """Return objects tracked by the garbage collector with a given class name. - - Example: - - >>> by_type('MyClass') - [] - - Note that the GC does not track simple objects like int or str. - - .. versionchanged:: 1.7 - New parameter: ``objects``. - - .. versionchanged:: 1.8 - Accepts fully-qualified type names (i.e. 'package.module.ClassName') - as well as short type names (i.e. 'ClassName'). - - """ - if objects is None: - objects = gc.get_objects() - try: - if '.' in typename: - return [o for o in objects if _long_typename(o) == typename] - else: - return [o for o in objects if _short_typename(o) == typename] - finally: - del objects # clear cyclic references to frame - - -def at(addr): - """Return an object at a given memory address. - - The reverse of id(obj): - - >>> at(id(obj)) is obj - True - - Note that this function does not work on objects that are not tracked by - the GC (e.g. ints or strings). - """ - for o in gc.get_objects(): - if id(o) == addr: - return o - return None - - -def at_addrs(address_set): - """Return a list of objects for a given set of memory addresses. - - The reverse of [id(obj1), id(obj2), ...]. Note that objects are returned - in an arbitrary order. - - When one gets ``new_ids`` from :func:`get_new_ids`, one can use this - function to get a list of those objects. Then one can iterate over the new - objects, print out what they are, and call :func:`show_backrefs` or - :func:`show_chain` to see where they are referenced. - - >>> a = [0, 1, 2] - >>> new_ids = get_new_ids() - >>> new_lists = at_addrs(new_ids['list']) - >>> a in new_lists - True - - Note that this function does not work on objects that are not tracked - by the GC (e.g. ints or strings). - - .. versionadded:: 3.4 - """ - res = [] - for o in gc.get_objects(): - if id(o) in address_set: - res.append(o) - return res - - -def find_ref_chain(obj, predicate, max_depth=20, extra_ignore=()): - """Find a shortest chain of references leading from obj. - - The end of the chain will be some object that matches your predicate. - - ``predicate`` is a function taking one argument and returning a boolean. - - ``max_depth`` limits the search depth. - - ``extra_ignore`` can be a list of object IDs to exclude those objects from - your search. - - Example: - - >>> find_ref_chain(obj, lambda x: isinstance(x, MyClass)) - [obj, ..., ] - - Returns ``[obj]`` if such a chain could not be found. - - .. versionadded:: 1.7 - """ - return _find_chain(obj, predicate, gc.get_referents, - max_depth=max_depth, extra_ignore=extra_ignore)[::-1] - - -def find_backref_chain(obj, predicate, max_depth=20, extra_ignore=()): - """Find a shortest chain of references leading to obj. - - The start of the chain will be some object that matches your predicate. - - ``predicate`` is a function taking one argument and returning a boolean. - - ``max_depth`` limits the search depth. - - ``extra_ignore`` can be a list of object IDs to exclude those objects from - your search. - - Example: - - >>> find_backref_chain(obj, is_proper_module) - [, ..., obj] - - Returns ``[obj]`` if such a chain could not be found. - - .. versionchanged:: 1.5 - Returns ``obj`` instead of ``None`` when a chain could not be found. - - """ - return _find_chain(obj, predicate, gc.get_referrers, - max_depth=max_depth, extra_ignore=extra_ignore) - - -def show_backrefs(objs, max_depth=3, extra_ignore=(), filter=None, too_many=10, - highlight=None, filename=None, extra_info=None, - refcounts=False, shortnames=True, output=None): - """Generate an object reference graph ending at ``objs``. - - The graph will show you what objects refer to ``objs``, directly and - indirectly. - - ``objs`` can be a single object, or it can be a list of objects. If - unsure, wrap the single object in a new list. - - ``filename`` if specified, can be the name of a .dot or a image - file, whose extension indicates the desired output format; note - that output to a specific format is entirely handled by GraphViz: - if the desired format is not supported, you just get the .dot - file. If ``filename`` and ``output`` are not specified, ``show_backrefs`` - will try to display the graph inline (if you're using IPython), otherwise - it'll try to produce a .dot file and spawn a viewer (xdot). If xdot is - not available, ``show_backrefs`` will convert the .dot file to a - .png and print its name. - - ``output`` if specified, the GraphViz output will be written to this - file object. ``output`` and ``filename`` should not both be specified. - - Use ``max_depth`` and ``too_many`` to limit the depth and breadth of the - graph. - - Use ``filter`` (a predicate) and ``extra_ignore`` (a list of object IDs) to - remove undesired objects from the graph. - - Use ``highlight`` (a predicate) to highlight certain graph nodes in blue. - - Use ``extra_info`` (a function taking one argument and returning a - string) to report extra information for objects. - - Specify ``refcounts=True`` if you want to see reference counts. - These will mostly match the number of arrows pointing to an object, - but can be different for various reasons. - - Specify ``shortnames=False`` if you want to see fully-qualified type - names ('package.module.ClassName'). By default you get to see only the - class name part. - - Examples: - - >>> show_backrefs(obj) - >>> show_backrefs([obj1, obj2]) - >>> show_backrefs(obj, max_depth=5) - >>> show_backrefs(obj, filter=lambda x: not inspect.isclass(x)) - >>> show_backrefs(obj, highlight=inspect.isclass) - >>> show_backrefs(obj, extra_ignore=[id(locals())]) - - .. versionchanged:: 1.3 - New parameters: ``filename``, ``extra_info``. - - .. versionchanged:: 1.5 - New parameter: ``refcounts``. - - .. versionchanged:: 1.8 - New parameter: ``shortnames``. - - .. versionchanged:: 2.0 - New parameter: ``output``. - - """ - # For show_backrefs(), it makes sense to stop when reaching a - # module because you'll end up in sys.modules and explode the - # graph with useless clutter. That's why we're specifying - # cull_func here, but not in show_graph(). - return _show_graph(objs, max_depth=max_depth, extra_ignore=extra_ignore, - filter=filter, too_many=too_many, highlight=highlight, - edge_func=gc.get_referrers, swap_source_target=False, - filename=filename, output=output, extra_info=extra_info, - refcounts=refcounts, shortnames=shortnames, - cull_func=is_proper_module) - - -def show_refs(objs, max_depth=3, extra_ignore=(), filter=None, too_many=10, - highlight=None, filename=None, extra_info=None, - refcounts=False, shortnames=True, output=None): - """Generate an object reference graph starting at ``objs``. - - The graph will show you what objects are reachable from ``objs``, directly - and indirectly. - - ``objs`` can be a single object, or it can be a list of objects. If - unsure, wrap the single object in a new list. - - ``filename`` if specified, can be the name of a .dot or a image - file, whose extension indicates the desired output format; note - that output to a specific format is entirely handled by GraphViz: - if the desired format is not supported, you just get the .dot - file. If ``filename`` and ``output`` is not specified, ``show_refs`` will - try to display the graph inline (if you're using IPython), otherwise it'll - try to produce a .dot file and spawn a viewer (xdot). If xdot is - not available, ``show_refs`` will convert the .dot file to a - .png and print its name. - - ``output`` if specified, the GraphViz output will be written to this - file object. ``output`` and ``filename`` should not both be specified. - - Use ``max_depth`` and ``too_many`` to limit the depth and breadth of the - graph. - - Use ``filter`` (a predicate) and ``extra_ignore`` (a list of object IDs) to - remove undesired objects from the graph. - - Use ``highlight`` (a predicate) to highlight certain graph nodes in blue. - - Use ``extra_info`` (a function returning a string) to report extra - information for objects. - - Specify ``refcounts=True`` if you want to see reference counts. - - Examples: - - >>> show_refs(obj) - >>> show_refs([obj1, obj2]) - >>> show_refs(obj, max_depth=5) - >>> show_refs(obj, filter=lambda x: not inspect.isclass(x)) - >>> show_refs(obj, highlight=inspect.isclass) - >>> show_refs(obj, extra_ignore=[id(locals())]) - - .. versionadded:: 1.1 - - .. versionchanged:: 1.3 - New parameters: ``filename``, ``extra_info``. - - .. versionchanged:: 1.5 - Follows references from module objects instead of stopping. - New parameter: ``refcounts``. - - .. versionchanged:: 1.8 - New parameter: ``shortnames``. - - .. versionchanged:: 2.0 - New parameter: ``output``. - """ - return _show_graph(objs, max_depth=max_depth, extra_ignore=extra_ignore, - filter=filter, too_many=too_many, highlight=highlight, - edge_func=gc.get_referents, swap_source_target=True, - filename=filename, extra_info=extra_info, - refcounts=refcounts, shortnames=shortnames, - output=output) - - -def show_chain(*chains, **kw): - """Show a chain (or several chains) of object references. - - Useful in combination with :func:`find_ref_chain` or - :func:`find_backref_chain`, e.g. - - >>> show_chain(find_backref_chain(obj, is_proper_module)) - - You can specify if you want that chain traced backwards or forwards - by passing a ``backrefs`` keyword argument, e.g. - - >>> show_chain(find_ref_chain(obj, is_proper_module), - ... backrefs=False) - - Ideally this shouldn't matter, but for some objects - :func:`gc.get_referrers` and :func:`gc.get_referents` are not perfectly - symmetrical. - - You can specify ``highlight``, ``extra_info``, ``refcounts``, - ``shortnames``, ``filename`` or ``output`` arguments like for - :func:`show_backrefs` or :func:`show_refs`. - - .. versionadded:: 1.5 - - .. versionchanged:: 1.7 - New parameter: ``backrefs``. - - .. versionchanged:: 2.0 - New parameter: ``output``. - - """ - backrefs = kw.pop('backrefs', True) - chains = [chain for chain in chains if chain] # remove empty ones - - def in_chains(x, ids=set(map(id, itertools.chain(*chains)))): - return id(x) in ids - max_depth = max(map(len, chains)) - 1 - if backrefs: - show_backrefs([chain[-1] for chain in chains], max_depth=max_depth, - filter=in_chains, **kw) - else: - show_refs([chain[0] for chain in chains], max_depth=max_depth, - filter=in_chains, **kw) - - -def is_proper_module(obj): - """ - Returns ``True`` if ``obj`` can be treated like a garbage collector root. - - That is, if ``obj`` is a module that is in ``sys.modules``. - - >>> import types - >>> is_proper_module([]) - False - >>> is_proper_module(types) - True - >>> is_proper_module(types.ModuleType('foo')) - False - - .. versionadded:: 1.8 - """ - return ( - inspect.ismodule(obj) - and obj is sys.modules.get(getattr(obj, '__name__', None)) - ) - - -# -# Internal helpers -# - -def _find_chain(obj, predicate, edge_func, max_depth=20, extra_ignore=()): - queue = [obj] - depth = {id(obj): 0} - parent = {id(obj): None} - ignore = set(extra_ignore) - ignore.add(id(extra_ignore)) - ignore.add(id(queue)) - ignore.add(id(depth)) - ignore.add(id(parent)) - ignore.add(id(ignore)) - ignore.add(id(sys._getframe())) # this function - ignore.add(id(sys._getframe(1))) # find_chain/find_backref_chain - gc.collect() - while queue: - target = queue.pop(0) - if predicate(target): - chain = [target] - while parent[id(target)] is not None: - target = parent[id(target)] - chain.append(target) - return chain - tdepth = depth[id(target)] - if tdepth < max_depth: - referrers = edge_func(target) - ignore.add(id(referrers)) - for source in referrers: - if id(source) in ignore: - continue - if id(source) not in depth: - depth[id(source)] = tdepth + 1 - parent[id(source)] = target - queue.append(source) - return [obj] # not found - - -def _show_graph(objs, edge_func, swap_source_target, - max_depth=3, extra_ignore=(), filter=None, too_many=10, - highlight=None, filename=None, extra_info=None, - refcounts=False, shortnames=True, output=None, - cull_func=None): - if not _isinstance(objs, (list, tuple)): - objs = [objs] - - is_interactive = False - if filename and output: - raise ValueError('Cannot specify both output and filename.') - elif output: - f = output - elif filename and filename.endswith('.dot'): - f = codecs.open(filename, 'w', encoding='utf-8') - dot_filename = filename - elif IS_INTERACTIVE: - is_interactive = True - f = StringIO() - else: - fd, dot_filename = tempfile.mkstemp(prefix='objgraph-', - suffix='.dot', text=True) - f = os.fdopen(fd, "w") - if getattr(f, 'encoding', None): - # Python 3 will wrap the file in the user's preferred encoding - # Re-wrap it for utf-8 - import io - f = io.TextIOWrapper(f.detach(), 'utf-8') - f.write('digraph ObjectGraph {\n' - ' node[shape=box, style=filled, fillcolor=white];\n') - queue = [] - depth = {} - ignore = set(extra_ignore) - ignore.add(id(objs)) - ignore.add(id(extra_ignore)) - ignore.add(id(queue)) - ignore.add(id(depth)) - ignore.add(id(ignore)) - ignore.add(id(sys._getframe())) # this function - ignore.add(id(sys._getframe().f_locals)) - ignore.add(id(sys._getframe(1))) # show_refs/show_backrefs - ignore.add(id(sys._getframe(1).f_locals)) - for obj in objs: - f.write(' %s[fontcolor=red];\n' % (_obj_node_id(obj))) - depth[id(obj)] = 0 - queue.append(obj) - del obj - gc.collect() - nodes = 0 - while queue: - nodes += 1 - # The names "source" and "target" are reversed here because - # originally there was just show_backrefs() and we were - # traversing the reference graph backwards. - target = queue.pop(0) - tdepth = depth[id(target)] - f.write(' %s[label="%s"];\n' % (_obj_node_id(target), - _obj_label(target, extra_info, - refcounts, shortnames))) - h, s, v = _gradient((0, 0, 1), (0, 0, .3), tdepth, max_depth) - if inspect.ismodule(target): - h = .3 - s = 1 - if highlight and highlight(target): - h = .6 - s = .6 - v = 0.5 + v * 0.5 - f.write(' %s[fillcolor="%g,%g,%g"];\n' - % (_obj_node_id(target), h, s, v)) - if v < 0.5: - f.write(' %s[fontcolor=white];\n' % (_obj_node_id(target))) - if hasattr(getattr(target, '__class__', None), '__del__'): - f.write(' %s->%s_has_a_del[color=red,style=dotted,' - 'len=0.25,weight=10];\n' % (_obj_node_id(target), - _obj_node_id(target))) - f.write(' %s_has_a_del[label="__del__",shape=doublecircle,' - 'height=0.25,color=red,fillcolor="0,.5,1",fontsize=6];\n' - % (_obj_node_id(target))) - if tdepth >= max_depth: - continue - if cull_func is not None and cull_func(target): - continue - neighbours = edge_func(target) - ignore.add(id(neighbours)) - n = 0 - skipped = 0 - for source in neighbours: - if id(source) in ignore: - continue - if filter and not filter(source): - continue - if n >= too_many: - skipped += 1 - continue - if swap_source_target: - srcnode, tgtnode = target, source - else: - srcnode, tgtnode = source, target - elabel = _edge_label(srcnode, tgtnode, shortnames) - f.write(' %s -> %s%s;\n' % (_obj_node_id(srcnode), - _obj_node_id(tgtnode), elabel)) - if id(source) not in depth: - depth[id(source)] = tdepth + 1 - queue.append(source) - n += 1 - del source - del neighbours - if skipped > 0: - h, s, v = _gradient((0, 1, 1), (0, 1, .3), tdepth + 1, max_depth) - if swap_source_target: - label = "%d more references" % skipped - edge = "%s->too_many_%s" % (_obj_node_id(target), - _obj_node_id(target)) - else: - label = "%d more backreferences" % skipped - edge = "too_many_%s->%s" % (_obj_node_id(target), - _obj_node_id(target)) - f.write(' %s[color=red,style=dotted,len=0.25,weight=10];\n' - % edge) - f.write(' too_many_%s[label="%s",shape=box,height=0.25,' - 'color=red,fillcolor="%g,%g,%g",fontsize=6];\n' - % (_obj_node_id(target), label, h, s, v)) - f.write(' too_many_%s[fontcolor=white];\n' - % (_obj_node_id(target))) - f.write("}\n") - - if output: - return - - if is_interactive: - return graphviz.Source(f.getvalue()) - else: - # The file should only be closed if this function was in charge of - # opening the file. - f.close() - print("Graph written to %s (%d nodes)" % (dot_filename, nodes)) - _present_graph(dot_filename, filename) - - -def _present_graph(dot_filename, filename=None): - """Present a .dot file to the user in the requested fashion. - - If ``filename`` is provided, runs ``dot`` to convert the .dot file - into the desired format, determined by the filename extension. - - If ``filename`` is not provided, tries to launch ``xdot``, a - graphical .dot file viewer. If ``xdot`` is not present on the system, - converts the graph to a PNG. - """ - if filename == dot_filename: - # nothing to do, the user asked for a .dot file and got it - return - if not filename and _program_in_path('xdot'): - print("Spawning graph viewer (xdot)") - subprocess.Popen(['xdot', dot_filename], close_fds=True) - elif _program_in_path('dot'): - if not filename: - print("Graph viewer (xdot) not found, generating a png instead") - filename = dot_filename[:-4] + '.png' - stem, ext = os.path.splitext(filename) - cmd = ['dot', '-T' + ext[1:], '-o' + filename, dot_filename] - dot = subprocess.Popen(cmd, close_fds=False) - dot.wait() - if dot.returncode != 0: - # XXX: shouldn't this go to stderr or a log? - print('dot failed (exit code %d) while executing "%s"' - % (dot.returncode, ' '.join(cmd))) - else: - print("Image generated as %s" % filename) - else: - if not filename: - print("Graph viewer (xdot) and image renderer (dot) not found," - " not doing anything else") - else: - print("Image renderer (dot) not found, not doing anything else") - - -def _obj_node_id(obj): - return ('o%d' % id(obj)).replace('-', '_') - - -def _obj_label(obj, extra_info=None, refcounts=False, shortnames=True): - if shortnames: - label = [_short_typename(obj)] - else: - label = [_long_typename(obj)] - if refcounts: - label[0] += ' [%d]' % (sys.getrefcount(obj) - 4) - # Why -4? To ignore the references coming from - # obj_label's frame (obj) - # show_graph's frame (target variable) - # sys.getrefcount()'s argument - # something else that doesn't show up in gc.get_referrers() - label.append(_safe_repr(obj)) - if extra_info: - label.append(str(extra_info(obj))) - return _quote('\n'.join(label)) - - -def _quote(s): - return (s.replace("\\", "\\\\") - .replace("\"", "\\\"") - .replace("\n", "\\n") - .replace("\0", "\\\\0")) - - -def _get_obj_type(obj): - objtype = type(obj) - if type(obj) == InstanceType: - objtype = obj.__class__ - return objtype - - -def _short_typename(obj): - return _get_obj_type(obj).__name__ - - -def _long_typename(obj): - objtype = _get_obj_type(obj) - name = objtype.__name__ - module = getattr(objtype, '__module__', None) - if module: - return '%s.%s' % (module, name) - else: - return name - - -def _safe_repr(obj): - try: - return _short_repr(obj) - except Exception: - return '(unrepresentable)' - - -def _name_or_repr(value): - try: - result = value.__name__ - except AttributeError: - result = repr(value)[:40] - - if _isinstance(result, basestring): - return result - else: - return repr(value)[:40] - - -def _short_repr(obj): - if _isinstance(obj, (type, types.ModuleType, types.BuiltinMethodType, - types.BuiltinFunctionType)): - return _name_or_repr(obj) - if _isinstance(obj, types.MethodType): - name = _name_or_repr(obj.__func__) - if obj.__self__: - return name + ' (bound)' - else: - return name - # NB: types.LambdaType is an alias for types.FunctionType! - if _isinstance(obj, types.LambdaType) and obj.__name__ == '': - return 'lambda: %s:%s' % (os.path.basename(obj.__code__.co_filename), - obj.__code__.co_firstlineno) - if _isinstance(obj, types.FrameType): - return '%s:%s' % (obj.f_code.co_filename, obj.f_lineno) - if _isinstance(obj, (tuple, list, dict, set)): - return '%d items' % len(obj) - return repr(obj)[:40] - - -def _gradient(start_color, end_color, depth, max_depth): - if max_depth == 0: - # avoid division by zero - return start_color - h1, s1, v1 = start_color - h2, s2, v2 = end_color - f = float(depth) / max_depth - h = h1 * (1-f) + h2 * f - s = s1 * (1-f) + s2 * f - v = v1 * (1-f) + v2 * f - return h, s, v - - -def _edge_label(source, target, shortnames=True): - if (_isinstance(target, dict) - and target is getattr(source, '__dict__', None)): - return ' [label="__dict__",weight=10]' - if _isinstance(source, types.FrameType): - if target is source.f_locals: - return ' [label="f_locals",weight=10]' - if target is source.f_globals: - return ' [label="f_globals",weight=10]' - if _isinstance(source, types.MethodType): - try: - if target is source.__self__: - return ' [label="__self__",weight=10]' - if target is source.__func__: - return ' [label="__func__",weight=10]' - except AttributeError: # pragma: nocover - # Python < 2.6 compatibility - if target is source.im_self: - return ' [label="im_self",weight=10]' - if target is source.im_func: - return ' [label="im_func",weight=10]' - if _isinstance(source, types.FunctionType): - for k in dir(source): - if target is getattr(source, k): - return ' [label="%s",weight=10]' % _quote(k) - if _isinstance(source, dict): - for k, v in iteritems(source): - if v is target: - if _isinstance(k, basestring) and _is_identifier(k): - return ' [label="%s",weight=2]' % _quote(k) - else: - if shortnames: - tn = _short_typename(k) - else: - tn = _long_typename(k) - return ' [label="%s"]' % _quote(tn + "\n" + _safe_repr(k)) - return '' - - -_is_identifier = re.compile('[a-zA-Z_][a-zA-Z_0-9]*$').match - - -def _program_in_path(program): - # XXX: Consider using distutils.spawn.find_executable or shutil.which - path = os.environ.get("PATH", os.defpath).split(os.pathsep) - path = [os.path.join(dir, program) for dir in path] - path = [True for file in path - if os.path.isfile(file) or os.path.isfile(file + '.exe')] - return bool(path) diff --git a/src/py/bbctrl/Planner.py b/src/py/bbctrl/Planner.py index fe27066..4fb77c0 100644 --- a/src/py/bbctrl/Planner.py +++ b/src/py/bbctrl/Planner.py @@ -1,46 +1,16 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - +from bbctrl.CommandQueue import CommandQueue +import bbctrl.Cmd as Cmd +import camotics.gplan as gplan # pylint: disable=no-name-in-module,import-error import json import math import re import time -from collections import deque -import camotics.gplan as gplan # pylint: disable=no-name-in-module,import-error -import bbctrl.Cmd as Cmd -from bbctrl.CommandQueue import CommandQueue - -reLogLine = re.compile( - r'^(?P[A-Z])[0-9 ]:' - r'((?P[^:]+):)?' - r'((?P\d+):)?' - r'((?P\d+):)?' - r'(?P.*)$') +reLogLine = re.compile(r'^(?P[A-Z])[0-9 ]:' + r'((?P[^:]+):)?' + r'((?P\d+):)?' + r'((?P\d+):)?' + r'(?P.*)$') def log_floats(o): @@ -50,10 +20,12 @@ def log_floats(o): return o -def log_json(o): return json.dumps(log_floats(o)) +def log_json(o): + return json.dumps(log_floats(o)) class Planner(): + def __init__(self, ctrl): self.ctrl = ctrl self.log = ctrl.log.get('Planner') @@ -64,21 +36,23 @@ class Planner(): ctrl.state.add_listener(self._update) - self.reset(stop = False) + self.reset(stop=False) self._report_time() + def is_busy(self): + return self.is_running() or self.cmdq.is_active() - def is_busy(self): return self.is_running() or self.cmdq.is_active() - def is_running(self): return self.planner.is_running() - def position_change(self): self._position_dirty = True + def is_running(self): + return self.planner.is_running() + def position_change(self): + self._position_dirty = True - def _sync_position(self, force = False): + def _sync_position(self, force=False): if not force and not self._position_dirty: return self._position_dirty = False self.planner.set_position(self.ctrl.state.get_position()) - def get_config(self, mdi, with_limits): state = self.ctrl.state config = self.ctrl.config @@ -88,21 +62,22 @@ class Planner(): cfg = { # NOTE Must get current units not configured default units 'default-units': 'METRIC' if state.get('metric') else 'IMPERIAL', - 'max-vel': state.get_axis_vector('vm', 1000), + 'max-vel': state.get_axis_vector('vm', 1000), 'max-accel': state.get_axis_vector('am', 1000000), - 'max-jerk': state.get_axis_vector('jm', 1000000), - 'rapid-auto-off': config.get('rapid-auto-off') and is_pwm, + 'max-jerk': state.get_axis_vector('jm', 1000000), + 'rapid-auto-off': config.get('rapid-auto-off') and is_pwm, 'max-blend-error': deviation, 'max-merge-error': deviation, - 'max-arc-error': deviation / 10, - 'junction-accel': config.get('junction-accel'), + 'max-arc-error': deviation / 10, + 'junction-accel': config.get('junction-accel'), } # We place an upper limit of 1000 km/min^3 on jerk for MDI movements if mdi: for axis in 'xyzabc': if axis in cfg['max-jerk']: - cfg['max-jerk'][axis] = min(1000 * 1000000, cfg['max-jerk'][axis]) + cfg['max-jerk'][axis] = min(1000 * 1000000, + cfg['max-jerk'][axis]) if with_limits: minLimit = state.get_soft_limit_vector('tn', -math.inf) @@ -134,13 +109,11 @@ class Planner(): return cfg - def _update(self, update): if 'id' in update: id = update['id'] - self.planner.set_active(id) # Release planner commands - self.cmdq.release(id) # Synchronize planner variables - + self.planner.set_active(id) # Release planner commands + self.cmdq.release(id) # Synchronize planner variables def _get_var_cb(self, name, units): value = 0 @@ -149,37 +122,36 @@ class Planner(): value = self.ctrl.state.get(name[1:], 0) try: float(value) - if units == 'IMPERIAL': value /= 25.4 # Assume metric - except ValueError: value = 0 + if units == 'IMPERIAL': value /= 25.4 # Assume metric + except ValueError: + value = 0 self.log.info('Get: %s=%s (units=%s)' % (name, value, units)) return value - def _log_cb(self, line): line = line.strip() m = reLogLine.match(line) if not m: return - level = m.group('level') - msg = m.group('msg') + level = m.group('level') + msg = m.group('msg') filename = m.group('file') - line = m.group('line') - column = m.group('column') + line = m.group('line') + column = m.group('column') where = ':'.join(filter(None.__ne__, [filename, line, column])) if line is not None: line = int(line) if column is not None: column = int(column) - if level == 'I': self.log.info (msg, where = where) - elif level == 'D': self.log.debug (msg, where = where) - elif level == 'W': self.log.warning (msg, where = where) - elif level == 'E': self.log.error (msg, where = where) + if level == 'I': self.log.info(msg, where=where) + elif level == 'D': self.log.debug(msg, where=where) + elif level == 'W': self.log.warning(msg, where=where) + elif level == 'E': self.log.error(msg, where=where) else: self.log.error('Could not parse planner log line: ' + line) - def _add_message(self, text): self.ctrl.state.add_message(text) @@ -187,14 +159,12 @@ class Planner(): if 0 <= line: where = '%s:%d' % (self.where, line) else: where = self.where - self.log.message(text, where = where) - + self.log.message(text, where=where) def _enqueue_set_cmd(self, id, name, value): self.log.info('set(#%d, %s, %s)', id, name, value) self.cmdq.enqueue(id, self.ctrl.state.set, name, value) - def _report_time(self): state = self.ctrl.state.get('xx', '') @@ -205,39 +175,35 @@ class Planner(): self.ctrl.state.set('plan_time', round(plan_time)) - elif state != 'HOLDING': self.ctrl.state.set('plan_time', 0) + elif state != 'HOLDING': + self.ctrl.state.set('plan_time', 0) self.ctrl.ioloop.call_later(1, self._report_time) - def _plan_time_restart(self): self.plan_time = self.ctrl.state.get('plan_time', 0) - def _update_time(self, plan_time, move_time): self.current_plan_time = plan_time self.move_time = move_time self.move_start = time.time() - def _enqueue_line_time(self, block): if block.get('first', False) or block.get('seeking', False): return # Sum move times - move_time = sum(block['times']) / 1000 # To seconds + move_time = sum(block['times']) / 1000 # To seconds self.cmdq.enqueue(block['id'], self._update_time, self.plan_time, move_time) self.plan_time += move_time - def _enqueue_dwell_time(self, block): self.cmdq.enqueue(block['id'], self._update_time, self.plan_time, block['seconds']) self.plan_time += block['seconds'] - def __encode(self, block): type, id = block['type'], block['id'] @@ -266,7 +232,7 @@ class Planner(): if len(name) != 2 or name[1] not in 'xyzabc': self._enqueue_set_cmd(id, name[1:], value) - if name == '_feed': # Must come after _enqueue_set_cmd() above + if name == '_feed': # Must come after _enqueue_set_cmd() above return Cmd.set_sync('if', 1 / value if value else 0) if name[0:1] == '_' and name[1:2] in 'xyzabc': @@ -281,7 +247,7 @@ class Planner(): if type == 'input': # TODO handle timeout - self.planner.synchronize(0) # TODO Fix this + self.planner.synchronize(0) # TODO Fix this return Cmd.input(block['port'], block['mode'], block['timeout']) if type == 'output': @@ -297,11 +263,10 @@ class Planner(): sw = self.ctrl.state.get_switch_id(block['switch']) return Cmd.seek(sw, block['active'], block['error']) - if type == 'end': return '' # Sends id + if type == 'end': return '' # Sends id raise Exception('Unknown planner command "%s"' % type) - def _encode(self, block): cmd = self.__encode(block) @@ -309,21 +274,18 @@ class Planner(): self.cmdq.enqueue(block['id'], None) return Cmd.set_sync('id', block['id']) + '\n' + cmd - def reset_times(self): self.move_start = 0 self.move_time = 0 self.plan_time = 0 self.current_plan_time = 0 - def close(self): # Release planner callbacks if self.planner is not None: self.planner.set_resolver(None) self.planner.set_logger(None) - def reset(self, *args, **kwargs): stop = kwargs.get('stop', True) if stop: @@ -341,15 +303,13 @@ class Planner(): if resetState: self.ctrl.state.reset() - - def mdi(self, cmd, with_limits = True): + def mdi(self, cmd, with_limits=True): self.where = '' self.log.info('MDI:' + cmd) self._sync_position() self.planner.load_string(cmd, self.get_config(True, with_limits)) self.reset_times() - def load(self, path): self.where = path path = self.ctrl.get_path('upload', path) @@ -358,7 +318,6 @@ class Planner(): self.planner.load(path, self.get_config(False, True)) self.reset_times() - def stop(self): try: self.planner.stop() @@ -368,7 +327,6 @@ class Planner(): self.log.exception('Internal error: Planner stop') self.reset() - def restart(self): try: id = self.ctrl.state.get('id') @@ -385,7 +343,6 @@ class Planner(): self.log.exception('Internal error: Planner restart') self.stop() - def next(self): try: while self.planner.has_more(): diff --git a/src/py/bbctrl/Preplanner.py b/src/py/bbctrl/Preplanner.py index 094fe9a..1b3b5ce 100644 --- a/src/py/bbctrl/Preplanner.py +++ b/src/py/bbctrl/Preplanner.py @@ -1,44 +1,16 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import os -import time -import json -import hashlib -import glob -import tempfile -import signal from concurrent.futures import Future from tornado import gen, process, iostream import bbctrl +import glob +import hashlib +import json +import os +import signal +import tempfile def hash_dump(o): - s = json.dumps(o, separators = (',', ':'), sort_keys = True) + s = json.dumps(o, separators=(',', ':'), sort_keys=True) return s.encode('utf8') @@ -59,10 +31,12 @@ def plan_hash(path, config): def safe_remove(path): try: os.unlink(path) - except: pass + except: + pass class Plan(object): + def __init__(self, preplanner, ctrl, filename): self.preplanner = preplanner @@ -81,29 +55,27 @@ class Plan(object): self.hid = plan_hash(self.gcode, self.config) fbase = '%s.%s.' % (self.base, self.hid) self.files = [ - fbase + 'json', - fbase + 'positions.gz', - fbase + 'speeds.gz'] + fbase + 'json', fbase + 'positions.gz', fbase + 'speeds.gz' + ] self.future = Future() ctrl.ioloop.add_callback(self._load) - def terminate(self): if self.cancel: return self.cancel = True if self.pid is not None: try: os.kill(self.pid, signal.SIGKILL) - except: pass - + except: + pass def delete(self): files = glob.glob(self.base + '.*') - for path in files: safe_remove(path) + for path in files: + safe_remove(path) - - def clean(self, max = 2): + def clean(self, max=2): plans = glob.glob(self.base + '.*.json') if len(plans) <= max: return @@ -116,20 +88,21 @@ class Plan(object): safe_remove(path[:-4] + 'positions.gz') safe_remove(path[:-4] + 'speeds.gz') - def _exists(self): for path in self.files: if not os.path.exists(path): return False return True - def _read(self): if self.cancel: return try: - with open(self.files[0], 'r') as f: meta = json.load(f) - with open(self.files[1], 'rb') as f: positions = f.read() - with open(self.files[2], 'rb') as f: speeds = f.read() + with open(self.files[0], 'r') as f: + meta = json.load(f) + with open(self.files[1], 'rb') as f: + positions = f.read() + with open(self.files[2], 'rb') as f: + speeds = f.read() return meta, positions, speeds @@ -141,26 +114,23 @@ class Plan(object): if os.path.exists(path): os.remove(path) - @gen.coroutine def _exec(self): - self.clean() # Clean up old plans + self.clean() # Clean up old plans with tempfile.TemporaryDirectory() as tmpdir: - cmd = ( - '/usr/bin/env', 'python3', - bbctrl.get_resource('plan.py'), - os.path.abspath(self.gcode), json.dumps(self.state), - json.dumps(self.config), - '--max-time=%s' % self.preplanner.max_plan_time, - '--max-loop=%s' % self.preplanner.max_loop_time - ) + cmd = ('/usr/bin/env', 'python3', bbctrl.get_resource('plan.py'), + os.path.abspath(self.gcode), json.dumps(self.state), + json.dumps(self.config), + '--max-time=%s' % self.preplanner.max_plan_time, + '--max-loop=%s' % self.preplanner.max_loop_time) self.preplanner.log.info('Running: %s', cmd) - proc = process.Subprocess(cmd, stdout = process.Subprocess.STREAM, - stderr = process.Subprocess.STREAM, - cwd = tmpdir) + proc = process.Subprocess(cmd, + stdout=process.Subprocess.STREAM, + stderr=process.Subprocess.STREAM, + cwd=tmpdir) errs = '' self.pid = proc.proc.pid @@ -170,7 +140,8 @@ class Plan(object): line = yield proc.stdout.read_until(b'\n') self.progress = float(line.strip()) if self.cancel: return - except iostream.StreamClosedError: pass + except iostream.StreamClosedError: + pass self.progress = 1 @@ -184,12 +155,11 @@ class Plan(object): proc.stdout.close() if not self.cancel: - os.rename(tmpdir + '/meta.json', self.files[0]) + os.rename(tmpdir + '/meta.json', self.files[0]) os.rename(tmpdir + '/positions.gz', self.files[1]) - os.rename(tmpdir + '/speeds.gz', self.files[2]) + os.rename(tmpdir + '/speeds.gz', self.files[2]) os.sync() - @gen.coroutine def _load(self): try: @@ -203,11 +173,13 @@ class Plan(object): self.future.set_result(self._read()) except: - self.preplanner.log.exception("Failed to load file - doesn't appear to be GCode.") + self.preplanner.log.exception( + "Failed to load file - doesn't appear to be GCode.") class Preplanner(object): - def __init__(self, ctrl, max_plan_time = 60 * 60 * 24, max_loop_time = 300): + + def __init__(self, ctrl, max_plan_time=60 * 60 * 24, max_loop_time=300): self.ctrl = ctrl self.log = ctrl.log.get('Preplanner') @@ -220,31 +192,27 @@ class Preplanner(object): self.started = Future() self.plans = {} - def start(self): if not self.started.done(): self.log.info('Preplanner started') self.started.set_result(True) - def invalidate(self, filename): if filename in self.plans: self.plans[filename].terminate() del self.plans[filename] - def invalidate_all(self): for filename, plan in self.plans.items(): plan.terminate() self.plans = {} - def delete_all_plans(self): files = glob.glob(self.ctrl.get_plan('*')) - for path in files: safe_remove(path) + for path in files: + safe_remove(path) self.invalidate_all() - def delete_plans(self, filename): if filename in self.plans: self.plans[filename].delete() @@ -265,6 +233,5 @@ class Preplanner(object): data = yield plan.future return data - def get_plan_progress(self, filename): return self.plans[filename].progress if filename in self.plans else 0 diff --git a/src/py/bbctrl/Pwr.py b/src/py/bbctrl/Pwr.py index 9c4579a..10a4d60 100644 --- a/src/py/bbctrl/Pwr.py +++ b/src/py/bbctrl/Pwr.py @@ -1,79 +1,49 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import bbctrl import bbctrl.Cmd as Cmd - # Must match regs in pwr firmware -TEMP_REG = 0 -VIN_REG = 1 -VOUT_REG = 2 -MOTOR_REG = 3 -LOAD1_REG = 4 -LOAD2_REG = 5 -VDD_REG = 6 -FLAGS_REG = 7 -VERSION_REG = 8 +TEMP_REG = 0 +VIN_REG = 1 +VOUT_REG = 2 +MOTOR_REG = 3 +LOAD1_REG = 4 +LOAD2_REG = 5 +VDD_REG = 6 +FLAGS_REG = 7 +VERSION_REG = 8 # Must be kept in sync with pwr firmware -UNDER_VOLTAGE_FLAG = 1 << 0 -OVER_VOLTAGE_FLAG = 1 << 1 -OVER_CURRENT_FLAG = 1 << 2 -SENSE_ERROR_FLAG = 1 << 3 -SHUNT_OVERLOAD_FLAG = 1 << 4 -MOTOR_OVERLOAD_FLAG = 1 << 5 -LOAD1_SHUTDOWN_FLAG = 1 << 6 -LOAD2_SHUTDOWN_FLAG = 1 << 7 -MOTOR_UNDER_VOLTAGE_FLAG = 1 << 8 +UNDER_VOLTAGE_FLAG = 1 << 0 +OVER_VOLTAGE_FLAG = 1 << 1 +OVER_CURRENT_FLAG = 1 << 2 +SENSE_ERROR_FLAG = 1 << 3 +SHUNT_OVERLOAD_FLAG = 1 << 4 +MOTOR_OVERLOAD_FLAG = 1 << 5 +LOAD1_SHUTDOWN_FLAG = 1 << 6 +LOAD2_SHUTDOWN_FLAG = 1 << 7 +MOTOR_UNDER_VOLTAGE_FLAG = 1 << 8 MOTOR_VOLTAGE_SENSE_ERROR_FLAG = 1 << 9 MOTOR_CURRENT_SENSE_ERROR_FLAG = 1 << 10 -LOAD1_SENSE_ERROR_FLAG = 1 << 11 -LOAD2_SENSE_ERROR_FLAG = 1 << 12 -VDD_CURRENT_SENSE_ERROR_FLAG = 1 << 13 -POWER_SHUTDOWN_FLAG = 1 << 14 -SHUNT_ERROR_FLAG = 1 << 15 +LOAD1_SENSE_ERROR_FLAG = 1 << 11 +LOAD2_SENSE_ERROR_FLAG = 1 << 12 +VDD_CURRENT_SENSE_ERROR_FLAG = 1 << 13 +POWER_SHUTDOWN_FLAG = 1 << 14 +SHUNT_ERROR_FLAG = 1 << 15 reg_names = 'temp vin vout motor load1 load2 vdd pwr_flags pwr_version'.split() class Pwr(): + def __init__(self, ctrl): self.ctrl = ctrl self.log = ctrl.log.get('Pwr') self.i2c_addr = ctrl.args.pwr_addr self.regs = [-1] * 9 - self.lcd_page = ctrl.lcd.add_new_page() self.failures = 0 self._update_cb(False) - def check_fault(self, var, status): status = bool(status) @@ -83,7 +53,6 @@ class Pwr(): return False - def check_faults(self): flags = self.regs[FLAGS_REG] @@ -142,19 +111,17 @@ class Pwr(): if self.check_fault('shunt_error', flags & SHUNT_ERROR_FLAG): self.log.warning('Shunt error') - - def _update_cb(self, now = True): + def _update_cb(self, now=True): if now: self._update() self.ctrl.ioloop.call_later(1, self._update_cb) - def _update(self): update = {} try: for i in range(len(self.regs)): value = self.ctrl.i2c.read_word(self.i2c_addr + i) - if value is None: return # Handle lack of i2c port + if value is None: return # Handle lack of i2c port if i == TEMP_REG: value -= 273 elif i == FLAGS_REG or i == VERSION_REG: pass @@ -170,7 +137,7 @@ class Pwr(): if i == FLAGS_REG: self.check_faults() except Exception as e: - if i < 6: # Older pwr firmware does not have regs > 5 + if i < 6: # Older pwr firmware does not have regs > 5 self.failures += 1 msg = 'Pwr communication failed at reg %d: %s' % (i, e) if self.failures != 5: self.log.info(msg) @@ -179,16 +146,6 @@ class Pwr(): self.failures = 0 return - self.lcd_page.text('%3dC Tmp' % self.regs[TEMP_REG], 0, 0) - self.lcd_page.text('%5.1fV In' % self.regs[VIN_REG], 0, 1) - self.lcd_page.text('%5.1fV Out' % self.regs[VOUT_REG], 0, 2) - self.lcd_page.text(' %04x Flg' % self.regs[FLAGS_REG], 0, 3) - - self.lcd_page.text('%5.1fA Mot' % self.regs[MOTOR_REG], 10, 0) - self.lcd_page.text('%5.1fA Ld1' % self.regs[LOAD1_REG], 10, 1) - self.lcd_page.text('%5.1fA Ld2' % self.regs[LOAD2_REG], 10, 2) - self.lcd_page.text('%5.1fA Vdd' % self.regs[VDD_REG], 10, 3) - if len(update): self.ctrl.state.update(update) self.failures = 0 diff --git a/src/py/bbctrl/RequestHandler.py b/src/py/bbctrl/RequestHandler.py index 771b4fd..99f6b5d 100644 --- a/src/py/bbctrl/RequestHandler.py +++ b/src/py/bbctrl/RequestHandler.py @@ -1,59 +1,32 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import traceback -import bbctrl - from tornado.web import HTTPError +import bbctrl import tornado.web +import traceback class RequestHandler(tornado.web.RequestHandler): + def __init__(self, app, request, **kwargs): super().__init__(app, request, **kwargs) self.app = app + def get_ctrl(self): + return self.app.get_ctrl(self.get_cookie('client-id')) - def get_ctrl(self): return self.app.get_ctrl(self.get_cookie('client-id')) - def get_log(self, name = 'API'): return self.get_ctrl().log.get(name) + def get_log(self, name='API'): + return self.get_ctrl().log.get(name) - - def get_path(self, path = None, filename = None): + def get_path(self, path=None, filename=None): return self.get_ctrl().get_path(path, filename) - - def get_upload(self, filename = None): + def get_upload(self, filename=None): return self.get_ctrl().get_upload(filename) - # Override exception logging def log_exception(self, typ, value, tb): - if (isinstance(value, HTTPError) and - 400 <= value.status_code and value.status_code < 500): return + if (isinstance(value, HTTPError) and 400 <= value.status_code + and value.status_code < 500): + return log = self.get_log() log.set_level(bbctrl.log.DEBUG) diff --git a/src/py/bbctrl/State.py b/src/py/bbctrl/State.py index e4c4212..b988850 100644 --- a/src/py/bbctrl/State.py +++ b/src/py/bbctrl/State.py @@ -1,48 +1,38 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import traceback -import copy -import uuid -import os -import bbctrl -from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler +from watchdog.observers import Observer +import copy +import iw_parse +import json +import os +import socket +import subprocess +import threading +import time +import traceback +import uuid + + +def call_get_output(cmd): + p = subprocess.Popen(cmd, stdout=subprocess.PIPE) + s = p.communicate()[0].decode('utf-8') + if p.returncode: + raise HTTPError(400, 'Command failed') + return s + class UploadChangeHandler(FileSystemEventHandler): + def __init__(self, state): self.state = state - def on_any_event(self, event): + def on_any_event(self, event): self.state.load_files() class State(object): + def __init__(self, ctrl): + self.lock = threading.Lock() self.ctrl = ctrl self.log = ctrl.log.get('State') @@ -70,52 +60,67 @@ class State(object): # the planner will scale returned values when in imperial mode. for i in range(4): self.set_callback(str(i) + 'home_position', - lambda name, i = i: self.motor_home_position(i)) + lambda name, i=i: self.motor_home_position(i)) self.set_callback(str(i) + 'home_travel', - lambda name, i = i: self.motor_home_travel(i)) + lambda name, i=i: self.motor_home_travel(i)) self.set_callback(str(i) + 'latch_backoff', - lambda name, i = i: self.motor_latch_backoff(i)) + lambda name, i=i: self.motor_latch_backoff(i)) self.set_callback(str(i) + 'zero_backoff', - lambda name, i = i: self.motor_zero_backoff(i)) + lambda name, i=i: self.motor_zero_backoff(i)) self.set_callback(str(i) + 'search_velocity', - lambda name, i = i: self.motor_search_velocity(i)) + lambda name, i=i: self.motor_search_velocity(i)) self.set_callback(str(i) + 'latch_velocity', - lambda name, i = i: self.motor_latch_velocity(i)) - - #self.set_callback('metric', lambda name: 1 if self.is_metric() else 0) - #self.set_callback('imperial', lambda name: 0 if self.is_metric() else 1) + lambda name, i=i: self.motor_latch_velocity(i)) self.reset() self.load_files() observer = Observer() - observer.schedule(UploadChangeHandler(self), self.ctrl.get_upload(), recursive=True) + observer.schedule(UploadChangeHandler(self), + self.ctrl.get_upload(), + recursive=True) observer.start() + threading.Thread(target=self._updateNetworkInfo, daemon=True).start() - def init(self): - # Init machine units - metric = self.ctrl.config.get('units', 'METRIC').upper() == 'METRIC' - self.log.info('INIT Metric %d' % metric) - if not 'metric' in self.vars: self.set('metric', metric) - if not 'imperial' in self.vars: self.set('imperial', not metric) - - # Bit diameter for probing - diameter = self.ctrl.config.get('probe-diameter', 6.35) - self.log.info('INIT Diameter %f' % diameter) - self.set('bitDiameter',diameter) + def _updateNetworkInfo(self): + while True: + try: + ipAddresses = call_get_output(['hostname', '-I']).split() + except: + ipAddresses = "" + hostname = socket.gethostname() + + try: + wifi = json.loads(call_get_output(['config-wifi', '-j'])) + except: + wifi = {'enabled': False} + + try: + lines = iw_parse.call_iwlist().decode("utf-8").split("\n") + wifi['networks'] = iw_parse.get_parsed_cells(lines) + except: + wifi['networks'] = [] + + self.set('networkInfo', { + 'ipAddresses': ipAddresses, + 'hostname': hostname, + 'wifi': wifi + }) + + time.sleep(5) def reset(self): # Unhome all motors - for i in range(4): self.set('%dhomed' % i, False) + for i in range(4): + self.set('%dhomed' % i, False) # Zero offsets and positions for axis in 'xyzabc': self.set(axis + 'p', 0) self.set('offset_' + axis, 0) - def load_files(self): files = [] @@ -123,8 +128,6 @@ class State(object): if not os.path.exists(upload): os.mkdir(upload) - from shutil import copy - copy(bbctrl.get_resource('http/buildbotics.nc'), upload) for path in os.listdir(upload): if os.path.isfile(upload + '/' + path): @@ -133,15 +136,15 @@ class State(object): files.sort() self.set('files', files) - if len(files): self.select_file(files[0]) - else: self.select_file('') - + if len(files): + self.select_file(files[0]) + else: + self.select_file('') def clear_files(self): self.select_file('') self.set('files', []) - def add_file(self, filename): files = copy.deepcopy(self.get('files')) if not filename in files: @@ -151,7 +154,6 @@ class State(object): self.select_file(filename) - def remove_file(self, filename): files = copy.deepcopy(self.get('files')) if filename in files: @@ -159,16 +161,16 @@ class State(object): self.set('files', files) if self.get('selected', filename) == filename: - if len(files): self.select_file(files[0]) - else: self.select_file('') - + if len(files): + self.select_file(files[0]) + else: + self.select_file('') def select_file(self, filename): self.set('selected', filename) time = os.path.getmtime(self.ctrl.get_upload(filename)) self.set('selected_time', time) - def set_bounds(self, bounds): for axis in 'xyzabc': for name in ('min', 'max'): @@ -176,24 +178,22 @@ class State(object): value = bounds[name][axis] if axis in bounds[name] else 0 self.set(var, value) - def ack_message(self, id): self.log.info('Message %d acknowledged' % id) msgs = self.vars['messages'] msgs = list(filter(lambda m: id < m['id'], msgs)) self.set('messages', msgs) - def add_message(self, text): - msg = dict(text = text, id = self.message_id) + msg = dict(text=text, id=self.message_id) self.message_id += 1 msgs = self.vars['messages'] - msgs = msgs + [msg] # It's important we make a new list here + msgs = msgs + [msg] # It's important we make a new list here self.set('messages', msgs) - def _notify(self): - if not self.changes: return + if not self.changes: + return for listener in self.listeners: try: @@ -201,53 +201,58 @@ class State(object): except Exception as e: self.log.warning('Updating state listener: %s', - traceback.format_exc()) + traceback.format_exc()) self.changes = {} self.timeout = None - def resolve(self, name): # Resolve axis prefixes to motor numbers if 2 < len(name) and name[1] == '_' and name[0] in 'xyzabc': motor = self.find_motor(name[0]) - if motor is not None: return str(motor) + name[2:] + if motor is not None: + return str(motor) + name[2:] return name + def has(self, name): + return self.resolve(name) in self.vars - def has(self, name): return self.resolve(name) in self.vars - def set_callback(self, name, cb): self.callbacks[self.resolve(name)] = cb - + def set_callback(self, name, cb): + self.callbacks[self.resolve(name)] = cb def set(self, name, value): - name = self.resolve(name) + self.lock.acquire() + try: + name = self.resolve(name) - if not name in self.vars or self.vars[name] != value: - self.vars[name] = value - self.changes[name] = value - - # Trigger listener notify - if self.timeout is None: - self.timeout = self.ctrl.ioloop.call_later(0.25, self._notify) + if not name in self.vars or self.vars[name] != value: + self.vars[name] = value + self.changes[name] = value + # Trigger listener notify + if self.timeout is None: + self.timeout = self.ctrl.ioloop.call_later( + 0.25, self._notify) + finally: + self.lock.release() def update(self, update): for name, value in update.items(): self.set(name, value) - - def get(self, name, default = None): + def get(self, name, default=None): name = self.resolve(name) - if name in self.vars: return self.vars[name] - if name in self.callbacks: return self.callbacks[name](name) + if name in self.vars: + return self.vars[name] + if name in self.callbacks: + return self.callbacks[name](name) if default is None: self.log.warning('State variable "%s" not found' % name) return default - def snapshot(self): vars = copy.deepcopy(self.vars) @@ -270,20 +275,19 @@ class State(object): return vars - def config(self, code, value): # Set machine variables via mach, others directly - if code in self.machine_var_set: self.ctrl.mach.set(code, value) - else: self.set(code, value) - + if code in self.machine_var_set: + self.ctrl.mach.set(code, value) + else: + self.set(code, value) def add_listener(self, listener): self.listeners.append(listener) listener(self.vars) - - def remove_listener(self, listener): self.listeners.remove(listener) - + def remove_listener(self, listener): + self.listeners.remove(listener) def set_machine_vars(self, vars): # Record all machine vars, indexed or otherwise @@ -292,8 +296,8 @@ class State(object): if 'index' in spec: for index in spec['index']: self.machine_var_set.add(index + code) - else: self.machine_var_set.add(code) - + else: + self.machine_var_set.add(code) def get_position(self): position = {} @@ -304,8 +308,7 @@ class State(object): return position - - def get_axis_vector(self, name, scale = 1): + def get_axis_vector(self, name, scale=1): v = {} for axis in 'xyzabc': @@ -313,11 +316,11 @@ class State(object): if motor is not None and self.motor_enabled(motor): value = self.get(str(motor) + name, None) - if value is not None: v[axis] = value * scale + if value is not None: + v[axis] = value * scale return v - def get_soft_limit_vector(self, var, default): limit = self.get_axis_vector(var, 1) @@ -327,23 +330,21 @@ class State(object): return limit - def find_motor(self, axis): for motor in range(4): - if not ('%dan' % motor) in self.vars: continue + if not ('%dan' % motor) in self.vars: + continue motor_axis = 'xyzabc'[self.vars['%dan' % motor]] if motor_axis == axis.lower() and self.vars.get('%dme' % motor, 0): return motor - - def is_axis_homed(self, axis): return self.get('%s_homed' % axis, False) - + def is_axis_homed(self, axis): + return self.get('%s_homed' % axis, False) def is_axis_enabled(self, axis): motor = self.find_motor(axis) return motor is not None and self.motor_enabled(motor) - def get_enabled_axes(self): axes = [] @@ -353,26 +354,25 @@ class State(object): return axes - def is_motor_faulted(self, motor): return self.get('%ddf' % motor, 0) & 0x1f - def is_axis_faulted(self, axis): motor = self.find_motor(axis) return motor is not None and self.is_motor_faulted(motor) - def axis_homing_mode(self, axis): motor = self.find_motor(axis) - if motor is None: return 'disabled' + if motor is None: + return 'disabled' return self.motor_homing_mode(motor) - def axis_home_fail_reason(self, axis): motor = self.find_motor(axis) - if motor is None: return 'Not mapped to motor' - if not self.motor_enabled(motor): return 'Motor disabled' + if motor is None: + return 'Not mapped to motor' + if not self.motor_enabled(motor): + return 'Motor disabled' mode = self.motor_homing_mode(motor) @@ -387,37 +387,41 @@ class State(object): softMax = int(self.get(axis + '_tm', 0)) if softMax <= softMin + 1: return 'max-soft-limit must be at least 1mm greater ' \ - 'than min-soft-limit' - + 'than min-soft-limit' def motor_enabled(self, motor): return bool(int(self.vars.get('%dme' % motor, 0))) - def motor_homing_mode(self, motor): mode = str(self.vars.get('%dho' % motor, 0)) - if mode == '0': return 'manual' - if mode == '1': return 'switch-min' - if mode == '2': return 'switch-max' - if mode == '3': return 'stall-min' - if mode == '4': return 'stall-max' + if mode == '0': + return 'manual' + if mode == '1': + return 'switch-min' + if mode == '2': + return 'switch-max' + if mode == '3': + return 'stall-min' + if mode == '4': + return 'stall-max' raise Exception('Unrecognized homing mode "%s"' % mode) - def motor_home_direction(self, motor): mode = self.motor_homing_mode(motor) - if mode.endswith('-min'): return -1 - if mode.endswith('-max'): return 1 - return 0 # Disabled - + if mode.endswith('-min'): + return -1 + if mode.endswith('-max'): + return 1 + return 0 # Disabled def motor_home_position(self, motor): mode = self.motor_homing_mode(motor) # Return soft limit positions - if mode.endswith('-min'): return self.vars['%dtn' % motor] - if mode.endswith('-max'): return self.vars['%dtm' % motor] - return 0 # Disabled - + if mode.endswith('-min'): + return self.vars['%dtn' % motor] + if mode.endswith('-max'): + return self.vars['%dtm' % motor] + return 0 # Disabled def motor_home_travel(self, motor): tmin = self.get(str(motor) + 'tm', 0) @@ -427,27 +431,22 @@ class State(object): # (travel_max - travel_min) * 1.5 * home_dir return (tmin - tmax) * 1.5 * hdir - def motor_latch_backoff(self, motor): lb = self.get(str(motor) + 'lb', 0) hdir = self.motor_home_direction(motor) - return -(lb * hdir) # -latch_backoff * home_dir - + return -(lb * hdir) # -latch_backoff * home_dir def motor_zero_backoff(self, motor): zb = self.get(str(motor) + 'zb', 0) hdir = self.motor_home_direction(motor) - return -(zb * hdir) # -zero_backoff * home_dir - + return -(zb * hdir) # -zero_backoff * home_dir def motor_search_velocity(self, motor): return 1000 * self.get(str(motor) + 'sv', 0) - def motor_latch_velocity(self, motor): return 1000 * self.get(str(motor) + 'lv', 0) - def get_axis_switch(self, axis, side): axis = axis.lower() @@ -461,14 +460,26 @@ class State(object): # This must match the switch ID enum in avr/src/switch.h hmode = self.motor_homing_mode(motor) - if hmode.startswith('stall-'): return motor + 10 + if hmode.startswith('stall-'): + return motor + 10 return 2 * motor + 2 + (0 if side.lower() == 'min' else 1) - def get_switch_id(self, switch): # TODO Support other input switches in CAMotics gcode/machine/PortType.h switch = switch.lower() - if switch == 'probe': return 1 - if switch[1:] == '-min': return self.get_axis_switch(switch[0], 'min') - if switch[1:] == '-max': return self.get_axis_switch(switch[0], 'max') + if switch == 'probe': + return 1 + if switch[1:] == '-min': + return self.get_axis_switch(switch[0], 'min') + if switch[1:] == '-max': + return self.get_axis_switch(switch[0], 'max') raise Exception('Unsupported switch "%s"' % switch) + + def init(self): + # Init machine units + metric = self.ctrl.config.get('units', 'METRIC').upper() == 'METRIC' + self.log.info('INIT Metric %d' % metric) + if not 'metric' in self.vars: + self.set('metric', metric) + if not 'imperial' in self.vars: + self.set('imperial', not metric) diff --git a/src/py/bbctrl/Web.py b/src/py/bbctrl/Web.py index cbfbd7c..b65682b 100644 --- a/src/py/bbctrl/Web.py +++ b/src/py/bbctrl/Web.py @@ -1,15 +1,13 @@ -import os -import json -import tornado -import sockjs.tornado -import datetime -import subprocess -import socket -from tornado.web import HTTPError from tornado import gen - +from tornado.web import HTTPError import bbctrl -import iw_parse +import datetime +import os +import re +import socket +import sockjs.tornado +import subprocess +import tornado def call_get_output(cmd): @@ -21,17 +19,19 @@ def call_get_output(cmd): class RebootHandler(bbctrl.APIHandler): + def put_ok(self): - self.get_ctrl().lcd.goodbye('Rebooting...') - subprocess.Popen('reboot') + subprocess.Popen(['reboot']) class ShutdownHandler(bbctrl.APIHandler): + def put_ok(self): subprocess.Popen(['shutdown', '-h', 'now']) class LogHandler(bbctrl.RequestHandler): + def get(self): with open(self.get_ctrl().log.get_path(), 'r') as f: self.write(f.read()) @@ -44,11 +44,13 @@ class LogHandler(bbctrl.RequestHandler): class MessageAckHandler(bbctrl.APIHandler): + def put_ok(self, id): self.get_ctrl().state.ack_message(int(id)) class BugReportHandler(bbctrl.RequestHandler): + def get(self): import tarfile import io @@ -87,13 +89,15 @@ class BugReportHandler(bbctrl.RequestHandler): class HostnameHandler(bbctrl.APIHandler): + def put(self): if self.get_ctrl().args.demo: raise HTTPError(400, 'Cannot set hostname in demo mode') if 'hostname' in self.json: - if subprocess.call(['/usr/local/bin/sethostname', - self.json['hostname'].strip()]) == 0: + if subprocess.call( + ['/usr/local/bin/sethostname', + self.json['hostname'].strip()]) == 0: self.write_json('ok') return @@ -101,30 +105,6 @@ class HostnameHandler(bbctrl.APIHandler): class NetworkHandler(bbctrl.APIHandler): - def get(self): - try: - ipAddresses = call_get_output(['hostname', '-I']).split() - except: - ipAddresses = "" - - hostname = socket.gethostname() - - try: - wifi = json.loads(call_get_output(['config-wifi', '-j'])) - except: - wifi = {'enabled': False} - - try: - lines = iw_parse.call_iwlist().decode("utf-8").split("\n") - wifi['networks'] = iw_parse.get_parsed_cells(lines) - except: - wifi['networks'] = [] - - self.write_json({ - 'ipAddresses': ipAddresses, - 'hostname': hostname, - 'wifi': wifi - }) def put(self): if self.get_ctrl().args.demo: @@ -154,11 +134,13 @@ class NetworkHandler(bbctrl.APIHandler): class ConfigLoadHandler(bbctrl.APIHandler): + def get(self): self.write_json(self.get_ctrl().config.load()) class ConfigDownloadHandler(bbctrl.APIHandler): + def set_default_headers(self): fmt = socket.gethostname() + '-%Y%m%d.json' filename = datetime.date.today().strftime(fmt) @@ -171,15 +153,21 @@ class ConfigDownloadHandler(bbctrl.APIHandler): class ConfigSaveHandler(bbctrl.APIHandler): - def put_ok(self): self.get_ctrl().config.save(self.json) + + def put_ok(self): + self.get_ctrl().config.save(self.json) class ConfigResetHandler(bbctrl.APIHandler): - def put_ok(self): self.get_ctrl().config.reset() + + def put_ok(self): + self.get_ctrl().config.reset() class FirmwareUpdateHandler(bbctrl.APIHandler): - def prepare(self): pass + + def prepare(self): + pass def put_ok(self): if not 'firmware' in self.request.files: @@ -193,17 +181,17 @@ class FirmwareUpdateHandler(bbctrl.APIHandler): with open('firmware/update.tar.bz2', 'wb') as f: f.write(firmware['body']) - self.get_ctrl().lcd.goodbye('Upgrading firmware') subprocess.Popen(['/usr/local/bin/update-bbctrl']) class UpgradeHandler(bbctrl.APIHandler): + def put_ok(self): - self.get_ctrl().lcd.goodbye('Upgrading firmware') subprocess.Popen(['/usr/local/bin/upgrade-bbctrl']) class PathHandler(bbctrl.APIHandler): + @gen.coroutine def get(self, filename, dataType, *args): if not os.path.exists(self.get_upload(filename)): @@ -253,6 +241,7 @@ class PathHandler(bbctrl.APIHandler): class HomeHandler(bbctrl.APIHandler): + def put_ok(self, axis, action, *args): if axis is not None: axis = ord(axis[1:2].lower()) @@ -270,62 +259,86 @@ class HomeHandler(bbctrl.APIHandler): class StartHandler(bbctrl.APIHandler): - def put_ok(self): self.get_ctrl().mach.start() + + def put_ok(self): + self.get_ctrl().mach.start() class EStopHandler(bbctrl.APIHandler): - def put_ok(self): self.get_ctrl().mach.estop() + + def put_ok(self): + self.get_ctrl().mach.estop() class ClearHandler(bbctrl.APIHandler): - def put_ok(self): self.get_ctrl().mach.clear() + + def put_ok(self): + self.get_ctrl().mach.clear() class StopHandler(bbctrl.APIHandler): - def put_ok(self): self.get_ctrl().mach.stop() + + def put_ok(self): + self.get_ctrl().mach.stop() class PauseHandler(bbctrl.APIHandler): - def put_ok(self): self.get_ctrl().mach.pause() + + def put_ok(self): + self.get_ctrl().mach.pause() class UnpauseHandler(bbctrl.APIHandler): - def put_ok(self): self.get_ctrl().mach.unpause() + + def put_ok(self): + self.get_ctrl().mach.unpause() class OptionalPauseHandler(bbctrl.APIHandler): - def put_ok(self): self.get_ctrl().mach.optional_pause() + + def put_ok(self): + self.get_ctrl().mach.optional_pause() class StepHandler(bbctrl.APIHandler): - def put_ok(self): self.get_ctrl().mach.step() + + def put_ok(self): + self.get_ctrl().mach.step() class PositionHandler(bbctrl.APIHandler): + def put_ok(self, axis): self.get_ctrl().mach.set_position(axis, float(self.json['position'])) class OverrideFeedHandler(bbctrl.APIHandler): - def put_ok(self, value): self.get_ctrl().mach.override_feed(float(value)) + + def put_ok(self, value): + self.get_ctrl().mach.override_feed(float(value)) class OverrideSpeedHandler(bbctrl.APIHandler): - def put_ok(self, value): self.get_ctrl().mach.override_speed(float(value)) + + def put_ok(self, value): + self.get_ctrl().mach.override_speed(float(value)) class ModbusReadHandler(bbctrl.APIHandler): + def put_ok(self): self.get_ctrl().mach.modbus_read(int(self.json['address'])) class ModbusWriteHandler(bbctrl.APIHandler): + def put_ok(self): self.get_ctrl().mach.modbus_write(int(self.json['address']), int(self.json['value'])) class JogHandler(bbctrl.APIHandler): + def put_ok(self): # Handle possible out of order jog command processing if 'ts' in self.json: @@ -344,8 +357,76 @@ class JogHandler(bbctrl.APIHandler): self.get_ctrl().mach.jog(self.json) +displayRotatePattern = re.compile(r'display_rotate\s*=\s*(\d)') +transformationMatrixPattern = re.compile( + r'(\n)(\s+)(MatchIsTouchscreen.*?\n)(\s+Option\s+\"TransformationMatrix\".*?\n)(.*?EndSection)', + re.DOTALL) +matchIsTouchscreenPattern = re.compile( + r'(\n)(\s+)(MatchIsTouchscreen.*?\n)(.*?EndSection)', re.DOTALL) + + +class ScreenRotationHandler(bbctrl.APIHandler): + + @gen.coroutine + def get(self): + with open("/boot/config.txt", 'rt') as config: + lines = config.readlines() + for line in lines: + if line.startswith('display_rotate'): + self.write_json({ + 'rotated': + int(displayRotatePattern.search(line).group(1)) != 0 + }) + return + + self.write_json({'rotated': False}) + return + + @gen.coroutine + def put_ok(self): + rotated = self.json['rotated'] + + subprocess.Popen([ + '/usr/local/bin/edit-boot-config', + 'display_rotate={}'.format(2 if rotated else 0) + ]) + + with open("/usr/share/X11/xorg.conf.d/40-libinput.conf", + 'rt') as config: + text = config.read() + text = transformationMatrixPattern.sub(r'\1\2\3\5', text) + if rotated: + text = matchIsTouchscreenPattern.sub( + r'\1\2\3\2Option "TransformationMatrix" "-1 0 1 0 -1 1 0 0 1"\1\4', + text) + with open("/usr/share/X11/xorg.conf.d/40-libinput.conf", + 'wt') as config: + config.write(text) + + subprocess.run('reboot') + + +class TimeHandler(bbctrl.APIHandler): + + def get(self): + timeinfo = call_get_output(['timedatectl']) + timezones = call_get_output( + ['timedatectl', 'list-timezones', '--no-pager']) + self.get_log('TimeHandler').info('Time stuff: {}, {}'.format( + timeinfo, timezones)) + + self.write_json({'timeinfo': timeinfo, 'timezones': timezones}) + + def put_ok(self): + datetime = self.json['datetime'] + timezone = self.json['timezone'] + subprocess.Popen(['timedatectl', 'set-time', datetime]) + subprocess.Popen(['timedatectl', 'set-timezone', timezone]) + + # Base class for Web Socket connections class ClientConnection(object): + def __init__(self, app): self.app = app self.count = 0 @@ -355,7 +436,8 @@ class ClientConnection(object): self.send({'heartbeat': self.count}) self.count += 1 - def send(self, msg): raise HTTPError(400, 'Not implemented') + def send(self, msg): + raise HTTPError(400, 'Not implemented') def on_open(self, id=None): self.ctrl = self.app.get_ctrl(id) @@ -379,10 +461,11 @@ class ClientConnection(object): # Used by CAMotics class WSConnection(ClientConnection, tornado.websocket.WebSocketHandler): + def __init__(self, app, request, **kwargs): ClientConnection.__init__(self, app) - tornado.websocket.WebSocketHandler.__init__( - self, app, request, **kwargs) + tornado.websocket.WebSocketHandler.__init__(self, app, request, + **kwargs) def send(self, msg): self.write_message(msg) @@ -393,6 +476,7 @@ class WSConnection(ClientConnection, tornado.websocket.WebSocketHandler): # Used by Web frontend class SockJSConnection(ClientConnection, sockjs.tornado.SockJSConnection): + def __init__(self, session): ClientConnection.__init__(self, session.server.app) sockjs.tornado.SockJSConnection.__init__(self, session) @@ -413,18 +497,20 @@ class SockJSConnection(ClientConnection, sockjs.tornado.SockJSConnection): ip = info.ip if 'X-Real-IP' in info.headers: ip = info.headers['X-Real-IP'] - self.app.get_ctrl(id).log.get( - 'Web').info('Connection from %s' % ip) + self.app.get_ctrl(id).log.get('Web').info('Connection from %s' % + ip) super().on_open(id) class StaticFileHandler(tornado.web.StaticFileHandler): + def set_extra_headers(self, path): self.set_header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') class Web(tornado.web.Application): + def __init__(self, args, ioloop): self.args = args self.ioloop = ioloop @@ -478,9 +564,12 @@ class Web(tornado.web.Application): (r'/api/modbus/write', ModbusWriteHandler), (r'/api/jog', JogHandler), (r'/api/video', bbctrl.VideoHandler), - (r'/(.*)', StaticFileHandler, - {'path': bbctrl.get_resource('http/'), - 'default_filename': 'index.html'}), + (r'/api/screen-rotation', ScreenRotationHandler), + (r'/api/time', TimeHandler), + (r'/(.*)', StaticFileHandler, { + 'path': bbctrl.get_resource('http/'), + 'default_filename': 'index.html' + }), ] router = sockjs.tornado.SockJSRouter(SockJSConnection, '/sockjs') @@ -492,12 +581,13 @@ class Web(tornado.web.Application): self.listen(args.port, address=args.addr) except Exception as e: - raise Exception('Failed to bind %s:%d: %s' % ( - args.addr, args.port, e)) + raise Exception('Failed to bind %s:%d: %s' % + (args.addr, args.port, e)) print('Listening on http://%s:%d/' % (args.addr, args.port)) - def opened(self, ctrl): ctrl.clear_timeout() + def opened(self, ctrl): + ctrl.clear_timeout() def closed(self, ctrl): # Time out clients in demo mode diff --git a/src/py/bbctrl/__init__.py b/src/py/bbctrl/__init__.py index b1a6452..d80df7a 100644 --- a/src/py/bbctrl/__init__.py +++ b/src/py/bbctrl/__init__.py @@ -1,38 +1,10 @@ #!/usr/bin/env python3 -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import os -import sys -import signal -import tornado import argparse import datetime +import signal +import sys +import tornado from pkg_resources import Requirement, resource_filename @@ -40,7 +12,6 @@ from bbctrl.RequestHandler import RequestHandler from bbctrl.APIHandler import APIHandler from bbctrl.FileHandler import FileHandler from bbctrl.Config import Config -from bbctrl.LCD import LCD, LCDPage from bbctrl.Mach import Mach from bbctrl.Web import Web from bbctrl.Jog import Jog @@ -52,18 +23,13 @@ from bbctrl.Preplanner import Preplanner from bbctrl.State import State from bbctrl.Comm import Comm from bbctrl.CommandQueue import CommandQueue -from bbctrl.MainLCDPage import MainLCDPage -from bbctrl.IPLCDPage import IPLCDPage from bbctrl.Camera import Camera, VideoHandler from bbctrl.AVR import AVR -from bbctrl.AVREmu import AVREmu from bbctrl.IOLoop import IOLoop from bbctrl.MonitorTemp import MonitorTemp import bbctrl.Cmd as Cmd import bbctrl.v4l2 as v4l2 import bbctrl.Log as log -import bbctrl.ObjGraph as ObjGraph - ctrl = None @@ -72,7 +38,7 @@ def get_resource(path): return resource_filename(Requirement.parse('bbctrl'), 'bbctrl/' + path) -def on_exit(sig = 0, func = None): +def on_exit(sig=0, func=None): global ctrl print('Exit handler triggered: signal = %d', sig) @@ -88,78 +54,66 @@ def time_str(): return datetime.datetime.now().strftime('%Y%m%d-%H:%M:%S') - -class Debugger: - def __init__(self, ioloop, freq = 60 * 15, depth = 100): - self.ioloop = ioloop - self.freq = freq - self.depth = depth - self._callback() - - - def _callback(self): - with open('bbctrl-debug-%s.log' % time_str(), 'w') as log: - def line(name): - log.write('==== ' + name + ' ' + '=' * (74 - len(name)) + '\n') - - line('Common') - ObjGraph.show_most_common_types(limit = self.depth, file = log) - - log.write('\n') - line('Growth') - ObjGraph.show_growth(limit = self.depth, file = log) - - log.write('\n') - line('New IDs') - ObjGraph.get_new_ids(limit = self.depth, file = log) - - log.flush() - self.ioloop.call_later(self.freq, self._callback) - - - def parse_args(): parser = argparse.ArgumentParser( - description = 'Buildbotics Machine Controller') + description='Buildbotics Machine Controller') - parser.add_argument('-p', '--port', default = 80, - type = int, help = 'HTTP port') - parser.add_argument('-a', '--addr', metavar = 'IP', default = '0.0.0.0', - help = 'HTTP address to bind') - parser.add_argument('-s', '--serial', default = '/dev/ttyAMA0', - help = 'Serial device') - parser.add_argument('-b', '--baud', default = 230400, type = int, - help = 'Serial baud rate') - parser.add_argument('--i2c-port', default = 1, type = int, - help = 'I2C port') - parser.add_argument('--lcd-addr', default = [0x27, 0x3f], type = int, - help = 'LCD I2C address') - parser.add_argument('--avr-addr', default = 0x2b, type = int, - help = 'AVR I2C address') - parser.add_argument('--pwr-addr', default = 0x60, type = int, - help = 'Power AVR I2C address') - parser.add_argument('-v', '--verbose', action = 'store_true', - help = 'Verbose output') - parser.add_argument('-l', '--log', metavar = "FILE", - help = 'Set a log file') - parser.add_argument('--disable-camera', action = 'store_true', - help = 'Disable the camera') - parser.add_argument('--width', default = 640, type = int, - help = 'Camera width') - parser.add_argument('--height', default = 480, type = int, - help = 'Camera height') - parser.add_argument('--fps', default = 15, type = int, - help = 'Camera frames per second') - parser.add_argument('--camera-clients', default = 4, - help = 'Maximum simultaneous camera clients') - parser.add_argument('--demo', action = 'store_true', - help = 'Enter demo mode') - parser.add_argument('--debug', default = 0, type = int, - help = 'Enable debug mode and set frequency in seconds') - parser.add_argument('--fast-emu', action = 'store_true', - help = 'Enter demo mode') - parser.add_argument('--client-timeout', default = 5 * 60, type = int, - help = 'Demo client timeout in seconds') + parser.add_argument('-p', '--port', default=80, type=int, help='HTTP port') + parser.add_argument('-a', + '--addr', + metavar='IP', + default='0.0.0.0', + help='HTTP address to bind') + parser.add_argument('-s', + '--serial', + default='/dev/ttyAMA0', + help='Serial device') + parser.add_argument('-b', + '--baud', + default=230400, + type=int, + help='Serial baud rate') + parser.add_argument('--i2c-port', default=1, type=int, help='I2C port') + parser.add_argument('--avr-addr', + default=0x2b, + type=int, + help='AVR I2C address') + parser.add_argument('--pwr-addr', + default=0x60, + type=int, + help='Power AVR I2C address') + parser.add_argument('-v', + '--verbose', + action='store_true', + help='Verbose output') + parser.add_argument('-l', '--log', metavar="FILE", help='Set a log file') + parser.add_argument('--disable-camera', + action='store_true', + help='Disable the camera') + parser.add_argument('--width', default=640, type=int, help='Camera width') + parser.add_argument('--height', + default=480, + type=int, + help='Camera height') + parser.add_argument('--fps', + default=15, + type=int, + help='Camera frames per second') + parser.add_argument('--camera-clients', + default=4, + help='Maximum simultaneous camera clients') + parser.add_argument('--demo', action='store_true', help='Enter demo mode') + parser.add_argument('--debug', + default=0, + type=int, + help='Enable debug mode and set frequency in seconds') + parser.add_argument('--fast-emu', + action='store_true', + help='Enter demo mode') + parser.add_argument('--client-timeout', + default=5 * 60, + type=int, + help='Demo client timeout in seconds') return parser.parse_args() @@ -175,16 +129,15 @@ def run(): # Create ioloop ioloop = tornado.ioloop.IOLoop.current() - # Set ObjGraph signal handler - if args.debug: Debugger(ioloop, args.debug) - # Start server web = Web(args, ioloop) try: ioloop.start() - except KeyboardInterrupt: on_exit() + except KeyboardInterrupt: + on_exit() -if __name__ == '__main__': run() +if __name__ == '__main__': + run() diff --git a/src/py/bbctrl/plan.py b/src/py/bbctrl/plan.py index 0961970..94a6886 100644 --- a/src/py/bbctrl/plan.py +++ b/src/py/bbctrl/plan.py @@ -1,51 +1,22 @@ #!/usr/bin/env python3 -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import sys import argparse +import camotics.gplan as gplan # pylint: disable=no-name-in-module,import-error +import gzip import json -import time +import math import math import os import re -import gzip import struct -import math -import camotics.gplan as gplan # pylint: disable=no-name-in-module,import-error +import sys +import time - -reLogLine = re.compile( - r'^(?P[A-Z])[0-9 ]:' - r'((?P[^:]+):)?' - r'((?P\d+):)?' - r'((?P\d+):)?' - r'(?P.*)$') +reLogLine = re.compile(r'^(?P[A-Z])[0-9 ]:' + r'((?P[^:]+):)?' + r'((?P\d+):)?' + r'((?P\d+):)?' + r'(?P.*)$') def compute_unit(a, b): @@ -77,6 +48,7 @@ def compute_move(start, unit, dist): class Plan(object): + def __init__(self, path, state, config): self.path = path self.state = state @@ -90,11 +62,14 @@ class Plan(object): self.planner.load(self.path, config) self.messages = [] - self.levels = dict(I = 'info', D = 'debug', W = 'warning', E = 'error', - C = 'critical') + self.levels = dict(I='info', + D='debug', + W='warning', + E='error', + C='critical') # Initialized axis states and bounds - self.bounds = dict(min = {}, max = {}) + self.bounds = dict(min={}, max={}) for axis in 'xyz': self.bounds['min'][axis] = math.inf self.bounds['max'][axis] = -math.inf @@ -105,12 +80,10 @@ class Plan(object): self.lastProgressTime = 0 self.time = 0 - def add_to_bounds(self, axis, value): if value < self.bounds['min'][axis]: self.bounds['min'][axis] = value if self.bounds['max'][axis] < value: self.bounds['max'][axis] = value - def get_bounds(self): # Remove infinity from bounds for axis in 'xyz': @@ -121,7 +94,6 @@ class Plan(object): return self.bounds - def update_speed(self, s): if self.currentSpeed == s: return False self.currentSpeed = s @@ -129,7 +101,6 @@ class Plan(object): return True - def get_var_cb(self, name, units): value = 0 @@ -139,19 +110,20 @@ class Plan(object): return value - def log_cb(self, level, msg, filename, line, column): if level in self.levels: level = self.levels[level] # Ignore missing tool warning - if (level == 'warning' and - msg.startswith('Auto-creating missing tool')): + if (level == 'warning' + and msg.startswith('Auto-creating missing tool')): return self.messages.append( - dict(level = level, msg = msg, filename = filename, line = line, - column = column)) - + dict(level=level, + msg=msg, + filename=filename, + line=line, + column=column)) def _log_cb(self, line): line = line.strip() @@ -171,7 +143,6 @@ class Plan(object): self.log_cb(level, msg, filename, line, column) - def progress(self, x): if time.time() - self.lastProgressTime < 1 and x != 1: return self.lastProgressTime = time.time() @@ -184,7 +155,6 @@ class Plan(object): sys.stdout.write(p) sys.stdout.flush() - def _run(self): start = time.clock() line = 0 @@ -197,14 +167,14 @@ class Plan(object): try: while self.planner.has_more(): cmd = self.planner.next() - self.planner.set_active(cmd['id']) # Release plan + self.planner.set_active(cmd['id']) # Release plan # Cannot synchronize with actual machine so fake it if self.planner.is_synchronizing(): self.planner.synchronize(0) if cmd['type'] == 'line': - if not (cmd.get('first', False) or - cmd.get('seeking', False)): + if not (cmd.get('first', False) + or cmd.get('seeking', False)): self.time += sum(cmd['times']) / 1000 target = cmd['target'] @@ -263,7 +233,6 @@ class Plan(object): except Exception as e: self.log_cb('error', str(e), os.path.basename(self.path), line, 0) - def run(self): lastS = 0 speed = 0 @@ -292,27 +261,32 @@ class Plan(object): f2.write(s) with open('meta.json', 'w') as f: - meta = dict( - time = self.time, - lines = self.lines, - maxSpeed = self.maxSpeed, - bounds = self.get_bounds(), - messages = self.messages) + meta = dict(time=self.time, + lines=self.lines, + maxSpeed=self.maxSpeed, + bounds=self.get_bounds(), + messages=self.messages) json.dump(meta, f) -parser = argparse.ArgumentParser(description = 'Buildbotics GCode Planner') -parser.add_argument('gcode', help = 'The GCode file to plan') -parser.add_argument('state', help = 'GCode state variables') -parser.add_argument('config', help = 'Planner config') +parser = argparse.ArgumentParser(description='Buildbotics GCode Planner') +parser.add_argument('gcode', help='The GCode file to plan') +parser.add_argument('state', help='GCode state variables') +parser.add_argument('config', help='Planner config') -parser.add_argument('--max-time', default = 600, - type = int, help = 'Maximum planning time in seconds') -parser.add_argument('--max-loop', default = 30, - type = int, help = 'Maximum time in loop in seconds') -parser.add_argument('--nice', default = 10, - type = int, help = 'Set "nice" process priority') +parser.add_argument('--max-time', + default=600, + type=int, + help='Maximum planning time in seconds') +parser.add_argument('--max-loop', + default=30, + type=int, + help='Maximum time in loop in seconds') +parser.add_argument('--nice', + default=10, + type=int, + help='Set "nice" process priority') args = parser.parse_args() diff --git a/src/py/bbctrl/v4l2.py b/src/py/bbctrl/v4l2.py index 02c49b3..0c79fc9 100644 --- a/src/py/bbctrl/v4l2.py +++ b/src/py/bbctrl/v4l2.py @@ -39,7 +39,6 @@ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - """ Python bindings for the v4l2 userspace api in Linux 2.6.34 """ @@ -49,7 +48,6 @@ Python bindings for the v4l2 userspace api in Linux 2.6.34 import ctypes import platform - # See ioctl.h of your architecture for appropriate constants here. # This has been tested only on x86 and MIPS _IOC_NRBITS = 8 @@ -62,24 +60,25 @@ _IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS if (platform.machine() == "mips"): _IOC_NONE = 1 _IOC_READ = 2 - _IOC_WRITE = 4 + _IOC_WRITE = 4 _IOC_SIZEBITS = 13 _IOC_DIRBITS = 3 else: _IOC_NONE = 0 _IOC_WRITE = 1 - _IOC_READ = 2 + _IOC_READ = 2 _IOC_SIZEBITS = 14 _IOC_DIRBITS = 2 _IOC_DIRSHIFT = _IOC_SIZESHIFT + _IOC_SIZEBITS + def _IOC(dir_, type_, nr, size): - return ( - ctypes.c_int32(dir_ << _IOC_DIRSHIFT).value | - ctypes.c_int32(ord(type_) << _IOC_TYPESHIFT).value | - ctypes.c_int32(nr << _IOC_NRSHIFT).value | - ctypes.c_int32(size << _IOC_SIZESHIFT).value) + return (ctypes.c_int32(dir_ << _IOC_DIRSHIFT).value + | ctypes.c_int32(ord(type_) << _IOC_TYPESHIFT).value + | ctypes.c_int32(nr << _IOC_NRSHIFT).value + | ctypes.c_int32(size << _IOC_SIZESHIFT).value) + def _IOC_TYPECHECK(t): return ctypes.sizeof(t) @@ -96,6 +95,7 @@ def _IOW(type_, nr, size): def _IOR(type_, nr, size): return _IOC(_IOC_READ, type_, nr, _IOC_TYPECHECK(size)) + def _IOWR(type_, nr, size): return _IOC(_IOC_READ | _IOC_WRITE, type_, nr, _IOC_TYPECHECK(size)) @@ -107,11 +107,11 @@ def _IOWR(type_, nr, size): enum = ctypes.c_uint c_int = ctypes.c_int - # # time # + class timeval(ctypes.Structure): _fields_ = [ ('secs', ctypes.c_long), @@ -123,10 +123,8 @@ class timeval(ctypes.Structure): # v4l2 # - VIDEO_MAX_FRAME = 32 - VID_TYPE_CAPTURE = 1 VID_TYPE_TUNER = 2 VID_TYPE_TELETEXT = 4 @@ -134,7 +132,7 @@ VID_TYPE_OVERLAY = 8 VID_TYPE_CHROMAKEY = 16 VID_TYPE_CLIPPING = 32 VID_TYPE_FRAMERAM = 64 -VID_TYPE_SCALES = 128 +VID_TYPE_SCALES = 128 VID_TYPE_MONOCHROME = 256 VID_TYPE_SUBCAPTURE = 512 VID_TYPE_MPEG_DECODER = 1024 @@ -163,32 +161,23 @@ v4l2_field = enum def V4L2_FIELD_HAS_TOP(field): - return ( - field == V4L2_FIELD_TOP or - field == V4L2_FIELD_INTERLACED or - field == V4L2_FIELD_INTERLACED_TB or - field == V4L2_FIELD_INTERLACED_BT or - field == V4L2_FIELD_SEQ_TB or - field == V4L2_FIELD_SEQ_BT) + return (field == V4L2_FIELD_TOP or field == V4L2_FIELD_INTERLACED + or field == V4L2_FIELD_INTERLACED_TB + or field == V4L2_FIELD_INTERLACED_BT or field == V4L2_FIELD_SEQ_TB + or field == V4L2_FIELD_SEQ_BT) def V4L2_FIELD_HAS_BOTTOM(field): - return ( - field == V4L2_FIELD_BOTTOM or - field == V4L2_FIELD_INTERLACED or - field == V4L2_FIELD_INTERLACED_TB or - field == V4L2_FIELD_INTERLACED_BT or - field == V4L2_FIELD_SEQ_TB or - field == V4L2_FIELD_SEQ_BT) + return (field == V4L2_FIELD_BOTTOM or field == V4L2_FIELD_INTERLACED + or field == V4L2_FIELD_INTERLACED_TB + or field == V4L2_FIELD_INTERLACED_BT or field == V4L2_FIELD_SEQ_TB + or field == V4L2_FIELD_SEQ_BT) def V4L2_FIELD_HAS_BOTH(field): - return ( - field == V4L2_FIELD_INTERLACED or - field == V4L2_FIELD_INTERLACED_TB or - field == V4L2_FIELD_INTERLACED_BT or - field == V4L2_FIELD_SEQ_TB or - field == V4L2_FIELD_SEQ_BT) + return (field == V4L2_FIELD_INTERLACED or field == V4L2_FIELD_INTERLACED_TB + or field == V4L2_FIELD_INTERLACED_BT or field == V4L2_FIELD_SEQ_TB + or field == V4L2_FIELD_SEQ_BT) v4l2_buf_type = enum @@ -206,7 +195,6 @@ v4l2_buf_type = enum V4L2_BUF_TYPE_PRIVATE, ) = list(range(1, 11)) + [0x80] - v4l2_ctrl_type = enum ( V4L2_CTRL_TYPE_INTEGER, @@ -218,7 +206,6 @@ v4l2_ctrl_type = enum V4L2_CTRL_TYPE_STRING, ) = range(1, 8) - v4l2_tuner_type = enum ( V4L2_TUNER_RADIO, @@ -226,7 +213,6 @@ v4l2_tuner_type = enum V4L2_TUNER_DIGITAL_TV, ) = range(1, 4) - v4l2_memory = enum ( V4L2_MEMORY_MMAP, @@ -234,7 +220,6 @@ v4l2_memory = enum V4L2_MEMORY_OVERLAY, ) = range(1, 4) - v4l2_colorspace = enum ( V4L2_COLORSPACE_SMPTE170M, @@ -247,7 +232,6 @@ v4l2_colorspace = enum V4L2_COLORSPACE_SRGB, ) = range(1, 9) - v4l2_priority = enum ( V4L2_PRIORITY_UNSET, @@ -278,6 +262,7 @@ class v4l2_fract(ctypes.Structure): # Driver capabilities # + class v4l2_capability(ctypes.Structure): _fields_ = [ ('driver', ctypes.c_uint8 * 16), @@ -315,11 +300,11 @@ V4L2_CAP_READWRITE = 0x01000000 V4L2_CAP_ASYNCIO = 0x02000000 V4L2_CAP_STREAMING = 0x04000000 - # # Video image format # + class v4l2_pix_format(ctypes.Structure): _fields_ = [ ('width', ctypes.c_uint32), @@ -332,6 +317,7 @@ class v4l2_pix_format(ctypes.Structure): ('priv', ctypes.c_uint32), ] + # RGB formats V4L2_PIX_FMT_RGB332 = v4l2_fourcc('R', 'G', 'B', '1') V4L2_PIX_FMT_RGB444 = v4l2_fourcc('R', '4', '4', '4') @@ -346,7 +332,7 @@ V4L2_PIX_FMT_RGB32 = v4l2_fourcc('R', 'G', 'B', '4') # Grey formats V4L2_PIX_FMT_GREY = v4l2_fourcc('G', 'R', 'E', 'Y') -V4L2_PIX_FMT_Y10 = v4l2_fourcc('Y', '1', '0', ' ') +V4L2_PIX_FMT_Y10 = v4l2_fourcc('Y', '1', '0', ' ') V4L2_PIX_FMT_Y16 = v4l2_fourcc('Y', '1', '6', ' ') # Palette formats @@ -417,11 +403,11 @@ V4L2_PIX_FMT_OV511 = v4l2_fourcc('O', '5', '1', '1') V4L2_PIX_FMT_OV518 = v4l2_fourcc('O', '5', '1', '8') V4L2_PIX_FMT_STV0680 = v4l2_fourcc('S', '6', '8', '0') - # # Format enumeration # + class v4l2_fmtdesc(ctypes.Structure): _fields_ = [ ('index', ctypes.c_uint32), @@ -432,10 +418,10 @@ class v4l2_fmtdesc(ctypes.Structure): ('reserved', ctypes.c_uint32 * 4), ] + V4L2_FMT_FLAG_COMPRESSED = 0x0001 V4L2_FMT_FLAG_EMULATED = 0x0002 - # # Experimental frame size and frame rate enumeration # @@ -467,21 +453,18 @@ class v4l2_frmsize_stepwise(ctypes.Structure): class v4l2_frmsizeenum(ctypes.Structure): + class _u(ctypes.Union): _fields_ = [ ('discrete', v4l2_frmsize_discrete), ('stepwise', v4l2_frmsize_stepwise), ] - _fields_ = [ - ('index', ctypes.c_uint32), - ('pixel_format', ctypes.c_uint32), - ('type', ctypes.c_uint32), - ('_u', _u), - ('reserved', ctypes.c_uint32 * 2) - ] + _fields_ = [('index', ctypes.c_uint32), ('pixel_format', ctypes.c_uint32), + ('type', ctypes.c_uint32), ('_u', _u), + ('reserved', ctypes.c_uint32 * 2)] - _anonymous_ = ('_u',) + _anonymous_ = ('_u', ) # @@ -505,6 +488,7 @@ class v4l2_frmival_stepwise(ctypes.Structure): class v4l2_frmivalenum(ctypes.Structure): + class _u(ctypes.Union): _fields_ = [ ('discrete', v4l2_fract), @@ -521,13 +505,14 @@ class v4l2_frmivalenum(ctypes.Structure): ('reserved', ctypes.c_uint32 * 2), ] - _anonymous_ = ('_u',) + _anonymous_ = ('_u', ) # # Timecode # + class v4l2_timecode(ctypes.Structure): _fields_ = [ ('type', ctypes.c_uint32), @@ -571,11 +556,11 @@ V4L2_JPEG_MARKER_DRI = 1 << 5 V4L2_JPEG_MARKER_COM = 1 << 6 V4L2_JPEG_MARKER_APP = 1 << 7 - # # Memory-mapping buffers # + class v4l2_requestbuffers(ctypes.Structure): _fields_ = [ ('count', ctypes.c_uint32), @@ -586,6 +571,7 @@ class v4l2_requestbuffers(ctypes.Structure): class v4l2_plane(ctypes.Structure): + class _u(ctypes.Union): _fields_ = [ ('mem_offset', ctypes.c_uint32), @@ -600,13 +586,12 @@ class v4l2_plane(ctypes.Structure): ('reserved', ctypes.c_uint32 * 11), ] + class v4l2_buffer(ctypes.Structure): + class _u(ctypes.Union): - _fields_ = [ - ('offset', ctypes.c_uint32), - ('userptr', ctypes.c_ulong), - ('planes', ctypes.POINTER(v4l2_plane)) - ] + _fields_ = [('offset', ctypes.c_uint32), ('userptr', ctypes.c_ulong), + ('planes', ctypes.POINTER(v4l2_plane))] _fields_ = [ ('index', ctypes.c_uint32), @@ -634,11 +619,11 @@ V4L2_BUF_FLAG_BFRAME = 0x0020 V4L2_BUF_FLAG_TIMECODE = 0x0100 V4L2_BUF_FLAG_INPUT = 0x0200 - # # Overlay preview # + class v4l2_framebuffer(ctypes.Structure): _fields_ = [ ('capability', ctypes.c_uint32), @@ -647,8 +632,9 @@ class v4l2_framebuffer(ctypes.Structure): ('fmt', v4l2_pix_format), ] + V4L2_FBUF_CAP_EXTERNOVERLAY = 0x0001 -V4L2_FBUF_CAP_CHROMAKEY = 0x0002 +V4L2_FBUF_CAP_CHROMAKEY = 0x0002 V4L2_FBUF_CAP_LIST_CLIPPING = 0x0004 V4L2_FBUF_CAP_BITMAP_CLIPPING = 0x0008 V4L2_FBUF_CAP_LOCAL_ALPHA = 0x0010 @@ -667,6 +653,8 @@ V4L2_FBUF_FLAG_SRC_CHROMAKEY = 0x0040 class v4l2_clip(ctypes.Structure): pass + + v4l2_clip._fields_ = [ ('c', v4l2_rect), ('next', ctypes.POINTER(v4l2_clip)), @@ -689,6 +677,7 @@ class v4l2_window(ctypes.Structure): # Capture parameters # + class v4l2_captureparm(ctypes.Structure): _fields_ = [ ('capability', ctypes.c_uint32), @@ -719,6 +708,7 @@ class v4l2_outputparm(ctypes.Structure): # Input image cropping # + class v4l2_cropcap(ctypes.Structure): _fields_ = [ ('type', v4l2_buf_type), @@ -741,7 +731,6 @@ class v4l2_crop(ctypes.Structure): v4l2_std_id = ctypes.c_uint64 - V4L2_STD_PAL_B = 0x00000001 V4L2_STD_PAL_B1 = 0x00000002 V4L2_STD_PAL_G = 0x00000004 @@ -773,26 +762,31 @@ V4L2_STD_SECAM_LC = 0x00800000 V4L2_STD_ATSC_8_VSB = 0x01000000 V4L2_STD_ATSC_16_VSB = 0x02000000 - # some common needed stuff V4L2_STD_PAL_BG = (V4L2_STD_PAL_B | V4L2_STD_PAL_B1 | V4L2_STD_PAL_G) V4L2_STD_PAL_DK = (V4L2_STD_PAL_D | V4L2_STD_PAL_D1 | V4L2_STD_PAL_K) -V4L2_STD_PAL = (V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_H | V4L2_STD_PAL_I) +V4L2_STD_PAL = (V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_H + | V4L2_STD_PAL_I) V4L2_STD_NTSC = (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_M_KR) V4L2_STD_SECAM_DK = (V4L2_STD_SECAM_D | V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1) -V4L2_STD_SECAM = (V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H | V4L2_STD_SECAM_DK | V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC) +V4L2_STD_SECAM = (V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H + | V4L2_STD_SECAM_DK | V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC) -V4L2_STD_525_60 = (V4L2_STD_PAL_M | V4L2_STD_PAL_60 | V4L2_STD_NTSC | V4L2_STD_NTSC_443) -V4L2_STD_625_50 = (V4L2_STD_PAL | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | V4L2_STD_SECAM) +V4L2_STD_525_60 = (V4L2_STD_PAL_M | V4L2_STD_PAL_60 | V4L2_STD_NTSC + | V4L2_STD_NTSC_443) +V4L2_STD_625_50 = (V4L2_STD_PAL | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc + | V4L2_STD_SECAM) V4L2_STD_ATSC = (V4L2_STD_ATSC_8_VSB | V4L2_STD_ATSC_16_VSB) V4L2_STD_UNKNOWN = 0 V4L2_STD_ALL = (V4L2_STD_525_60 | V4L2_STD_625_50) # some merged standards -V4L2_STD_MN = (V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | V4L2_STD_NTSC) +V4L2_STD_MN = (V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc + | V4L2_STD_NTSC) V4L2_STD_B = (V4L2_STD_PAL_B | V4L2_STD_PAL_B1 | V4L2_STD_SECAM_B) -V4L2_STD_GH = (V4L2_STD_PAL_G | V4L2_STD_PAL_H|V4L2_STD_SECAM_G | V4L2_STD_SECAM_H) +V4L2_STD_GH = (V4L2_STD_PAL_G | V4L2_STD_PAL_H | V4L2_STD_SECAM_G + | V4L2_STD_SECAM_H) V4L2_STD_DK = (V4L2_STD_PAL_DK | V4L2_STD_SECAM_DK) @@ -811,17 +805,16 @@ class v4l2_standard(ctypes.Structure): # Video timings dv preset # + class v4l2_dv_preset(ctypes.Structure): - _fields_ = [ - ('preset', ctypes.c_uint32), - ('reserved', ctypes.c_uint32 * 4) - ] + _fields_ = [('preset', ctypes.c_uint32), ('reserved', ctypes.c_uint32 * 4)] # # DV preset enumeration # + class v4l2_dv_enum_preset(ctypes.Structure): _fields_ = [ ('index', ctypes.c_uint32), @@ -832,6 +825,7 @@ class v4l2_dv_enum_preset(ctypes.Structure): ('reserved', ctypes.c_uint32 * 4), ] + # # DV preset values # @@ -846,21 +840,21 @@ V4L2_DV_720P50 = 6 V4L2_DV_720P59_94 = 7 V4L2_DV_720P60 = 8 V4L2_DV_1080I29_97 = 9 -V4L2_DV_1080I30 = 10 -V4L2_DV_1080I25 = 11 -V4L2_DV_1080I50 = 12 -V4L2_DV_1080I60 = 13 -V4L2_DV_1080P24 = 14 -V4L2_DV_1080P25 = 15 -V4L2_DV_1080P30 = 16 -V4L2_DV_1080P50 = 17 -V4L2_DV_1080P60 = 18 - +V4L2_DV_1080I30 = 10 +V4L2_DV_1080I25 = 11 +V4L2_DV_1080I50 = 12 +V4L2_DV_1080I60 = 13 +V4L2_DV_1080P24 = 14 +V4L2_DV_1080P25 = 15 +V4L2_DV_1080P30 = 16 +V4L2_DV_1080P50 = 17 +V4L2_DV_1080P60 = 18 # # DV BT timings # + class v4l2_bt_timings(ctypes.Structure): _fields_ = [ ('width', ctypes.c_uint32), @@ -882,6 +876,7 @@ class v4l2_bt_timings(ctypes.Structure): _pack_ = True + # Interlaced or progressive format V4L2_DV_PROGRESSIVE = 0 V4L2_DV_INTERLACED = 1 @@ -892,6 +887,7 @@ V4L2_DV_HSYNC_POS_POL = 0x00000002 class v4l2_dv_timings(ctypes.Structure): + class _u(ctypes.Union): _fields_ = [ ('bt', v4l2_bt_timings), @@ -903,18 +899,18 @@ class v4l2_dv_timings(ctypes.Structure): ('_u', _u), ] - _anonymous_ = ('_u',) + _anonymous_ = ('_u', ) _pack_ = True # Values for the type field V4L2_DV_BT_656_1120 = 0 - # # Video inputs # + class v4l2_input(ctypes.Structure): _fields_ = [ ('index', ctypes.c_uint32), @@ -957,6 +953,7 @@ V4L2_IN_CAP_STD = 0x00000004 # Video outputs # + class v4l2_output(ctypes.Structure): _fields_ = [ ('index', ctypes.c_uint32), @@ -970,7 +967,7 @@ class v4l2_output(ctypes.Structure): V4L2_OUTPUT_TYPE_MODULATOR = 1 -V4L2_OUTPUT_TYPE_ANALOG = 2 +V4L2_OUTPUT_TYPE_ANALOG = 2 V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY = 3 V4L2_OUT_CAP_PRESETS = 0x00000001 @@ -981,6 +978,7 @@ V4L2_OUT_CAP_STD = 0x00000004 # Controls # + class v4l2_control(ctypes.Structure): _fields_ = [ ('id', ctypes.c_uint32), @@ -989,6 +987,7 @@ class v4l2_control(ctypes.Structure): class v4l2_ext_control(ctypes.Structure): + class _u(ctypes.Union): _fields_ = [ ('value', ctypes.c_int32), @@ -996,13 +995,10 @@ class v4l2_ext_control(ctypes.Structure): ('reserved', ctypes.c_void_p), ] - _fields_ = [ - ('id', ctypes.c_uint32), - ('reserved2', ctypes.c_uint32 * 2), - ('_u', _u) - ] + _fields_ = [('id', ctypes.c_uint32), ('reserved2', ctypes.c_uint32 * 2), + ('_u', _u)] - _anonymous_ = ('_u',) + _anonymous_ = ('_u', ) _pack_ = True @@ -1016,25 +1012,26 @@ class v4l2_ext_controls(ctypes.Structure): ] -V4L2_CTRL_CLASS_USER = 0x00980000 # Old-style 'user' controls -V4L2_CTRL_CLASS_MPEG = 0x00990000 # MPEG-compression controls -V4L2_CTRL_CLASS_CAMERA = 0x009a0000 # Camera class controls -V4L2_CTRL_CLASS_FM_TX = 0x009b0000 # FM Modulator controls -V4L2_CTRL_CLASS_FLASH = 0x009c0000 # Camera flash controls -V4L2_CTRL_CLASS_JPEG = 0x009d0000 # JPEG-compression controls -V4L2_CTRL_CLASS_IMAGE_SOURCE = 0x009e0000 # Image source controls -V4L2_CTRL_CLASS_IMAGE_PROC = 0x009f0000 # Image processing controls -V4L2_CTRL_CLASS_DV = 0x00a00000 # Digital Video controls -V4L2_CTRL_CLASS_FM_RX = 0x00a10000 # FM Receiver controls -V4L2_CTRL_CLASS_RF_TUNER = 0x00a20000 # RF tuner controls -V4L2_CTRL_CLASS_DETECT = 0x00a30000 # Detection controls +V4L2_CTRL_CLASS_USER = 0x00980000 # Old-style 'user' controls +V4L2_CTRL_CLASS_MPEG = 0x00990000 # MPEG-compression controls +V4L2_CTRL_CLASS_CAMERA = 0x009a0000 # Camera class controls +V4L2_CTRL_CLASS_FM_TX = 0x009b0000 # FM Modulator controls +V4L2_CTRL_CLASS_FLASH = 0x009c0000 # Camera flash controls +V4L2_CTRL_CLASS_JPEG = 0x009d0000 # JPEG-compression controls +V4L2_CTRL_CLASS_IMAGE_SOURCE = 0x009e0000 # Image source controls +V4L2_CTRL_CLASS_IMAGE_PROC = 0x009f0000 # Image processing controls +V4L2_CTRL_CLASS_DV = 0x00a00000 # Digital Video controls +V4L2_CTRL_CLASS_FM_RX = 0x00a10000 # FM Receiver controls +V4L2_CTRL_CLASS_RF_TUNER = 0x00a20000 # RF tuner controls +V4L2_CTRL_CLASS_DETECT = 0x00a30000 # Detection controls + def V4L2_CTRL_ID_MASK(): return 0x0fffffff def V4L2_CTRL_ID2CLASS(id_): - return id_ & 0x0fff0000 # unsigned long + return id_ & 0x0fff0000 # unsigned long def V4L2_CTRL_DRIVER_PRIV(id_): @@ -1089,13 +1086,13 @@ V4L2_CID_AUDIO_BASS = V4L2_CID_BASE + 7 V4L2_CID_AUDIO_TREBLE = V4L2_CID_BASE + 8 V4L2_CID_AUDIO_MUTE = V4L2_CID_BASE + 9 V4L2_CID_AUDIO_LOUDNESS = V4L2_CID_BASE + 10 -V4L2_CID_BLACK_LEVEL = V4L2_CID_BASE + 11 # Deprecated +V4L2_CID_BLACK_LEVEL = V4L2_CID_BASE + 11 # Deprecated V4L2_CID_AUTO_WHITE_BALANCE = V4L2_CID_BASE + 12 V4L2_CID_DO_WHITE_BALANCE = V4L2_CID_BASE + 13 V4L2_CID_RED_BALANCE = V4L2_CID_BASE + 14 V4L2_CID_BLUE_BALANCE = V4L2_CID_BASE + 15 V4L2_CID_GAMMA = V4L2_CID_BASE + 16 -V4L2_CID_WHITENESS = V4L2_CID_GAMMA # Deprecated +V4L2_CID_WHITENESS = V4L2_CID_GAMMA # Deprecated V4L2_CID_EXPOSURE = V4L2_CID_BASE + 17 V4L2_CID_AUTOGAIN = V4L2_CID_BASE + 18 V4L2_CID_GAIN = V4L2_CID_BASE + 19 @@ -1286,7 +1283,7 @@ v4l2_mpeg_audio_crc = enum V4L2_CID_MPEG_AUDIO_MUTE = V4L2_CID_MPEG_BASE + 109 V4L2_CID_MPEG_AUDIO_AAC_BITRATE = V4L2_CID_MPEG_BASE + 110 -V4L2_CID_MPEG_AUDIO_AC3_BITRATE = V4L2_CID_MPEG_BASE + 111 +V4L2_CID_MPEG_AUDIO_AC3_BITRATE = V4L2_CID_MPEG_BASE + 111 v4l2_mpeg_audio_ac3_bitrate = enum ( @@ -1472,7 +1469,6 @@ v4l2_preemphasis = enum V4L2_CID_TUNE_POWER_LEVEL = V4L2_CID_FM_TX_CLASS_BASE + 113 V4L2_CID_TUNE_ANTENNA_CAPACITOR = V4L2_CID_FM_TX_CLASS_BASE + 114 - # JPEG-class control IDs V4L2_CID_JPEG_CLASS_BASE = V4L2_CTRL_CLASS_JPEG | 0x900 @@ -1480,7 +1476,7 @@ V4L2_CID_JPEG_CLASS = V4L2_CTRL_CLASS_JPEG | 1 V4L2_CID_JPEG_CHROMA_SUBSAMPLING = V4L2_CID_JPEG_CLASS_BASE + 1 -v4l2_jpeg_chroma_subsampling = enum +v4l2_jpeg_chroma_subsampling = enum ( V4L2_JPEG_CHROMA_SUBSAMPLING_444, V4L2_JPEG_CHROMA_SUBSAMPLING_422, @@ -1493,18 +1489,18 @@ v4l2_jpeg_chroma_subsampling = enum V4L2_CID_JPEG_RESTART_INTERVAL = V4L2_CID_JPEG_CLASS_BASE + 2 V4L2_CID_JPEG_COMPRESSION_QUALITY = V4L2_CID_JPEG_CLASS_BASE + 3 -V4L2_CID_JPEG_ACTIVE_MARKER = V4L2_CID_JPEG_CLASS_BASE + 4 +V4L2_CID_JPEG_ACTIVE_MARKER = V4L2_CID_JPEG_CLASS_BASE + 4 V4L2_JPEG_ACTIVE_MARKER_APP0 = 1 << 0 V4L2_JPEG_ACTIVE_MARKER_APP1 = 1 << 1 -V4L2_JPEG_ACTIVE_MARKER_COM = 1 << 16 -V4L2_JPEG_ACTIVE_MARKER_DQT = 1 << 17 -V4L2_JPEG_ACTIVE_MARKER_DHT = 1 << 18 - +V4L2_JPEG_ACTIVE_MARKER_COM = 1 << 16 +V4L2_JPEG_ACTIVE_MARKER_DQT = 1 << 17 +V4L2_JPEG_ACTIVE_MARKER_DHT = 1 << 18 # # Tuning # + class v4l2_tuner(ctypes.Structure): _fields_ = [ ('index', ctypes.c_uint32), @@ -1579,6 +1575,7 @@ class v4l2_hw_freq_seek(ctypes.Structure): # RDS # + class v4l2_rds_data(ctypes.Structure): _fields_ = [ ('lsb', ctypes.c_char), @@ -1589,7 +1586,7 @@ class v4l2_rds_data(ctypes.Structure): _pack_ = True -V4L2_RDS_BLOCK_MSK = 0x7 +V4L2_RDS_BLOCK_MSK = 0x7 V4L2_RDS_BLOCK_A = 0 V4L2_RDS_BLOCK_B = 1 V4L2_RDS_BLOCK_C = 2 @@ -1600,11 +1597,11 @@ V4L2_RDS_BLOCK_INVALID = 7 V4L2_RDS_BLOCK_CORRECTED = 0x40 V4L2_RDS_BLOCK_ERROR = 0x80 - # # Audio # + class v4l2_audio(ctypes.Structure): _fields_ = [ ('index', ctypes.c_uint32), @@ -1672,7 +1669,9 @@ V4L2_ENC_CMD_STOP_AT_GOP_END = 1 << 0 class v4l2_encoder_cmd(ctypes.Structure): + class _u(ctypes.Union): + class _s(ctypes.Structure): _fields_ = [ ('data', ctypes.c_uint32 * 8), @@ -1688,13 +1687,14 @@ class v4l2_encoder_cmd(ctypes.Structure): ('_u', _u), ] - _anonymous_ = ('_u',) + _anonymous_ = ('_u', ) # # Data services (VBI) # + class v4l2_vbi_format(ctypes.Structure): _fields_ = [ ('sampling_rate', ctypes.c_uint32), @@ -1726,8 +1726,8 @@ V4L2_SLICED_VPS = 0x0400 V4L2_SLICED_CAPTION_525 = 0x1000 V4L2_SLICED_WSS_625 = 0x4000 V4L2_SLICED_VBI_525 = V4L2_SLICED_CAPTION_525 -V4L2_SLICED_VBI_625 = ( - V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625) +V4L2_SLICED_VBI_625 = (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS + | V4L2_SLICED_WSS_625) class v4l2_sliced_vbi_cap(ctypes.Structure): @@ -1753,7 +1753,6 @@ class v4l2_sliced_vbi_data(ctypes.Structure): # Sliced VBI data inserted into MPEG Streams # - V4L2_MPEG_VBI_IVTV_TELETEXT_B = 1 V4L2_MPEG_VBI_IVTV_CAPTION_525 = 4 V4L2_MPEG_VBI_IVTV_WSS_625 = 5 @@ -1771,7 +1770,7 @@ class v4l2_mpeg_vbi_itv0_line(ctypes.Structure): class v4l2_mpeg_vbi_itv0(ctypes.Structure): _fields_ = [ - ('linemask', ctypes.c_uint32 * 2), # how to define __le32 in ctypes? + ('linemask', ctypes.c_uint32 * 2), # how to define __le32 in ctypes? ('line', v4l2_mpeg_vbi_itv0_line * 35), ] @@ -1791,18 +1790,16 @@ V4L2_MPEG_VBI_IVTV_MAGIC1 = "ITV0" class v4l2_mpeg_vbi_fmt_ivtv(ctypes.Structure): + class _u(ctypes.Union): _fields_ = [ ('itv0', v4l2_mpeg_vbi_itv0), ('ITV0', v4l2_mpeg_vbi_ITV0), ] - _fields_ = [ - ('magic', ctypes.c_char * 4), - ('_u', _u) - ] + _fields_ = [('magic', ctypes.c_char * 4), ('_u', _u)] - _anonymous_ = ('_u',) + _anonymous_ = ('_u', ) _pack_ = True @@ -1810,7 +1807,9 @@ class v4l2_mpeg_vbi_fmt_ivtv(ctypes.Structure): # Aggregate structures # + class v4l2_format(ctypes.Structure): + class _u(ctypes.Union): _fields_ = [ ('pix', v4l2_pix_format), @@ -1827,6 +1826,7 @@ class v4l2_format(ctypes.Structure): class v4l2_streamparm(ctypes.Structure): + class _u(ctypes.Union): _fields_ = [ ('capture', v4l2_captureparm), @@ -1834,10 +1834,7 @@ class v4l2_streamparm(ctypes.Structure): ('raw_data', ctypes.c_char * 200), ] - _fields_ = [ - ('type', v4l2_buf_type), - ('parm', _u) - ] + _fields_ = [('type', v4l2_buf_type), ('parm', _u)] # @@ -1851,6 +1848,7 @@ V4L2_CHIP_MATCH_AC97 = 3 class v4l2_dbg_match(ctypes.Structure): + class _u(ctypes.Union): _fields_ = [ ('addr', ctypes.c_uint32), @@ -1862,7 +1860,7 @@ class v4l2_dbg_match(ctypes.Structure): ('_u', _u), ] - _anonymous_ = ('_u',) + _anonymous_ = ('_u', ) _pack_ = True @@ -1897,7 +1895,7 @@ VIDIOC_ENUM_FMT = _IOWR('V', 2, v4l2_fmtdesc) VIDIOC_G_FMT = _IOWR('V', 4, v4l2_format) VIDIOC_S_FMT = _IOWR('V', 5, v4l2_format) VIDIOC_REQBUFS = _IOWR('V', 8, v4l2_requestbuffers) -VIDIOC_QUERYBUF = _IOWR('V', 9, v4l2_buffer) +VIDIOC_QUERYBUF = _IOWR('V', 9, v4l2_buffer) VIDIOC_G_FBUF = _IOR('V', 10, v4l2_framebuffer) VIDIOC_S_FBUF = _IOW('V', 11, v4l2_framebuffer) VIDIOC_OVERLAY = _IOW('V', 14, ctypes.c_int) @@ -1925,7 +1923,7 @@ VIDIOC_G_OUTPUT = _IOR('V', 46, ctypes.c_int) VIDIOC_S_OUTPUT = _IOWR('V', 47, ctypes.c_int) VIDIOC_ENUMOUTPUT = _IOWR('V', 48, v4l2_output) VIDIOC_G_AUDOUT = _IOR('V', 49, v4l2_audioout) -VIDIOC_S_AUDOUT = _IOW('V', 50, v4l2_audioout) +VIDIOC_S_AUDOUT = _IOW('V', 50, v4l2_audioout) VIDIOC_G_MODULATOR = _IOWR('V', 54, v4l2_modulator) VIDIOC_S_MODULATOR = _IOW('V', 55, v4l2_modulator) VIDIOC_G_FREQUENCY = _IOWR('V', 56, v4l2_frequency) diff --git a/src/py/inevent/AbsAxisScaling.py b/src/py/inevent/AbsAxisScaling.py deleted file mode 100644 index 4b00721..0000000 --- a/src/py/inevent/AbsAxisScaling.py +++ /dev/null @@ -1,106 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -# The inevent Python module was adapted from pi3d.event from the pi3d -# project. -# -# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC. -# Copyright (c) 2015, Tim Skillman. -# Copyright (c) 2015, Paddy Gaunt. -# Copyright (c) 2015, Tom Ritchford. -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -import array -import fcntl -import struct -from inevent import ioctl - - -def EVIOCGABS(axis): - return ioctl._IOR(ord('E'), 0x40 + axis, "ffffff") # get abs value/limits - - - -class AbsAxisScaling(object): - """ - Fetches and implements the EV_ABS axis scaling. - - The constructor fetches the scaling values from the given stream for the - given axis using an ioctl. - - There is a scale method, which scales a given value to the range -1..+1. - """ - - def __init__(self, stream, axis): - """ - Fetch the scale values for this stream and fill in the instance - variables accordingly. - """ - s = array.array("i", [1, 2, 3, 4, 5, 6]) - try: - fcntl.ioctl(stream.filehandle, EVIOCGABS(axis), s) - - except IOError: - self.value = self.minimum = self.maximum = self.fuzz = self.flat = \ - self.resolution = 1 - - else: - self.value, self.minimum, self.maximum, self.fuzz, self.flat, \ - self.resolution = struct.unpack("iiiiii", s) - - - def __str__(self): - return "Value {0} Min {1}, Max {2}, Fuzz {3}, Flat {4}, Res {5}".format( - self.value, self.minimum, self.maximum, self.fuzz, self.flat, - self.resolution) - - - def scale(self, value): - """ - scales the given value into the range -1..+1 - """ - return (float(value) - float(self.minimum)) / \ - float(self.maximum - self.minimum) * 2.0 - 1.0 diff --git a/src/py/inevent/Constants.py b/src/py/inevent/Constants.py deleted file mode 100644 index 0f3a2ed..0000000 --- a/src/py/inevent/Constants.py +++ /dev/null @@ -1,124 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -# The inevent Python module was adapted from pi3d.event from the pi3d -# project. -# -# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC. -# Copyright (c) 2015, Tim Skillman. -# Copyright (c) 2015, Paddy Gaunt. -# Copyright (c) 2015, Tom Ritchford. -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -EV_SYN = 0x00 -EV_KEY = 0x01 -EV_REL = 0x02 -EV_ABS = 0x03 -EV_MSC = 0x04 -EV_SW = 0x05 -EV_LED = 0x11 -EV_SND = 0x12 -EV_REP = 0x14 -EV_FF = 0x15 -EV_PWR = 0x16 -EV_FF_STATUS = 0x17 - -ev_type_name = {} -ev_type_name[EV_SYN] = "SYN" -ev_type_name[EV_KEY] = "KEY" -ev_type_name[EV_REL] = "REL" -ev_type_name[EV_ABS] = "ABS" -ev_type_name[EV_MSC] = "MSC" -ev_type_name[EV_SW] = "SW" -ev_type_name[EV_LED] = "LED" -ev_type_name[EV_SND] = "SND" -ev_type_name[EV_REP] = "REP" -ev_type_name[EV_FF] = "FF" -ev_type_name[EV_PWR] = "PWR" -ev_type_name[EV_FF_STATUS] = "FF_STATUS" - -SYN_REPORT = 0 -SYN_CONFIG = 1 - -REL_X = 0x00 -REL_Y = 0x01 -REL_Z = 0x02 -REL_RX = 0x03 -REL_RY = 0x04 -REL_RZ = 0x05 -REL_HWHEEL = 0x06 -REL_DIAL = 0x07 -REL_WHEEL = 0x08 -REL_MISC = 0x09 -REL_MAX = 0x0f - -ABS_X = 0x00 -ABS_Y = 0x01 -ABS_Z = 0x02 -ABS_RX = 0x03 -ABS_RY = 0x04 -ABS_RZ = 0x05 -ABS_THROTTLE = 0x06 -ABS_RUDDER = 0x07 -ABS_WHEEL = 0x08 -ABS_GAS = 0x09 -ABS_BRAKE = 0x0a -ABS_HAT0X = 0x10 -ABS_HAT0Y = 0x11 -ABS_HAT1X = 0x12 -ABS_HAT1Y = 0x13 -ABS_HAT2X = 0x14 -ABS_HAT2Y = 0x15 -ABS_HAT3X = 0x16 -ABS_HAT3Y = 0x17 -ABS_PRESSURE = 0x18 -ABS_DISTANCE = 0x19 -ABS_TILT_X = 0x1a -ABS_TILT_Y = 0x1b -ABS_TOOL_WIDTH = 0x1c -ABS_VOLUME = 0x20 -ABS_MISC = 0x28 -ABS_MAX = 0x3f diff --git a/src/py/inevent/Event.py b/src/py/inevent/Event.py deleted file mode 100644 index bf8f2e1..0000000 --- a/src/py/inevent/Event.py +++ /dev/null @@ -1,142 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -# The inevent Python module was adapted from pi3d.event from the pi3d -# project. -# -# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC. -# Copyright (c) 2015, Tim Skillman. -# Copyright (c) 2015, Paddy Gaunt. -# Copyright (c) 2015, Tom Ritchford. -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -import struct - -from inevent.Constants import * - - -_format = 'llHHi' -size = struct.calcsize(_format) - - -class Event(object): - """ - A single event from the linux input event system. - - Events are tuples: (Time, Type, Code, Value) - In addition we remember the stream it came from. - - Externally, only the unhandled event handler gets passed the whole event, - but the SYN handler gets the code and value. (Also the keyboard handler, but - those are renamed to key and value.) - - This class is responsible for converting the Linux input event structure into - one of these objects and back again. - """ - def __init__(self, stream, time = None, type = None, code = None, - value = None): - """ - Create a new event. - - Generally all but the stream parameter are left out; we will want to - populate the object from a Linux input event using decode. - """ - self.stream = stream - self.time = time - self.type = type - self.code = code - self.value = value - - - def get_type_name(self): - if self.type not in ev_type_name: return '0x%x' % self.type - return ev_type_name[self.type] - - - def get_source(self): - return "%s[%d]" % (self.stream.devType, self.stream.devIndex) - - - def __str__(self): - """ - Uses the stream to give the device type and whether it is currently grabbed. - """ - grabbed = "grabbed" if self.stream.grabbed else "ungrabbed" - - return "Event %s %s @%f: %s 0x%x=0x%x" % ( - self.get_source(), grabbed, self.time, self.get_type_name(), self.code, - self.value) - - - def __repr__(self): - return "Event(%s, %f, 0x%x, 0x%x, 0x%x)" % ( - repr(self.stream), self.time, self.type, self.code, self.value) - - - def encode(self): - """ - Encode this event into a Linux input event structure. - - The output is packed into a string. It is unlikely that this function - will be required, but it might as well be here. - """ - tsec = int(self.time) - tfrac = int((self.time - tsec) * 1000000) - - return struct.pack(_format, tsec, tfrac, self.type, self.code, self.value) - - - def decode(self, s): - """ - Decode a Linux input event into the fields of this object. - - Arguments: - *s* - A binary structure packed into a string. - """ - tsec, tfrac, self.type, self.code, self.value = struct.unpack(_format, s) - - self.time = tsec + tfrac / 1000000.0 diff --git a/src/py/inevent/EventHandler.py b/src/py/inevent/EventHandler.py deleted file mode 100644 index ccc9d7c..0000000 --- a/src/py/inevent/EventHandler.py +++ /dev/null @@ -1,146 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -# The inevent Python module was adapted from pi3d.event from the pi3d -# project. -# -# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC. -# Copyright (c) 2015, Tim Skillman. -# Copyright (c) 2015, Paddy Gaunt. -# Copyright (c) 2015, Tom Ritchford. -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -from inevent.Constants import * -from inevent.EventStream import EventStream - - -class EventHandler(object): - """ - A class to handle events. - - Four types of events are handled: REL (mouse movement), KEY (keybaord keys and - other device buttons), ABS (joysticks and gamepad analogue sticks) and SYN - (delimits simultaneous events such as mouse movements) - """ - def __init__(self): - self.buttons = dict() - - - def event(self, event, handler, name): - """ - Handles the given event. - - If the event is passed to a handler or otherwise handled then returns None, - else returns the event. All handlers are optional. - - All key events are handled by putting them in the self.buttons dict, and - optionally by calling the supplied handler. - - REL X, Y and wheel V and H events are all accumulated internally and - also optionally passed to the supplied handler. All these events are - handled. - - ABS X, Y, Z, RX, RY, RZ, Hat0X, Hat0Y are all accumulated internally and - also optionally passed to the supplied handler. Other ABS events are not - handled. - - All SYN events are passed to the supplied handler. - - There are several ABS events that we do not handle. In particular: - THROTTLE, RUDDER, WHEEL, GAS, BRAKE, HAT1, HAT2, HAT3, PRESSURE, - DISTANCE, TILT, TOOL_WIDTH. Implementing these is left as an exercise - for the interested reader. - - Likewise, since one handler is handling all events for all devices, we - may get the situation where two devices return the same button. The only - way to handle that would seem to be to have a key dict for every device, - which seems needlessly profligate for a situation that may never arise. - """ - - state = event.stream.state - - if event.type == EV_KEY: self.buttons[event.code] = event.value - elif event.type == EV_REL: state.rel[event.code] += event.value - elif event.type == EV_ABS: - state.abs[event.code] = event.stream.scale(event.code, event.value) - - if handler: handler.event(event, state, name) - - - def key_state(self, code): - """ - Returns the last event value for the given key code. - - Key names can be converted to key codes using codeOf[str]. - If the key is pressed the returned value will be 1 (pressed) or 2 (held). - If the key is not pressed, the returned value will be 0. - """ - return self.buttons.get(code, 0) - - - def clear_key(self, code): - """ - Clears the event value for the given key code. - - Key names can be converted to key codes using codeOf[str]. - This emulates a key-up but does not generate any events. - """ - self.buttons[code] = 0 - - - def get_keys(self): - """ - Returns the first of whichever keys have been pressed. - - Key names can be converted to key codes using codeOf[str]. - This emulates a key-up but does not generate any events. - """ - k_list = [] - - for k in self.buttons: - if self.buttons[k] != 0: k_list.append(k) - - return k_list diff --git a/src/py/inevent/EventState.py b/src/py/inevent/EventState.py deleted file mode 100644 index d1443bf..0000000 --- a/src/py/inevent/EventState.py +++ /dev/null @@ -1,145 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -# The inevent Python module was adapted from pi3d.event from the pi3d -# project. -# -# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC. -# Copyright (c) 2015, Tim Skillman. -# Copyright (c) 2015, Paddy Gaunt. -# Copyright (c) 2015, Tom Ritchford. -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -from inevent.Constants import * - - -class EventState: - def __init__(self): - self.abs = [0.0] * ABS_MAX - self.rel = [0.0] * REL_MAX - - - def __str__(self): - return ("({:6.3f}, {:6.3f}, {:6.3f}) ".format(*self.get_joystick3d()) + - "({:6.3f}, {:6.3f}, {:6.3f}) ".format(*self.get_joystickR3d()) + - "({:2.0f}, {:2.0f}) ".format(*self.get_hat()) + - "({:0.2f}, {:0.2f}) ".format(*self.get_mouse()) + - "({:0.2f}, {:0.2f})".format(*self.get_wheel())) - - - def get_joystick(self): - """ - Returns the x,y coordinates for a joystick or left gamepad analogue stick. - - The values are returned as a tuple. All values are -1.0 to +1.0 with - 0.0 being centred. - """ - return self.abs[ABS_X], self.abs[ABS_Y] - - - def get_joystick3d(self): - """ - Returns the x,y,z coordinates for a joystick or left gamepad analogue stick - - The values are returned as a tuple. All values are -1.0 to +1.0 with - 0.0 being centred. - """ - return self.abs[ABS_X], self.abs[ABS_Y], self.abs[ABS_Z] - - - def get_joystickR(self): - """ - Returns the x,y coordinates for a right gamepad analogue stick. - - The values are returned as a tuple. For some odd reason, the gamepad - returns values in the Z axes of both joysticks, with y being the first. - - All values are -1.0 to +1.0 with 0.0 being centred. - """ - return self.abs[ABS_RZ], self.abs[ABS_Z] - - - def get_joystickR3d(self): - """ - Returns the x,y,z coordinates for a 2nd joystick control - - The values are returned as a tuple. All values are -1.0 to +1.0 with - 0.0 being centred. - """ - return self.abs[ABS_RX], self.abs[ABS_RY], self.abs[ABS_RZ] - - - def get_hat(self): - """ - Returns the x,y coordinates for a joystick hat or gamepad direction pad - - The values are returned as a tuple. All values are -1.0 to +1.0 with - 0.0 being centred. - """ - return self.abs[ABS_HAT0X], self.abs[ABS_HAT0Y] - - - def get_mouse(self): - return self.rel[REL_X], self.rel[REL_Y] - - - def get_wheel(self): - return self.rel[REL_WHEEL], self.rel[REL_HWHEEL] - - - def get_mouse_movement(self): - """ - Returns the accumulated REL (mouse or other relative device) movements - since the last call. - - The returned value is a tuple: (X, Y, WHEEL, H-WHEEL) - """ - ret = self.get_mouse() + self.get_wheel() - - self.rel[REL_X] = self.rel[REL_Y] = 0 - self.rel[REL_WHEEL] = self.rel[REL_HWHEEL] = 0 - - return ret diff --git a/src/py/inevent/EventStream.py b/src/py/inevent/EventStream.py deleted file mode 100644 index aac648d..0000000 --- a/src/py/inevent/EventStream.py +++ /dev/null @@ -1,218 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -# The inevent Python module was adapted from pi3d.event from the pi3d -# project. -# -# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC. -# Copyright (c) 2015, Tim Skillman. -# Copyright (c) 2015, Paddy Gaunt. -# Copyright (c) 2015, Tom Ritchford. -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -import fcntl -import os -import select -import logging - -from inevent.Constants import * -from inevent import ioctl -from inevent.AbsAxisScaling import AbsAxisScaling -from inevent import Event -from inevent.EventState import EventState - - -log = logging.getLogger('inevent') - -EVIOCGRAB = ioctl._IOW(ord('E'), 0x90, "i") # Grab/Release device - - - -class EventStream(object): - """ - encapsulates the event* file handling - - Each device is represented by a file in /dev/input called eventN, where N is - a small number. (Actually, a keybaord can be represented by two such files.) - Instances of this class open one of these files and provide means to read - events from them. - - Class methods also exist to read from multiple files simultaneously, and - also to grab and ungrab all instances of a given type. - """ - axisX = 0 - axisY = 1 - axisZ = 2 - axisRX = 3 - axisRY = 4 - axisRZ = 5 - axisHat0X = 6 - axisHat0Y = 7 - axisHat1X = 8 - axisHat1Y = 9 - axisHat2X = 10 - axisHat2Y = 11 - axisHat3X = 12 - axisHat3Y = 13 - axisThrottle = 14 - axisRudder = 15 - axisWheel = 16 - axisGas = 17 - axisBrake = 18 - axisPressure = 19 - axisDistance = 20 - axisTiltX = 21 - axisTiltY = 22 - axisToolWidth = 23 - numAxes = 24 - - axisToEvent = [ - ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ, ABS_HAT0X, ABS_HAT0Y, - ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y, ABS_HAT3X, ABS_HAT3Y, - ABS_THROTTLE, ABS_RUDDER, ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_PRESSURE, - ABS_DISTANCE, ABS_TILT_X, ABS_TILT_Y, ABS_TOOL_WIDTH] - - - def __init__(self, devIndex, devType, devName): - """ - Opens the given /dev/input/event file and grabs it. - - Also adds it to a class-global list of all existing streams. - """ - self.devIndex = devIndex - self.devType = devType - self.devName = devName - self.filename = "/dev/input/event" + str(devIndex) - self.filehandle = os.open(self.filename, os.O_RDWR) - self.state = EventState() - self.grab(True) - self.absInfo = [None] * ABS_MAX - - if devType == "js": - for axis in range(ABS_MAX): - self.absInfo[axis] = AbsAxisScaling(self, axis) - - - def scale(self, axis, value): - """ - Scale the given value according to the given axis. - - acquire_abs_info must have been previously called to acquire the data to - do the scaling. - """ - assert axis < ABS_MAX, "Axis number out of range" - - if self.absInfo[axis]: return self.absInfo[axis].scale(value) - else: return value - - - def grab(self, grab = True): - """ - Grab (or release) exclusive access to all devices of the given type. - - The devices are grabbed if grab is True and released if grab is False. - - All devices are grabbed to begin with. We might want to ungrab the - keyboard for example to use it for text entry. While not grabbed, all - key-down and key-hold events are filtered out. - """ - fcntl.ioctl(self.filehandle, EVIOCGRAB, 1 if grab else 0) - self.grabbed = grab - - - def __iter__(self): - """s - Required to make this class an iterator - """ - return self - - - def next(self): return self.__next__() - - - def __next__(self): - """ - Returns the next waiting event. - - If no event is waiting, returns None. - """ - ready = select.select([self.filehandle], [], [], 0)[0] - if ready: return self.read() - - - def read(self): - """ - Read and return the next waiting event. - """ - try: - s = os.read(self.filehandle, Event.size) - if s: - event = Event.Event(self) - event.decode(s) - return event - - except Exception as e: - log.info('Reading event: %s' % e) - - - def __enter__(self): return self - - - def release(self): - "Ungrabs the file and closes it." - - try: - self.grab(False) - os.close(self.filehandle) - - except: - pass - - - def __exit__(self, type, value, traceback): - "Ungrabs the file and closes it." - - self.release() diff --git a/src/py/inevent/FindDevices.py b/src/py/inevent/FindDevices.py deleted file mode 100644 index 2f3970a..0000000 --- a/src/py/inevent/FindDevices.py +++ /dev/null @@ -1,245 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -# The inevent Python module was adapted from pi3d.event from the pi3d -# project. -# -# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC. -# Copyright (c) 2015, Tim Skillman. -# Copyright (c) 2015, Paddy Gaunt. -# Copyright (c) 2015, Tom Ritchford. -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -import re -import logging -from inevent.Constants import * - -log = logging.getLogger('inevent') - - -def test_bit(nlst, b): - index = b / 32 - bit = b % 32 - return index < len(nlst) and nlst[index] & (1 << bit) - - -def EvToStr(events): - s = [] - - if test_bit(events, EV_SYN): s.append("EV_SYN") - if test_bit(events, EV_KEY): s.append("EV_KEY") - if test_bit(events, EV_REL): s.append("EV_REL") - if test_bit(events, EV_ABS): s.append("EV_ABS") - if test_bit(events, EV_MSC): s.append("EV_MSC") - if test_bit(events, EV_LED): s.append("EV_LED") - if test_bit(events, EV_SND): s.append("EV_SND") - if test_bit(events, EV_REP): s.append("EV_REP") - if test_bit(events, EV_FF): s.append("EV_FF" ) - if test_bit(events, EV_PWR): s.append("EV_PWR") - if test_bit(events, EV_FF_STATUS): s.append("EV_FF_STATUS") - - return s - - -class DeviceCapabilities(object): - def __init__(self, firstLine, filehandle): - self.EV_SYNevents = [] - self.EV_KEYevents = [] - self.EV_RELevents = [] - self.EV_ABSevents = [] - self.EV_MSCevents = [] - self.EV_LEDevents = [] - self.EV_SNDevents = [] - self.EV_REPevents = [] - self.EV_FFevents = [] - self.EV_PWRevents = [] - self.EV_FF_STATUSevents = [] - self.eventTypes = [] - - match = re.search(".*Bus=([0-9A-Fa-f]+).*Vendor=([0-9A-Fa-f]+).*" - "Product=([0-9A-Fa-f]+).*Version=([0-9A-Fa-f]+).*", - firstLine) - - if not match: - log.warning("Do not understand device ID: %s", firstLine) - self.bus = 0 - self.vendor = 0 - self.product = 0 - self.version = 0 - - else: - self.bus = int(match.group(1), base = 16) - self.vendor = int(match.group(2), base = 16) - self.product = int(match.group(3), base = 16) - self.version = int(match.group(4), base = 16) - - for line in filehandle: - if not line.strip(): break - - if line[0] == "N": - match = re.search('Name="([^"]+)"', line) - if match: self.name = match.group(1) - else: self.name = "UNKNOWN" - - elif line[0] == "P": - match = re.search('Phys=(.+)', line) - if match: self.phys = match.group(1) - else: self.phys = "UNKNOWN" - - elif line[0] == "S": - match = re.search('Sysfs=(.+)', line) - if match: self.sysfs = match.group(1) - else: self.sysfs = "UNKNOWN" - - elif line[0] == "U": - match = re.search('Uniq=(.*)', line) - if match: self.uniq = match.group(1) - else: self.uniq = "UNKNOWN" - - elif line[0] == "H": - match = re.search('Handlers=(.+)', line) - if match: self.handlers = match.group(1).split() - else: self.handlers = [] - - elif line[:5] == "B: EV": - eventsNums = [int(x, base = 16) for x in line[6:].split()] - eventsNums.reverse() - self.eventTypes = eventsNums - - elif line[:6] == "B: KEY": - eventsNums = [int(x, base = 16) for x in line[7:].split()] - eventsNums.reverse() - self.EV_KEYevents = eventsNums - - elif line[:6] == "B: ABS": - eventsNums = [int(x, base = 16) for x in line[7:].split()] - eventsNums.reverse() - self.EV_ABSevents = eventsNums - - elif line[:6] == "B: MSC": - eventsNums = [int(x, base = 16) for x in line[7:].split()] - eventsNums.reverse() - self.EV_MSCevents = eventsNums - - elif line[:6] == "B: REL": - eventsNums = [int(x, base = 16) for x in line[7:].split()] - eventsNums.reverse() - self.EV_RELevents = eventsNums - - elif line[:6] == "B: LED": - eventsNums = [int(x, base = 16) for x in line[7:].split()] - eventsNums.reverse() - self.EV_LEDevents = eventsNums - - for handler in self.handlers: - if handler[:5] == "event": self.eventIndex = int(handler[5:]) - - self.isMouse = False - self.isKeyboard = False - self.isJoystick = False - - - def doesProduce(self, eventType, eventCode): - return test_bit(self.eventTypes, eventType) and ( - (eventType == EV_SYN and test_bit(self.EV_SYNevents, eventCode)) or - (eventType == EV_KEY and test_bit(self.EV_KEYevents, eventCode)) or - (eventType == EV_REL and test_bit(self.EV_RELevents, eventCode)) or - (eventType == EV_ABS and test_bit(self.EV_ABSevents, eventCode)) or - (eventType == EV_MSC and test_bit(self.EV_MSCevents, eventCode)) or - (eventType == EV_LED and test_bit(self.EV_LEDevents, eventCode)) or - (eventType == EV_SND and test_bit(self.EV_SNDevents, eventCode)) or - (eventType == EV_REP and test_bit(self.EV_REPevents, eventCode)) or - (eventType == EV_FF and test_bit(self.EV_FFevents, eventCode)) or - (eventType == EV_PWR and test_bit(self.EV_PWRevents, eventCode)) or - (eventType == EV_FF_STATUS and - test_bit(self.EV_FF_STATUSevents, eventCode))) - - - def __str__(self): - return ( - ("%s\n" - "Bus: %s Vendor: %s Product: %s Version: %s\n" - "Phys: %s\n" - "Sysfs: %s\n" - "Uniq: %s\n" - "Handlers: %s Event Index: %s\n" - "Keyboard: %s Mouse: %s Joystick: %s\n" - "Events: %s") % ( - self.name, self.bus, self.vendor, self.product, self.version, self.phys, - self.sysfs, self.uniq, self.handlers, self.eventIndex, self.isKeyboard, - self.isMouse, self.isJoystick, EvToStr(self.eventTypes))) - - -deviceCapabilities = [] - - -def get_devices(filename = "/proc/bus/input/devices"): - global deviceCapabilities - - with open("/proc/bus/input/devices", "r") as filehandle: - for line in filehandle: - if line[0] == "I": - deviceCapabilities.append(DeviceCapabilities(line, filehandle)) - - return deviceCapabilities - - -def print_devices(): - devs = get_devices() - - for dev in devs: - print(str(dev)) - print(" ABS: {}" - .format([x for x in range(64) if test_bit(dev.EV_ABSevents, x)])) - print(" REL: {}" - .format([x for x in range(64) if test_bit(dev.EV_RELevents, x)])) - print(" MSC: {}" - .format([x for x in range(64) if test_bit(dev.EV_MSCevents, x)])) - print(" KEY: {}" - .format([x for x in range(512) if test_bit(dev.EV_KEYevents, x)])) - print(" LED: {}" - .format([x for x in range(64) if test_bit(dev.EV_LEDevents, x)])) - print() diff --git a/src/py/inevent/InEvent.py b/src/py/inevent/InEvent.py deleted file mode 100644 index a85ea44..0000000 --- a/src/py/inevent/InEvent.py +++ /dev/null @@ -1,288 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -# The inevent Python module was adapted from pi3d.event from the pi3d -# project. -# -# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC. -# Copyright (c) 2015, Tim Skillman. -# Copyright (c) 2015, Paddy Gaunt. -# Copyright (c) 2015, Tom Ritchford. -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -import pyudev -import re -import select -import errno -import functools -import logging - -from inevent.EventHandler import EventHandler -from inevent import Keys -from inevent.Constants import * -from inevent.EventStream import EventStream - - -log = logging.getLogger('inevent') - -_KEYS = (k for k in vars(Keys) if not k.startswith('_')) -KEY_CODE = dict((k, getattr(Keys, k)) for k in _KEYS) -CODE_KEY = {} -for v in KEY_CODE: CODE_KEY[KEY_CODE[v]] = v - - -def key_to_code(key): - return KEY_CODE.get(str(key), -1) \ - if isinstance(key, str) else key - - -def code_to_key(code): return CODE_KEY.get(code, '') - - -class InEvent(object): - """Encapsulates the entire InEvent subsystem. - - This is generally all you need to import. - - On instantiation, we open all devices that are keyboards, mice or joysticks. - That means we might have two of one sort of another, and that might be a - problem, but it would be rather rare. - - There are several ABS (joystick, touch) events that we do not handle, - specifically THROTTLE, RUDDER, WHEEL, GAS, BRAKE, HAT1, HAT2, HAT3, PRESSURE, - DISTANCE, TILT, TOOL_WIDTH. Implementing these is left as an exercise - for the interested reader. Similarly, we make no attempt to handle - multi-touch. - - Handlers can be supplied, in which case they are called for each event, but - it isn't necessary; API exists for all the events. - - The handler signature is: - - def handler_func(event, state) - - where: - event: - An Event object describing the event. - - state: - An EventState object describing the current state. - - Use key_to_code() to convert from the name of a key to its code, - and code_to_key() to convert a code to a name. - - The keys are listed in inevent.Constants.py or /usr/include/linux/input.h - Note that the key names refer to a US keyboard. - """ - def __init__(self, ioloop, cb, types = 'kbd mouse js'.split()): - self.ioloop = ioloop - self.cb = cb - self.streams = [] - self.handler = EventHandler() - self.types = types - - self.udevCtx = pyudev.Context() - self.udevMon = pyudev.Monitor.from_netlink(self.udevCtx) - self.udevMon.filter_by(subsystem = 'input') - - devs = list(self.find_devices(types)) - for index, type, name in devs: - self.add_stream(index, type, name) - - self.udevMon.start() - ioloop.add_handler(self.udevMon.fileno(), self.udev_handler, ioloop.READ) - - - def get_dev(self, index): - return pyudev.Device.from_name(self.udevCtx, 'input', 'event%s' % index) - - - def get_dev_name(self, index): - try: - dev = self.get_dev(index) - return dev.parent.attributes.asstring('name').decode('utf-8') - except: pass - - - def find_devices(self, types): - """Finds the event indices of all devices of the specified types. - - A type is a string on the handlers line of /proc/bus/input/devices. - Keyboards use "kbd", mice use "mouse" and joysticks (and gamepads) use "js". - - Returns a list of integer indexes N, where /dev/input/eventN is the event - stream for each device. - - If butNot is given it holds a list of tuples which the returned values - should not match. - - All devices of each type are returned; if you have two mice, they will both - be used. - """ - with open("/proc/bus/input/devices", "r") as filehandle: - for line in filehandle: - if line[0] == "H": - for type in types: - if type in line: - match = re.search("event([0-9]+)", line) - index = match and match.group(1) - if index: - yield int(index), type, self.get_dev_name(index) - break - - - def process_udev_event(self): - action, device = self.udevMon.receive_device() - if device is None: return - - match = re.search(r"/dev/input/event([0-9]+)", str(device.device_node)) - devIndex = match and match.group(1) - if not devIndex: return - devIndex = int(devIndex) - - if action == 'add': - for index, devType, devName in self.find_devices(self.types): - if index == devIndex: - self.add_stream(devIndex, devType, devName) - break - - if action == 'remove': self.remove_stream(devIndex) - - - def stream_handler(self, fd, events): - for stream in self.streams: - if stream.filehandle == fd: - while True: - event = stream.next() - if event: self.handler.event(event, self.cb, stream.devName) - else: break - - - def udev_handler(self, fd, events): - self.process_udev_event() - - - def add_stream(self, devIndex, devType, devName): - try: - stream = EventStream(devIndex, devType, devName) - self.streams.append(stream) - - self.ioloop.add_handler(stream.filehandle, self.stream_handler, - self.ioloop.READ) - - log.info('Added %s[%d] %s', devType, devIndex, devName) - - except OSError as e: - log.warning('Failed to add %s[%d]: %s', devType, devIndex, e) - - - def remove_stream(self, devIndex): - for stream in self.streams: - if stream.devIndex == devIndex: - self.streams.remove(stream) - self.ioloop.remove_handler(stream.filehandle) - stream.release() - self.cb.clear() - - log.info('Removed %s[%d]', stream.devType, devIndex) - - - def key_state(self, key): - """ - Returns the state of the given key. - - The returned value will be 0 for key-up, or 1 for key-down. This method - returns a key-held(2) as 1 to aid in using the returned value as a - movement distance. - - This function accepts either the key code or the string name of the key. - It would be more efficient to look-up and store the code of - the key with KEY_CODE[], rather than using the string every time. (Which - involves a dict look-up keyed with a string for every key_state call, every - time around the loop.) - - Gamepad keys are: - Select = BTN_BASE3, Start = BTN_BASE4 - L1 = BTN_TOP R1 = BTN_BASE - L2 = BTN_PINKIE R2 = BTN_BASE2 - - The action buttons are: - BTN_THUMB - BTN_TRIGGER - BTN_TOP - BTN_THUMB2 - - Analogue Left Button = BTN_BASE5 - Analogue Right Button = BTN_BASE6 - - Some of those may clash with extended mouse buttons, so if you are using - both at once, you'll see some overlap. - - The direction pad is hat0 (see get_hat) - """ - return self.handler.key_state(key_to_code(key)) - - - def clear_key(self, key): - """ - Clears the state of the given key. - - Emulates a key-up, but does not call any handlers. - """ - return self.handler.clear_key(key_to_code(key)) - - - def get_keys(self): - return [code_to_key(k) for k in self.handler.get_keys()] - - - def release(self): - """ - Ungrabs all streams and closes all files. - - Only do this when you're finished with this object. You can't use it again. - """ - for s in self.streams: s.release() diff --git a/src/py/inevent/JogHandler.py b/src/py/inevent/JogHandler.py deleted file mode 100644 index f5fad5b..0000000 --- a/src/py/inevent/JogHandler.py +++ /dev/null @@ -1,153 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import logging - -from inevent.Constants import * - - -log = logging.getLogger('inevent') -log.setLevel(logging.INFO) - - -def axes_to_string(axes): - s = '' - for axis in axes: - if s: s += ', ' - else: s = '(' - s += '{:6.3f}'.format(axis) - return s + ')' - - -def event_to_string(event, state): - s = '{} {}: '.format(event.get_source(), event.get_type_name()) - - if event.type == EV_ABS: - s += axes_to_string(state.get_joystick3d()) + ' ' + \ - axes_to_string(state.get_joystickR3d()) + ' ' + \ - '({:2.0f}, {:2.0f}) '.format(*state.get_hat()) - - if event.type == EV_REL: - s += '({:d}, {:d}) '.format(*state.get_mouse()) + \ - '({:d}, {:d})'.format(*state.get_wheel()) - - if event.type == EV_KEY: - state = 'pressed' if event.value else 'released' - s += '0x{:x} {}'.format(event.code, state) - - return s - - -class JogHandler: - def __init__(self, config): - self.config = config - self.reset() - - - def changed(self): - log.info(axes_to_string(self.axes) + ' x {:d}'.format(self.speed)) - - - def up(self): log.debug('up') - def down(self): log.debug('down') - def left(self): log.debug('left') - def right(self): log.debug('right') - - - def reset(self): - self.axes = [0.0, 0.0, 0.0, 0.0] - self.speed = 3 - self.vertical_lock = 0 - self.horizontal_lock = 0 - - - def clear(self): - self.reset() - self.changed() - - - def get_config(self, name): - if name in self.config: return self.config[name] - return self.config['default'] - - - def event(self, event, state, dev_name): - if event.type not in [EV_ABS, EV_REL, EV_KEY]: return - - config = self.get_config(dev_name) - changed = False - - # Process event - if event.type == EV_ABS and event.code in config['axes']: - pass - - elif event.type == EV_ABS and event.code in config['arrows']: - axis = config['arrows'].index(event.code) - - if event.value < 0: - if axis == 1: self.up() - else: self.left() - - elif 0 < event.value: - if axis == 1: self.down() - else: self.right() - - elif event.type == EV_KEY and event.code in config['speed']: - old_speed = self.speed - self.speed = config['speed'].index(event.code) + 1 - if self.speed != old_speed: changed = True - - elif event.type == EV_KEY and event.code in config['lock']: - index = config['lock'].index(event.code) - - self.horizontal_lock, self.vertical_lock = False, False - - if event.value: - if index == 0: self.horizontal_lock = True - if index == 1: self.vertical_lock = True - - log.debug(event_to_string(event, state)) - - # Update axes - old_axes = list(self.axes) - - for axis in range(4): - self.axes[axis] = event.stream.state.abs[config['axes'][axis]] - self.axes[axis] *= config['dir'][axis] - - if abs(self.axes[axis]) < config['deadband']: - self.axes[axis] = 0 - - if self.horizontal_lock and axis not in [0, 3]: - self.axes[axis] = 0 - - if self.vertical_lock and axis not in [1, 2]: - self.axes[axis] = 0 - - if old_axes != self.axes: changed = True - - if changed: self.changed() diff --git a/src/py/inevent/Keys.py b/src/py/inevent/Keys.py deleted file mode 100644 index 449aa97..0000000 --- a/src/py/inevent/Keys.py +++ /dev/null @@ -1,445 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -# The inevent Python module was adapted from pi3d.event from the pi3d -# project. -# -# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC. -# Copyright (c) 2015, Tim Skillman. -# Copyright (c) 2015, Paddy Gaunt. -# Copyright (c) 2015, Tom Ritchford. -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -KEY_ESC = 1 -KEY_1 = 2 -KEY_2 = 3 -KEY_3 = 4 -KEY_4 = 5 -KEY_5 = 6 -KEY_6 = 7 -KEY_7 = 8 -KEY_8 = 9 -KEY_9 = 10 -KEY_0 = 11 -KEY_MINUS = 12 -KEY_EQUAL = 13 -KEY_BACKSPACE = 14 -KEY_TAB = 15 -KEY_Q = 16 -KEY_W = 17 -KEY_E = 18 -KEY_R = 19 -KEY_T = 20 -KEY_Y = 21 -KEY_U = 22 -KEY_I = 23 -KEY_O = 24 -KEY_P = 25 -KEY_LEFTBRACE = 26 -KEY_RIGHTBRACE = 27 -KEY_ENTER = 28 -KEY_LEFTCTRL = 29 -KEY_A = 30 -KEY_S = 31 -KEY_D = 32 -KEY_F = 33 -KEY_G = 34 -KEY_H = 35 -KEY_J = 36 -KEY_K = 37 -KEY_L = 38 -KEY_SEMICOLON = 39 -KEY_APOSTROPHE = 40 -KEY_GRAVE = 41 -KEY_LEFTSHIFT = 42 -KEY_BACKSLASH = 43 -KEY_Z = 44 -KEY_X = 45 -KEY_C = 46 -KEY_V = 47 -KEY_B = 48 -KEY_N = 49 -KEY_M = 50 -KEY_COMMA = 51 -KEY_DOT = 52 -KEY_SLASH = 53 -KEY_RIGHTSHIFT = 54 -KEY_KPASTERISK = 55 -KEY_LEFTALT = 56 -KEY_SPACE = 57 -KEY_CAPSLOCK = 58 -KEY_F1 = 59 -KEY_F2 = 60 -KEY_F3 = 61 -KEY_F4 = 62 -KEY_F5 = 63 -KEY_F6 = 64 -KEY_F7 = 65 -KEY_F8 = 66 -KEY_F9 = 67 -KEY_F10 = 68 -KEY_NUMLOCK = 69 -KEY_SCROLLLOCK = 70 -KEY_KP7 = 71 -KEY_KP8 = 72 -KEY_KP9 = 73 -KEY_KPMINUS = 74 -KEY_KP4 = 75 -KEY_KP5 = 76 -KEY_KP6 = 77 -KEY_KPPLUS = 78 -KEY_KP1 = 79 -KEY_KP2 = 80 -KEY_KP3 = 81 -KEY_KP0 = 82 -KEY_KPDOT = 83 - -KEY_ZENKAKUHANKAKU = 85 -KEY_102ND = 86 -KEY_F11 = 87 -KEY_F12 = 88 -KEY_RO = 89 -KEY_KATAKANA = 90 -KEY_HIRAGANA = 91 -KEY_HENKAN = 92 -KEY_KATAKANAHIRAGANA = 93 -KEY_MUHENKAN = 94 -KEY_KPJPCOMMA = 95 -KEY_KPENTER = 96 -KEY_RIGHTCTRL = 97 -KEY_KPSLASH = 98 -KEY_SYSRQ = 99 -KEY_RIGHTALT = 100 -KEY_LINEFEED = 101 -KEY_HOME = 102 -KEY_UP = 103 -KEY_PAGEUP = 104 -KEY_LEFT = 105 -KEY_RIGHT = 106 -KEY_END = 107 -KEY_DOWN = 108 -KEY_PAGEDOWN = 109 -KEY_INSERT = 110 -KEY_DELETE = 111 -KEY_MACRO = 112 -KEY_MUTE = 113 -KEY_VOLUMEDOWN = 114 -KEY_VOLUMEUP = 115 -KEY_POWER = 116 -KEY_KPEQUAL = 117 -KEY_KPPLUSMINUS = 118 -KEY_PAUSE = 119 - -KEY_KPCOMMA = 121 -KEY_HANGUEL = 122 -KEY_HANJA = 123 -KEY_YEN = 124 -KEY_LEFTMETA = 125 -KEY_RIGHTMETA = 126 -KEY_COMPOSE = 127 - -KEY_STOP = 128 -KEY_AGAIN = 129 -KEY_PROPS = 130 -KEY_UNDO = 131 -KEY_FRONT = 132 -KEY_COPY = 133 -KEY_OPEN = 134 -KEY_PASTE = 135 -KEY_FIND = 136 -KEY_CUT = 137 -KEY_HELP = 138 -KEY_MENU = 139 -KEY_CALC = 140 -KEY_SETUP = 141 -KEY_SLEEP = 142 -KEY_WAKEUP = 143 -KEY_FILE = 144 -KEY_SENDFILE = 145 -KEY_DELETEFILE = 146 -KEY_XFER = 147 -KEY_PROG1 = 148 -KEY_PROG2 = 149 -KEY_WWW = 150 -KEY_MSDOS = 151 -KEY_COFFEE = 152 -KEY_DIRECTION = 153 -KEY_CYCLEWINDOWS = 154 -KEY_MAIL = 155 -KEY_BOOKMARKS = 156 -KEY_COMPUTER = 157 -KEY_BACK = 158 -KEY_FORWARD = 159 -KEY_CLOSECD = 160 -KEY_EJECTCD = 161 -KEY_EJECTCLOSECD = 162 -KEY_NEXTSONG = 163 -KEY_PLAYPAUSE = 164 -KEY_PREVIOUSSONG = 165 -KEY_STOPCD = 166 -KEY_RECORD = 167 -KEY_REWIND = 168 -KEY_PHONE = 169 -KEY_ISO = 170 -KEY_CONFIG = 171 -KEY_HOMEPAGE = 172 -KEY_REFRESH = 173 -KEY_EXIT = 174 -KEY_MOVE = 175 -KEY_EDIT = 176 -KEY_SCROLLUP = 177 -KEY_SCROLLDOWN = 178 -KEY_KPLEFTPAREN = 179 -KEY_KPRIGHTPAREN = 180 - -KEY_F13 = 183 -KEY_F14 = 184 -KEY_F15 = 185 -KEY_F16 = 186 -KEY_F17 = 187 -KEY_F18 = 188 -KEY_F19 = 189 -KEY_F20 = 190 -KEY_F21 = 191 -KEY_F22 = 192 -KEY_F23 = 193 -KEY_F24 = 194 - -KEY_PLAYCD = 200 -KEY_PAUSECD = 201 -KEY_PROG3 = 202 -KEY_PROG4 = 203 -KEY_SUSPEND = 205 -KEY_CLOSE = 206 -KEY_PLAY = 207 -KEY_FASTFORWARD = 208 -KEY_BASSBOOST = 209 -KEY_PRINT = 210 -KEY_HP = 211 -KEY_CAMERA = 212 -KEY_SOUND = 213 -KEY_QUESTION = 214 -KEY_EMAIL = 215 -KEY_CHAT = 216 -KEY_SEARCH = 217 -KEY_CONNECT = 218 -KEY_FINANCE = 219 -KEY_SPORT = 220 -KEY_SHOP = 221 -KEY_ALTERASE = 222 -KEY_CANCEL = 223 -KEY_BRIGHTNESSDOWN = 224 -KEY_BRIGHTNESSUP = 225 -KEY_MEDIA = 226 - -KEY_UNKNOWN = 240 - -BTN_MISC = 0x100 -BTN_0 = 0x100 -BTN_1 = 0x101 -BTN_2 = 0x102 -BTN_3 = 0x103 -BTN_4 = 0x104 -BTN_5 = 0x105 -BTN_6 = 0x106 -BTN_7 = 0x107 -BTN_8 = 0x108 -BTN_9 = 0x109 - -BTN_MOUSE = 0x110 -BTN_LEFT = 0x110 -BTN_RIGHT = 0x111 -BTN_MIDDLE = 0x112 -BTN_SIDE = 0x113 -BTN_EXTRA = 0x114 -BTN_FORWARD = 0x115 -BTN_BACK = 0x116 -BTN_TASK = 0x117 - -BTN_JOYSTICK = 0x120 -BTN_TRIGGER = 0x120 -BTN_THUMB = 0x121 -BTN_THUMB2 = 0x122 -BTN_TOP = 0x123 -BTN_TOP2 = 0x124 -BTN_PINKIE = 0x125 -BTN_BASE = 0x126 -BTN_BASE2 = 0x127 -BTN_BASE3 = 0x128 -BTN_BASE4 = 0x129 -BTN_BASE5 = 0x12a -BTN_BASE6 = 0x12b -BTN_DEAD = 0x12f - -BTN_GAMEPAD = 0x130 -BTN_A = 0x130 -BTN_B = 0x131 -BTN_C = 0x132 -BTN_X = 0x133 -BTN_Y = 0x134 -BTN_Z = 0x135 -BTN_TL = 0x136 -BTN_TR = 0x137 -BTN_TL2 = 0x138 -BTN_TR2 = 0x139 -BTN_SELECT = 0x13a -BTN_START = 0x13b -BTN_MODE = 0x13c -BTN_THUMBL = 0x13d -BTN_THUMBR = 0x13e - -BTN_DIGI = 0x140 -BTN_TOOL_PEN = 0x140 -BTN_TOOL_RUBBER = 0x141 -BTN_TOOL_BRUSH = 0x142 -BTN_TOOL_PENCIL = 0x143 -BTN_TOOL_AIRBRUSH = 0x144 -BTN_TOOL_FINGER = 0x145 -BTN_TOOL_MOUSE = 0x146 -BTN_TOOL_LENS = 0x147 -BTN_TOUCH = 0x14a -BTN_STYLUS = 0x14b -BTN_STYLUS2 = 0x14c -BTN_TOOL_DOUBLETAP = 0x14d -BTN_TOOL_TRIPLETAP = 0x14e - -BTN_WHEEL = 0x150 -BTN_GEAR_DOWN = 0x150 -BTN_GEAR_UP = 0x151 - -KEY_OK = 0x160 -KEY_SELECT = 0x161 -KEY_GOTO = 0x162 -KEY_CLEAR = 0x163 -KEY_POWER2 = 0x164 -KEY_OPTION = 0x165 -KEY_INFO = 0x166 -KEY_TIME = 0x167 -KEY_VENDOR = 0x168 -KEY_ARCHIVE = 0x169 -KEY_PROGRAM = 0x16a -KEY_CHANNEL = 0x16b -KEY_FAVORITES = 0x16c -KEY_EPG = 0x16d -KEY_PVR = 0x16e -KEY_MHP = 0x16f -KEY_LANGUAGE = 0x170 -KEY_TITLE = 0x171 -KEY_SUBTITLE = 0x172 -KEY_ANGLE = 0x173 -KEY_ZOOM = 0x174 -KEY_MODE = 0x175 -KEY_KEYBOARD = 0x176 -KEY_SCREEN = 0x177 -KEY_PC = 0x178 -KEY_TV = 0x179 -KEY_TV2 = 0x17a -KEY_VCR = 0x17b -KEY_VCR2 = 0x17c -KEY_SAT = 0x17d -KEY_SAT2 = 0x17e -KEY_CD = 0x17f -KEY_TAPE = 0x180 -KEY_RADIO = 0x181 -KEY_TUNER = 0x182 -KEY_PLAYER = 0x183 -KEY_TEXT = 0x184 -KEY_DVD = 0x185 -KEY_AUX = 0x186 -KEY_MP3 = 0x187 -KEY_AUDIO = 0x188 -KEY_VIDEO = 0x189 -KEY_DIRECTORY = 0x18a -KEY_LIST = 0x18b -KEY_MEMO = 0x18c -KEY_CALENDAR = 0x18d -KEY_RED = 0x18e -KEY_GREEN = 0x18f -KEY_YELLOW = 0x190 -KEY_BLUE = 0x191 -KEY_CHANNELUP = 0x192 -KEY_CHANNELDOWN = 0x193 -KEY_FIRST = 0x194 -KEY_LAST = 0x195 -KEY_AB = 0x196 -KEY_NEXT = 0x197 -KEY_RESTART = 0x198 -KEY_SLOW = 0x199 -KEY_SHUFFLE = 0x19a -KEY_BREAK = 0x19b -KEY_PREVIOUS = 0x19c -KEY_DIGITS = 0x19d -KEY_TEEN = 0x19e -KEY_TWEN = 0x19f - -KEY_DEL_EOL = 0x1c0 -KEY_DEL_EOS = 0x1c1 -KEY_INS_LINE = 0x1c2 -KEY_DEL_LINE = 0x1c3 - -KEY_FN = 0x1d0 -KEY_FN_ESC = 0x1d1 -KEY_FN_F1 = 0x1d2 -KEY_FN_F2 = 0x1d3 -KEY_FN_F3 = 0x1d4 -KEY_FN_F4 = 0x1d5 -KEY_FN_F5 = 0x1d6 -KEY_FN_F6 = 0x1d7 -KEY_FN_F7 = 0x1d8 -KEY_FN_F8 = 0x1d9 -KEY_FN_F9 = 0x1da -KEY_FN_F10 = 0x1db -KEY_FN_F11 = 0x1dc -KEY_FN_F12 = 0x1dd -KEY_FN_1 = 0x1de -KEY_FN_2 = 0x1df -KEY_FN_D = 0x1e0 -KEY_FN_E = 0x1e1 -KEY_FN_F = 0x1e2 -KEY_FN_S = 0x1e3 -KEY_FN_B = 0x1e4 - -KEY_MAX = 0x1ff diff --git a/src/py/inevent/__init__.py b/src/py/inevent/__init__.py deleted file mode 100644 index 5e6780d..0000000 --- a/src/py/inevent/__init__.py +++ /dev/null @@ -1,57 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -# The inevent Python module was adapted from pi3d.event from the pi3d -# project. -# -# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC. -# Copyright (c) 2015, Tim Skillman. -# Copyright (c) 2015, Paddy Gaunt. -# Copyright (c) 2015, Tom Ritchford. -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -from .InEvent import InEvent -from .JogHandler import JogHandler diff --git a/src/py/inevent/ioctl.py b/src/py/inevent/ioctl.py deleted file mode 100644 index 652ef68..0000000 --- a/src/py/inevent/ioctl.py +++ /dev/null @@ -1,128 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -# The inevent Python module was adapted from pi3d.event from the pi3d -# project. -# -# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC. -# Copyright (c) 2015, Tim Skillman. -# Copyright (c) 2015, Paddy Gaunt. -# Copyright (c) 2015, Tom Ritchford. -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# IOCTL macros -# -# ioctl command encoding: 32 bits total, command in lower 16 bits, -# size of the parameter structure in the lower 14 bits of the -# upper 16 bits. -# -# Encoding the size of the parameter structure in the ioctl request -# is useful for catching programs compiled with old versions -# and to avoid overwriting user space outside the user buffer area. -# The highest 2 bits are reserved for indicating the ``access mode''. -# NOTE: This limits the max parameter size to 16kB - 1 -# -# The following is for compatibility across the various Linux -# platforms. The generic ioctl numbering scheme doesn't really enforce -# a type field. De facto, however, the top 8 bits of the lower 16 -# bits are indeed used as a type field, so we might just as well make -# this explicit here. - -import struct - - -sizeof = struct.calcsize - -_IOC_NRBITS = 8 -_IOC_TYPEBITS = 8 -_IOC_SIZEBITS = 14 -_IOC_DIRBITS = 2 - -_IOC_NRMASK = (1 << _IOC_NRBITS) - 1 -_IOC_TYPEMASK = (1 << _IOC_TYPEBITS) - 1 -_IOC_SIZEMASK = (1 << _IOC_SIZEBITS) - 1 -_IOC_DIRMASK = (1 << _IOC_DIRBITS) - 1 - -_IOC_NRSHIFT = 0 -_IOC_TYPESHIFT = _IOC_NRSHIFT + _IOC_NRBITS -_IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS -_IOC_DIRSHIFT = _IOC_SIZESHIFT + _IOC_SIZEBITS - -_IOC_NONE = 0 -_IOC_WRITE = 1 -_IOC_READ = 2 -_IOC_RW = _IOC_READ | _IOC_WRITE - - -def _IOC(dir, type, nr, size): - return int( - (dir << _IOC_DIRSHIFT) | - (type << _IOC_TYPESHIFT) | - (nr << _IOC_NRSHIFT) | - (size << _IOC_SIZESHIFT)) - -# encode ioctl numbers -def _IO(type, nr): return _IOC(_IOC_NONE, type, nr, 0) -def _IOR(type, nr, fmt): return _IOC(_IOC_READ, type, nr, sizeof(fmt)) -def _IOW(type, nr, fmt): return _IOC(_IOC_WRITE, type, nr, sizeof(fmt)) -def _IOWR(type, nr, fmt): return _IOC(_IOC_RW, type, nr, sizeof(fmt)) -def _IOR_BAD(type, nr, fmt): return _IOC(_IOC_READ, type, nr, sizeof(fmt)) -def _IOW_BAD(type, nr, fmt): return _IOC(_IOC_WRITE, type, nr, sizeof(fmt)) -def _IOWR_BAD(type, nr, fmt): return _IOC(_IOC_RW, type, nr, sizeof(fmt)) - -# decode ioctl numbers -def _IOC_DIR(nr): return (nr >> _IOC_DIRSHIFT) & _IOC_DIRMASK -def _IOC_TYPE(nr): return (nr >> _IOC_TYPESHIFT) & _IOC_TYPEMASK -def _IOC_NR(nr): return (nr >> _IOC_NRSHIFT) & _IOC_NRMASK -def _IOC_SIZE(nr): return (nr >> _IOC_SIZESHIFT) & _IOC_SIZEMASK - -# for drivers/sound files -IOC_IN = _IOC_WRITE << _IOC_DIRSHIFT -IOC_OUT = _IOC_READ << _IOC_DIRSHIFT -IOC_INOUT = _IOC_RW << _IOC_DIRSHIFT -IOCSIZE_MASK = _IOC_SIZEMASK << _IOC_SIZESHIFT -IOCSIZE_SHIFT = _IOC_SIZESHIFT - diff --git a/src/py/lcd/__init__.py b/src/py/lcd/__init__.py deleted file mode 100644 index 238a6e1..0000000 --- a/src/py/lcd/__init__.py +++ /dev/null @@ -1,236 +0,0 @@ -#!/usr/bin/env python3 - -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import time -import logging - - -log = logging.getLogger('LCD') - - -# Control flags -REG_SELECT_BIT = 1 << 0 -READ_BIT = 1 << 1 -ENABLE_BIT = 1 << 2 -BACKLIGHT_BIT = 1 << 3 - -# Commands -LCD_CLEAR_DISPLAY = 1 << 0 -LCD_RETURN_HOME = 1 << 1 -LCD_ENTRY_MODE_SET = 1 << 2 -LCD_DISPLAY_CONTROL = 1 << 3 -LCD_CURSOR_SHIFT = 1 << 4 -LCD_FUNCTION_SET = 1 << 5 -LCD_SET_CGRAM_ADDR = 1 << 6 -LCD_SET_DDRAM_ADDR = 1 << 7 - -# Entry Mode Set flags -LCD_ENTRY_SHIFT_DISPLAY = 1 << 0 -LCD_ENTRY_SHIFT_INC = 1 << 1 -LCD_ENTRY_SHIFT_DEC = 0 << 1 - -# Display Control flags -LCD_BLINK_ON = 1 << 0 -LCD_BLINK_OFF = 0 << 0 -LCD_CURSOR_ON = 1 << 1 -LCD_CURSOR_OFF = 0 << 1 -LCD_DISPLAY_ON = 1 << 2 -LCD_DISPLAY_OFF = 0 << 2 - -# Cursor Shift flags -LCD_SHIFT_RIGHT = 1 << 2 -LCD_SHIFT_LEFT = 0 << 2 -LCD_SHIFT_DISPLAY = 1 << 3 -LCD_SHIFT_CURSOR = 0 << 3 - -# Function Set flags -LCD_5x11_DOTS = 1 << 2 -LCD_5x8_DOTS = 0 << 2 -LCD_2_LINE = 1 << 3 -LCD_1_LINE = 0 << 3 -LCD_8_BIT_MODE = 1 << 4 -LCD_4_BIT_MODE = 0 << 4 - -# Text justification flags -JUSTIFY_LEFT = 0 -JUSTIFY_RIGHT = 1 -JUSTIFY_CENTER = 2 - - - -class LCD: - def __init__(self, i2c, addr, height = 4, width = 20): - self.addr = addr - self.height = height - self.width = width - self.i2c = i2c - self.backlight = True - - self.reset() - - - def reset(self): - self.clear() - time.sleep(0.050) - self.write_nibble(3 << 4) # Home - time.sleep(0.050) - self.write_nibble(3 << 4) # Home - time.sleep(0.050) - self.write_nibble(3 << 4) # Home - self.write_nibble(2 << 4) # 4-bit - - self.write(LCD_FUNCTION_SET | LCD_2_LINE | LCD_5x8_DOTS | - LCD_4_BIT_MODE) - self.write(LCD_DISPLAY_CONTROL | LCD_DISPLAY_ON) - self.write(LCD_ENTRY_MODE_SET | LCD_ENTRY_SHIFT_INC) - - - def write_i2c(self, data): - if self.backlight: data |= BACKLIGHT_BIT - - self.i2c.write(self.addr, data) - time.sleep(0.0001) - - - # Write half of a command to LCD - def write_nibble(self, data): - self.write_i2c(data) - - # Strobe - self.write_i2c(data | ENABLE_BIT) - time.sleep(0.0005) - - self.write_i2c(data & ~ENABLE_BIT) - time.sleep(0.0001) - - - # Write an 8-bit command to LCD - def write(self, cmd, flags = 0): - self.write_nibble(flags | (cmd & 0xf0)) - self.write_nibble(flags | ((cmd << 4) & 0xf0)) - - - def set_cursor(self, on, blink): - data = LCD_DISPLAY_CONTROL - - if on: data |= LCD_CURSOR_ON - if blink: data |= LCD_BLINK_ON - - self.write(data) - - - def set_backlight(self, enable): - self.backlight = enable - self.write_i2c(0) - - - def program_char(self, addr, data): - if addr < 0 or 8 <= addr: return - - self.write(LCD_SET_CGRAM_ADDR | (addr << 3)) - for x in data: - self.write(x, REG_SELECT_BIT) - - - def goto(self, x, y): - if x < 0 or self.width <= x or y < 0 or self.height <= y: return - self.write(LCD_SET_DDRAM_ADDR | (0, 64, 20, 84)[y] + int(x)) - - - def put_char(self, c): - self.write(ord(c), REG_SELECT_BIT) - - - def text(self, msg, x = None, y = None): - if x is not None and y is not None: self.goto(x, y) - - for c in msg: self.put_char(c) - - - def display(self, line, msg, justify = JUSTIFY_LEFT): - if justify == JUSTIFY_RIGHT: x = self.width - len(msg) - elif justify == JUSTIFY_CENTER: x = (self.width - len(msg)) / 2 - else: x = 0 - - if x < 0: x = 0 - - self.text(msg, x, line) - - - def shift(self, count = 1, right = True, display = True): - cmd = LCD_CURSOR_SHIFT - if right: cmd |= LCD_SHIFT_RIGHT - if display: cmd |= LCD_SHIFT_DISPLAY - - for i in range(count): self.write(cmd) - - - # Clear LCD and move cursor home - def clear(self): - self.write(LCD_CLEAR_DISPLAY) - self.write(LCD_RETURN_HOME) - - - -if __name__ == "__main__": - lcd = LCD(1, 0x27) - - lcd.clear() - - lcd.program_char(0, (0b11011, - 0b11011, - 0b00000, - 0b01100, - 0b01100, - 0b00000, - 0b11011, - 0b11011)) - - lcd.program_char(1, (0b11000, - 0b01100, - 0b00110, - 0b00011, - 0b00011, - 0b00110, - 0b01100, - 0b11000)) - - lcd.program_char(2, (0b00011, - 0b00110, - 0b01100, - 0b11000, - 0b11000, - 0b01100, - 0b00110, - 0b00011)) - - lcd.display(0, '\0' * lcd.width) - lcd.display(1, 'Hello world!', JUSTIFY_CENTER) - lcd.display(2, '\1\2' * (lcd.width / 2)) - lcd.display(3, '12345678901234567890') diff --git a/src/py/lcd/splash.py b/src/py/lcd/splash.py deleted file mode 100644 index 203f60a..0000000 --- a/src/py/lcd/splash.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python3 - -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import lcd - -if __name__ == "__main__": - screen = lcd.LCD(1, 0x27) - - screen.clear() - screen.display(0, 'Buildbotics', lcd.JUSTIFY_CENTER) - screen.display(1, 'Controller', lcd.JUSTIFY_CENTER) - screen.display(3, 'Booting...', lcd.JUSTIFY_CENTER) diff --git a/src/resources/buildbotics.nc b/src/resources/buildbotics.nc deleted file mode 100644 index 8c5ddb0..0000000 --- a/src/resources/buildbotics.nc +++ /dev/null @@ -1,403 +0,0 @@ -G21 -(File: 'buildbotics_logo.tpl') -G0 Z3 -F1600 -M3 S10000 -M6 T2 -G0 X59.25 Y5.85 -G1 Z-1.5 -G1 X61.68 Y6.7 -G1 X63.86 Y8.07 -G1 X65.68 Y9.89 -G1 X67.05 Y12.07 -G1 X67.9 Y14.5 -G1 X68.2 Y17.09 -G1 Y56.6 -G1 X67.73 Y59.04 -G1 X50.8 -G1 Y34.9 -G1 X50.65 Y34.55 -G1 X50.3 Y34.4 -G1 X23.46 -G1 X23.1 Y34.55 -G1 X22.96 Y34.9 -G1 X22.98 Y49.88 -G1 X22.96 Y59.05 -G1 X22.41 -G1 X19.26 -G1 X6.04 -G1 X5.56 Y56.53 -G1 Y17.09 -G1 X5.85 Y14.5 -G1 X6.7 Y12.07 -G1 X8.07 Y9.89 -G1 X9.89 Y8.07 -G1 X12.07 Y6.7 -G1 X14.5 Y5.85 -G1 X17.09 Y5.56 -G1 X56.67 -G1 X59.25 Y5.85 -G0 Z3 -G0 X64.26 Y64.72 -G1 Z-1.5 -G1 X61.78 Y66.52 -G1 X58.91 Y67.68 -G1 X56.54 Y68.08 -G1 X17.22 -G1 X14.84 Y67.68 -G1 X11.97 Y66.52 -G1 X9.49 Y64.72 -G1 X8.08 Y63.16 -G1 X27.35 -G1 X27.89 Y63.45 -G1 X27.96 Y63.48 -G1 X31.48 Y64.75 -G1 X31.52 Y64.76 -G1 X31.56 Y64.77 -G1 X35.19 Y65.41 -G1 X35.26 -G1 X35.97 Y65.44 -G1 X36.04 Y65.45 -G1 X36.07 -G1 X36.82 Y65.44 -G1 X36.83 -G1 X36.89 -G1 X36.95 -G1 X36.97 -G1 X37.72 Y65.43 -G1 X37.74 -G1 X37.8 -G1 X37.81 -G1 X37.88 -G1 X37.89 -G1 X38.65 Y65.38 -G1 X38.68 -G1 X38.75 Y65.37 -G1 X39.38 Y65.32 -G1 X39.44 Y65.31 -G1 X42.68 Y64.64 -G1 X42.76 Y64.62 -G1 X45.87 Y63.44 -G1 X45.93 Y63.41 -G1 X46.4 Y63.16 -G1 X65.67 -G1 X64.26 Y64.72 -G0 Z3 -G0 X36.88 Y9.4 -G1 Z-1.5 -G1 X37.31 Y9.64 -G1 X39.58 Y13.48 -G1 X39.63 Y13.6 -G1 X39.65 Y13.73 -G1 Y27.54 -G1 X41.67 -G1 Y25.39 -G1 X41.75 Y25.12 -G1 X41.97 Y24.93 -G1 X46.41 Y22.92 -G1 Y19.97 -G1 X45.44 -G1 X45.08 Y19.82 -G1 X44.94 Y19.47 -G1 Y13.73 -G1 X45.08 Y13.38 -G1 X45.44 Y13.23 -G1 X49.94 Y13.24 -G1 X50.29 Y13.39 -G1 X50.44 Y13.74 -G1 Y19.47 -G1 X50.29 Y19.83 -G1 X49.93 Y19.97 -G1 X48.92 -G1 Y23.61 -G1 X48.84 Y23.88 -G1 X48.63 Y24.06 -G1 X44.19 Y26.12 -G1 Y27.54 -G1 X49.22 -G1 X49.33 Y27.56 -G1 X49.44 Y27.6 -G1 X50.13 Y27.94 -G1 X50.25 Y28.02 -G1 X50.34 Y28.13 -G1 X50.73 Y28.77 -G1 X50.78 Y28.89 -G1 X50.8 Y29.03 -G1 Y33.05 -G1 Y34.25 -G1 Y34.65 -G1 X50.66 Y35.01 -G1 X50.3 Y35.15 -G1 X23.46 -G1 X23.1 Y35.01 -G1 X22.96 Y34.65 -G1 Y29.07 -G1 X22.97 Y28.94 -G1 X23.02 Y28.82 -G1 X23.4 Y28.17 -G1 X23.49 Y28.06 -G1 X23.6 Y27.98 -G1 X24.29 Y27.6 -G1 X24.4 Y27.56 -G1 X24.52 Y27.54 -G1 X25.55 -G1 Y26.4 -G1 X23.4 Y25.52 -G1 X23.17 Y25.33 -G1 X23.09 Y25.06 -G1 Y17.54 -G1 X23.23 Y17.19 -G1 X23.59 Y17.04 -G1 X24.6 -G1 Y10.36 -G1 X24.62 Y10.23 -G1 X24.66 Y10.11 -G1 X24.8 Y9.88 -G1 X24.88 Y9.77 -G1 X24.99 Y9.68 -G1 X25.25 Y9.54 -G1 X25.37 Y9.5 -G1 X25.49 Y9.48 -G1 X26.53 -G1 X26.65 Y9.49 -G1 X26.76 Y9.54 -G1 X27.01 Y9.66 -G1 X27.12 Y9.74 -G1 X27.21 Y9.85 -G1 X27.35 Y10.09 -G1 X27.41 Y10.22 -G1 X27.43 Y10.35 -G1 Y10.43 -G1 X27.47 Y17.04 -G1 X28.57 -G1 X28.92 Y17.19 -G1 X29.07 Y17.54 -G1 Y24.64 -G1 X30.72 Y25.3 -G1 X30.95 Y25.49 -G1 X31.03 Y25.77 -G1 X31.02 Y27.54 -G1 X34.03 -G1 Y13.73 -G1 X34.05 Y13.59 -G1 X34.1 Y13.47 -G1 X36.45 Y9.64 -G1 X36.88 Y9.4 -G0 Z3 -G0 X49.94 Y10.82 -G1 Z-1.5 -G1 X50.29 Y10.97 -G1 X50.44 Y11.32 -G1 Y13.34 -G1 X50.29 Y13.69 -G1 X49.94 Y13.84 -G1 X45.44 -G1 X45.08 Y13.69 -G1 X44.94 Y13.34 -G1 Y11.32 -G1 X45.08 Y10.97 -G1 X45.44 Y10.82 -G1 X49.94 -G0 Z3 -G0 X48.46 Y9.7 -G1 Z-1.5 -G1 X48.59 Y9.72 -G1 X48.71 Y9.77 -G1 X50.03 Y10.53 -G1 X50.21 Y10.71 -G1 X50.28 Y10.96 -G1 X50.14 Y11.31 -G1 X49.78 Y11.46 -G1 X45.62 -G1 X45.14 Y11.09 -G1 X45.37 Y10.53 -G1 X46.69 Y9.77 -G1 X46.81 Y9.72 -G1 X46.94 Y9.7 -G1 X48.46 -G0 Z3 -G0 X50.3 Y34.4 -G1 Z-1.5 -G1 X50.66 Y34.55 -G1 X50.8 Y34.9 -G1 Y49.88 -G1 X50.79 Y59.52 -G1 X50.76 Y59.69 -G1 X50.67 Y59.84 -G1 X50.09 Y60.52 -G1 X50.06 Y60.55 -G1 X50.02 Y60.58 -G1 X47.89 Y62.26 -G1 X47.85 Y62.28 -G1 X47.81 Y62.31 -G1 X44.46 Y64.03 -G1 X44.41 Y64.05 -G1 X44.37 Y64.06 -G1 X40.69 Y65.1 -G1 X40.62 Y65.12 -G1 X37.86 Y65.45 -G1 X37.8 Y65.46 -G1 X36.89 Y65.44 -G1 X36.83 -G1 X36.82 -G1 X36.07 Y65.45 -G1 X36.04 Y65.44 -G1 X35.97 -G1 X35.1 Y65.41 -G1 X35.04 Y65.4 -G1 X32.44 Y64.99 -G1 X32.37 Y64.97 -G1 X28.94 Y63.9 -G1 X28.89 Y63.88 -G1 X28.85 Y63.86 -G1 X25.74 Y62.2 -G1 X25.7 Y62.18 -G1 X25.66 Y62.15 -G1 X23.68 Y60.56 -G1 X23.65 Y60.53 -G1 X23.62 Y60.5 -G1 X23.08 Y59.87 -G1 X22.99 Y59.71 -G1 X22.96 Y59.54 -G1 X22.98 Y49.88 -G1 X22.96 Y34.9 -G1 X23.1 Y34.55 -G1 X23.46 Y34.4 -G1 X50.3 -G0 Z3 -G0 X55.2 Y43.67 -G1 Z-1.5 -G1 Y51.34 -G1 X55.11 Y51.94 -G1 X54.83 Y52.88 -G1 X54.39 Y53.88 -G1 X53.8 Y54.85 -G1 X53.09 Y55.74 -G1 X52.28 Y56.47 -G1 X51.41 Y56.98 -G1 X51.07 Y57.09 -G1 Y43.67 -G1 X55.2 -G0 Z3 -G0 X22.69 Y43.63 -G1 Z-1.5 -G1 Y57.09 -G1 X22.35 Y56.98 -G1 X21.47 Y56.47 -G1 X20.67 Y55.74 -G1 X19.95 Y54.85 -G1 X19.36 Y53.88 -G1 X18.92 Y52.88 -G1 X18.64 Y51.94 -G1 X18.55 Y51.34 -G1 Y43.63 -G1 X22.69 -G0 Z3 -G0 X28.55 Y35.84 -G1 Z-0.99 -G1 X30.11 Y36.15 -G1 X31.43 Y37.03 -G1 X32.32 Y38.35 -G1 X32.63 Y39.91 -G1 X32.32 Y41.47 -G1 X31.43 Y42.79 -G1 X30.11 Y43.68 -G1 X28.55 Y43.99 -G1 X26.99 Y43.68 -G1 X25.67 Y42.79 -G1 X24.79 Y41.47 -G1 X24.48 Y39.91 -G1 X24.79 Y38.35 -G1 X25.67 Y37.03 -G1 X26.99 Y36.15 -G1 X28.55 Y35.84 -G0 Z3 -G0 X45.33 Y35.93 -G1 Z-0.99 -G1 X46.88 Y36.24 -G1 X48.21 Y37.12 -G1 X49.09 Y38.45 -G1 X49.4 Y40 -G1 X49.09 Y41.56 -G1 X48.21 Y42.88 -G1 X46.88 Y43.77 -G1 X45.33 Y44.08 -G1 X43.77 Y43.77 -G1 X42.45 Y42.88 -G1 X41.56 Y41.56 -G1 X41.25 Y40 -G1 X41.56 Y38.45 -G1 X42.45 Y37.12 -G1 X43.77 Y36.24 -G1 X45.33 Y35.93 -G0 Z3 -G0 X45.2 Y39.12 -G1 Z-0.99 -G1 X45.7 Y39.19 -G1 X46.07 Y39.52 -G1 X46.22 Y40 -G1 X46.07 Y40.49 -G1 X45.7 Y40.81 -G1 X45.2 Y40.89 -G1 X44.74 Y40.68 -G1 X44.47 Y40.26 -G1 Y39.75 -G1 X44.74 Y39.33 -G1 X45.2 Y39.12 -G0 Z3 -G0 X28.43 Y39.03 -G1 Z-0.99 -G1 X28.92 Y39.1 -G1 X29.3 Y39.43 -G1 X29.44 Y39.91 -G1 X29.3 Y40.4 -G1 X28.92 Y40.72 -G1 X28.43 Y40.8 -G1 X27.97 Y40.59 -G1 X27.7 Y40.16 -G1 Y39.66 -G1 X27.97 Y39.24 -G1 X28.43 Y39.03 -G0 Z3 -G0 X55.76 Y0 -G1 Z-1.5 -G1 X59.27 Y0.35 -G1 X62.65 Y1.37 -G1 X65.76 Y3.03 -G1 X68.49 Y5.27 -G1 X70.73 Y8 -G1 X72.39 Y11.11 -G1 X73.42 Y14.49 -G1 X73.76 Y18 -G1 Y55.69 -G1 X73.42 Y59.2 -G1 X72.39 Y62.57 -G1 X70.73 Y65.69 -G1 X68.49 Y68.41 -G1 X65.76 Y70.65 -G1 X62.65 Y72.31 -G1 X59.27 Y73.34 -G1 X55.76 Y73.69 -G1 X18 -G1 X14.49 Y73.34 -G1 X11.11 Y72.31 -G1 X8 Y70.65 -G1 X5.27 Y68.41 -G1 X3.03 Y65.69 -G1 X1.37 Y62.57 -G1 X0.35 Y59.2 -G1 X0 Y55.69 -G1 Y18 -G1 X0.35 Y14.49 -G1 X1.37 Y11.11 -G1 X3.03 Y8 -G1 X5.27 Y5.27 -G1 X8 Y3.03 -G1 X11.11 Y1.37 -G1 X14.49 Y0.35 -G1 X18 Y0 -G1 X55.76 -G0 Z3 -M5 -G0 X40 Y75 -M2 diff --git a/src/resources/config-template.json b/src/resources/config-template.json index a39ddfd..fad50fb 100644 --- a/src/resources/config-template.json +++ b/src/resources/config-template.json @@ -22,11 +22,6 @@ "max": 100000000, "unit": "mm/min²", "default": 200000 - }, - "probing-prompts": { - "help": "Enable or disable safety prompts during and after probing", - "type": "bool", - "default": true } }, @@ -507,14 +502,14 @@ }, "probe-fast-seek": { "type": "float", - "unit": "mm/m", + "unit": "mm/min", "min": 0, "max": 1000, "default": 200 }, "probe-slow-seek": { "type": "float", - "unit": "mm/m", + "unit": "mm/min", "min": 0, "max": 1000, "default": 25 diff --git a/src/resources/fonts/material-symbols-outlined.woff2 b/src/resources/fonts/material-symbols-outlined.woff2 deleted file mode 100644 index a162be0..0000000 Binary files a/src/resources/fonts/material-symbols-outlined.woff2 and /dev/null differ diff --git a/src/splash/buildbotics.plymouth b/src/splash/buildbotics.plymouth deleted file mode 100644 index 5ce2ae8..0000000 --- a/src/splash/buildbotics.plymouth +++ /dev/null @@ -1,8 +0,0 @@ -[Plymouth Theme] -Name=buildbotics -Description=Buildbotics boot splash -ModuleName=script - -[script] -ImageDir=/usr/share/plymouth/themes/buildbotics -ScriptFile=/usr/share/plymouth/themes/buildbotics/buildbotics.script diff --git a/src/splash/splash.png b/src/splash/splash.png deleted file mode 100644 index 274371e..0000000 Binary files a/src/splash/splash.png and /dev/null differ diff --git a/src/static/js/three.min.js b/src/static/js/three.min.js index 75e5c31..a0a33c8 100644 --- a/src/static/js/three.min.js +++ b/src/static/js/three.min.js @@ -172,7 +172,7 @@ c.isSpriteMaterial?(t.diffuse.value=c.color,t.opacity.value=c.opacity,t.rotation b.envMap,a.flipEnvMap.value=b.envMap&&b.envMap.isCubeTexture?-1:1,a.reflectivity.value=b.reflectivity,a.refractionRatio.value=b.refractionRatio,a.maxMipLevel.value=Ca.get(b.envMap).__maxMipLevel);b.lightMap&&(a.lightMap.value=b.lightMap,a.lightMapIntensity.value=b.lightMapIntensity);b.aoMap&&(a.aoMap.value=b.aoMap,a.aoMapIntensity.value=b.aoMapIntensity);if(b.map)var c=b.map;else b.specularMap?c=b.specularMap:b.displacementMap?c=b.displacementMap:b.normalMap?c=b.normalMap:b.bumpMap?c=b.bumpMap:b.roughnessMap? c=b.roughnessMap:b.metalnessMap?c=b.metalnessMap:b.alphaMap?c=b.alphaMap:b.emissiveMap&&(c=b.emissiveMap);void 0!==c&&(c.isWebGLRenderTarget&&(c=c.texture),!0===c.matrixAutoUpdate&&c.updateMatrix(),a.uvTransform.value.copy(c.matrix))}function r(a,b){a.specular.value=b.specular;a.shininess.value=Math.max(b.shininess,1E-4);b.emissiveMap&&(a.emissiveMap.value=b.emissiveMap);b.bumpMap&&(a.bumpMap.value=b.bumpMap,a.bumpScale.value=b.bumpScale,1===b.side&&(a.bumpScale.value*=-1));b.normalMap&&(a.normalMap.value= b.normalMap,a.normalScale.value.copy(b.normalScale),1===b.side&&a.normalScale.value.negate());b.displacementMap&&(a.displacementMap.value=b.displacementMap,a.displacementScale.value=b.displacementScale,a.displacementBias.value=b.displacementBias)}function v(a,b){a.roughness.value=b.roughness;a.metalness.value=b.metalness;b.roughnessMap&&(a.roughnessMap.value=b.roughnessMap);b.metalnessMap&&(a.metalnessMap.value=b.metalnessMap);b.emissiveMap&&(a.emissiveMap.value=b.emissiveMap);b.bumpMap&&(a.bumpMap.value= -b.bumpMap,a.bumpScale.value=b.bumpScale,1===b.side&&(a.bumpScale.value*=-1));b.normalMap&&(a.normalMap.value=b.normalMap,a.normalScale.value.copy(b.normalScale),1===b.side&&a.normalScale.value.negate());b.displacementMap&&(a.displacementMap.value=b.displacementMap,a.displacementScale.value=b.displacementScale,a.displacementBias.value=b.displacementBias);b.envMap&&(a.envMapIntensity.value=b.envMapIntensity)}console.log("THREE.WebGLRenderer","96");a=a||{};var y=void 0!==a.canvas?a.canvas:document.createElementNS("http://www.w3.org/1999/xhtml", +b.bumpMap,a.bumpScale.value=b.bumpScale,1===b.side&&(a.bumpScale.value*=-1));b.normalMap&&(a.normalMap.value=b.normalMap,a.normalScale.value.copy(b.normalScale),1===b.side&&a.normalScale.value.negate());b.displacementMap&&(a.displacementMap.value=b.displacementMap,a.displacementScale.value=b.displacementScale,a.displacementBias.value=b.displacementBias);b.envMap&&(a.envMapIntensity.value=b.envMapIntensity)}a=a||{};var y=void 0!==a.canvas?a.canvas:document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"),x=void 0!==a.context?a.context:null,w=void 0!==a.alpha?a.alpha:!1,G=void 0!==a.depth?a.depth:!0,D=void 0!==a.stencil?a.stencil:!0,O=void 0!==a.antialias?a.antialias:!1,S=void 0!==a.premultipliedAlpha?a.premultipliedAlpha:!0,E=void 0!==a.preserveDrawingBuffer?a.preserveDrawingBuffer:!1,z=void 0!==a.powerPreference?a.powerPreference:"default",A=null,B=null;this.domElement=y;this.context=null;this.sortObjects=this.autoClearStencil=this.autoClearDepth=this.autoClearColor=this.autoClear=!0;this.clippingPlanes= [];this.localClippingEnabled=!1;this.gammaFactor=2;this.physicallyCorrectLights=this.gammaOutput=this.gammaInput=!1;this.toneMappingWhitePoint=this.toneMappingExposure=this.toneMapping=1;this.maxMorphTargets=8;this.maxMorphNormals=4;var P=this,I=!1,F=null,L=null,M=null,Q=-1;var H=b=null;var U=!1;var V=null,Z=null,T=new aa,zc=new aa,Y=null,fa=0,X=y.width,N=y.height,W=1,cb=new aa(0,0,X,N),ha=new aa(0,0,X,N),ra=!1,pa=new od,ba=new Nf,qd=!1,Xd=!1,yc=new J,db=new p;try{w={alpha:w,depth:G,stencil:D,antialias:O, premultipliedAlpha:S,preserveDrawingBuffer:E,powerPreference:z};y.addEventListener("webglcontextlost",d,!1);y.addEventListener("webglcontextrestored",e,!1);var C=x||y.getContext("webgl",w)||y.getContext("experimental-webgl",w);if(null===C){if(null!==y.getContext("webgl"))throw Error("Error creating WebGL context with your selected attributes.");throw Error("Error creating WebGL context.");}void 0===C.getShaderPrecisionFormat&&(C.getShaderPrecisionFormat=function(){return{rangeMin:1,rangeMax:1,precision:1}})}catch(Lg){console.error("THREE.WebGLRenderer: "+ diff --git a/src/static/js/vue.js b/src/static/js/vue.js index c8d69ec..a357bde 100644 --- a/src/static/js/vue.js +++ b/src/static/js/vue.js @@ -394,7 +394,7 @@ var inBrowser = typeof window !== 'undefined' && Object.prototype.toString.call(window) !== '[object Object]'; // detect devtools - var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; + var devtools = false; // UA sniffing for working around browser-specific quirks var UA = inBrowser && window.navigator.userAgent.toLowerCase(); @@ -9677,14 +9677,5 @@ var template = Object.freeze({ Vue.version = '1.0.17'; - // devtools global hook - /* istanbul ignore next */ - if (devtools) { - devtools.emit('init', Vue); - } else if ('development' !== 'production' && inBrowser && /Chrome\/\d+/.test(window.navigator.userAgent)) { - console.log('Download the Vue Devtools for a better development experience:\n' + 'https://github.com/vuejs/vue-devtools'); - } - return Vue; - })); \ No newline at end of file diff --git a/src/stylus/style.styl b/src/stylus/style.styl index 09a21e0..caed3a5 100644 --- a/src/stylus/style.styl +++ b/src/stylus/style.styl @@ -4,6 +4,9 @@ body [v-cloak] display none +.menu-link + z-index unset + tt color #000 background #eee @@ -29,6 +32,10 @@ tt clear right .header + height 140px + padding 0 + +.nav-header padding-left 60px display flex @@ -282,6 +289,12 @@ span.unit // The jogging buttons, etc. .control-buttons button font-size 150% + width 100px + height 100px + + .jog-units + font-size initial + margin-left 5px &:first-child margin 0.5em 0 @@ -350,6 +363,7 @@ span.unit .axis .name text-transform capitalize + vertical-align middle .name, .position font-size 24pt @@ -436,7 +450,7 @@ span.unit min-width 8em width 100% - .mach_units + .units padding 0 select diff --git a/src/svelte-components/package-lock.json b/src/svelte-components/package-lock.json index 9b7bc07..ef58833 100644 --- a/src/svelte-components/package-lock.json +++ b/src/svelte-components/package-lock.json @@ -8,19 +8,22 @@ "name": "svelte-components", "version": "0.0.0", "devDependencies": { - "@sveltejs/kit": "^1.0.0-next.357", - "@sveltejs/vite-plugin-svelte": "^1.0.0-next.49", + "@sveltejs/kit": "^1.0.0-next.392", + "@sveltejs/vite-plugin-svelte": "^1.0.1", "@tsconfig/svelte": "^3.0.0", "node-sass": "^7.0.1", "polyfill-object.fromentries": "^1.0.1", "smui-theme": "^6.0.0-beta.16", - "svelte": "^3.48.0", + "string.prototype.matchall": "^4.0.7", + "svelte": "^3.49.0", "svelte-check": "^2.8.0", + "svelte-icon": "^1.2.4", "svelte-material-ui": "^6.0.0-beta.16", "svelte-preprocess": "^4.10.7", + "svelte-tiny-virtual-list": "^2.0.5", "tslib": "^2.4.0", "typescript": "^4.7.4", - "vite": "^2.9.13" + "vite": "^3.0.2" } }, "node_modules/@babel/code-frame": { @@ -127,9 +130,9 @@ "dev": true }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz", - "integrity": "sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, "engines": { "node": ">=6.0.0" @@ -1514,46 +1517,46 @@ } }, "node_modules/@sveltejs/kit": { - "version": "1.0.0-next.357", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.357.tgz", - "integrity": "sha512-nCAehVybIEpQNnPu61V/EFVdfDb1nBSiQUfW9EcSSDEUbyAMCVBOKZZuzQ0qQDp3xniqRkyDzpBA4wN+ADxHBw==", + "version": "1.0.0-next.392", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.392.tgz", + "integrity": "sha512-od4rDJ/Soq0I7mda7sTbAnNKERHSDEGNa7QBpLA859xgBkwC1JnEIymYOh9dm+hMyHhB0bUoRoaur0qxKLqOOw==", "dev": true, "dependencies": { - "@sveltejs/vite-plugin-svelte": "^1.0.0-next.48", + "@sveltejs/vite-plugin-svelte": "^1.0.1", "chokidar": "^3.5.3", - "sade": "^1.8.1", - "vite": "^2.9.10" + "sade": "^1.8.1" }, "bin": { "svelte-kit": "svelte-kit.js" }, "engines": { - "node": ">=16.7" + "node": ">=16.9" }, "peerDependencies": { - "svelte": "^3.44.0" + "svelte": "^3.44.0", + "vite": "^3.0.0" } }, "node_modules/@sveltejs/vite-plugin-svelte": { - "version": "1.0.0-next.49", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.0-next.49.tgz", - "integrity": "sha512-AKh0Ka8EDgidnxWUs8Hh2iZLZovkETkefO99XxZ4sW4WGJ7VFeBx5kH/NIIGlaNHLcrIvK3CK0HkZwC3Cici0A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.1.tgz", + "integrity": "sha512-PorCgUounn0VXcpeJu+hOweZODKmGuLHsLomwqSj+p26IwjjGffmYQfVHtiTWq+NqaUuuHWWG7vPge6UFw4Aeg==", "dev": true, "dependencies": { "@rollup/pluginutils": "^4.2.1", "debug": "^4.3.4", "deepmerge": "^4.2.2", - "kleur": "^4.1.4", + "kleur": "^4.1.5", "magic-string": "^0.26.2", "svelte-hmr": "^0.14.12" }, "engines": { - "node": "^14.13.1 || >= 16" + "node": "^14.18.0 || >= 16" }, "peerDependencies": { "diff-match-patch": "^1.0.5", "svelte": "^3.44.0", - "vite": "^2.9.0" + "vite": "^3.0.0" }, "peerDependenciesMeta": { "diff-match-patch": { @@ -1583,9 +1586,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.1.tgz", - "integrity": "sha512-CmR8+Tsy95hhwtZBKJBs0/FFq4XX7sDZHlGGf+0q+BRZfMbOTkzkj0AFAuTyXbObDIoanaBBW0+KEW+m3N16Wg==", + "version": "18.0.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.6.tgz", + "integrity": "sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -1867,6 +1870,19 @@ "node": ">= 10" } }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2126,6 +2142,22 @@ "node": ">=0.10.0" } }, + "node_modules/define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2209,6 +2241,60 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es6-promise": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", @@ -2216,9 +2302,9 @@ "dev": true }, "node_modules/esbuild": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.48.tgz", - "integrity": "sha512-w6N1Yn5MtqK2U1/WZTX9ZqUVb8IOLZkZ5AdHkT6x3cHDMVsYWC7WPdiLmx19w3i4Rwzy5LqsEMtVihG3e4rFzA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.49.tgz", + "integrity": "sha512-/TlVHhOaq7Yz8N1OJrjqM3Auzo5wjvHFLk+T8pIue+fhnhIMpfAzsG6PLVMbFveVxqD2WOp3QHei+52IMUNmCw==", "dev": true, "hasInstallScript": true, "bin": { @@ -2228,32 +2314,32 @@ "node": ">=12" }, "optionalDependencies": { - "esbuild-android-64": "0.14.48", - "esbuild-android-arm64": "0.14.48", - "esbuild-darwin-64": "0.14.48", - "esbuild-darwin-arm64": "0.14.48", - "esbuild-freebsd-64": "0.14.48", - "esbuild-freebsd-arm64": "0.14.48", - "esbuild-linux-32": "0.14.48", - "esbuild-linux-64": "0.14.48", - "esbuild-linux-arm": "0.14.48", - "esbuild-linux-arm64": "0.14.48", - "esbuild-linux-mips64le": "0.14.48", - "esbuild-linux-ppc64le": "0.14.48", - "esbuild-linux-riscv64": "0.14.48", - "esbuild-linux-s390x": "0.14.48", - "esbuild-netbsd-64": "0.14.48", - "esbuild-openbsd-64": "0.14.48", - "esbuild-sunos-64": "0.14.48", - "esbuild-windows-32": "0.14.48", - "esbuild-windows-64": "0.14.48", - "esbuild-windows-arm64": "0.14.48" + "esbuild-android-64": "0.14.49", + "esbuild-android-arm64": "0.14.49", + "esbuild-darwin-64": "0.14.49", + "esbuild-darwin-arm64": "0.14.49", + "esbuild-freebsd-64": "0.14.49", + "esbuild-freebsd-arm64": "0.14.49", + "esbuild-linux-32": "0.14.49", + "esbuild-linux-64": "0.14.49", + "esbuild-linux-arm": "0.14.49", + "esbuild-linux-arm64": "0.14.49", + "esbuild-linux-mips64le": "0.14.49", + "esbuild-linux-ppc64le": "0.14.49", + "esbuild-linux-riscv64": "0.14.49", + "esbuild-linux-s390x": "0.14.49", + "esbuild-netbsd-64": "0.14.49", + "esbuild-openbsd-64": "0.14.49", + "esbuild-sunos-64": "0.14.49", + "esbuild-windows-32": "0.14.49", + "esbuild-windows-64": "0.14.49", + "esbuild-windows-arm64": "0.14.49" } }, "node_modules/esbuild-android-64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.48.tgz", - "integrity": "sha512-3aMjboap/kqwCUpGWIjsk20TtxVoKck8/4Tu19rubh7t5Ra0Yrpg30Mt1QXXlipOazrEceGeWurXKeFJgkPOUg==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.49.tgz", + "integrity": "sha512-vYsdOTD+yi+kquhBiFWl3tyxnj2qZJsl4tAqwhT90ktUdnyTizgle7TjNx6Ar1bN7wcwWqZ9QInfdk2WVagSww==", "cpu": [ "x64" ], @@ -2267,9 +2353,9 @@ } }, "node_modules/esbuild-android-arm64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.48.tgz", - "integrity": "sha512-vptI3K0wGALiDq+EvRuZotZrJqkYkN5282iAfcffjI5lmGG9G1ta/CIVauhY42MBXwEgDJkweiDcDMRLzBZC4g==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.49.tgz", + "integrity": "sha512-g2HGr/hjOXCgSsvQZ1nK4nW/ei8JUx04Li74qub9qWrStlysaVmadRyTVuW32FGIpLQyc5sUjjZopj49eGGM2g==", "cpu": [ "arm64" ], @@ -2283,9 +2369,9 @@ } }, "node_modules/esbuild-darwin-64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.48.tgz", - "integrity": "sha512-gGQZa4+hab2Va/Zww94YbshLuWteyKGD3+EsVon8EWTWhnHFRm5N9NbALNbwi/7hQ/hM1Zm4FuHg+k6BLsl5UA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.49.tgz", + "integrity": "sha512-3rvqnBCtX9ywso5fCHixt2GBCUsogNp9DjGmvbBohh31Ces34BVzFltMSxJpacNki96+WIcX5s/vum+ckXiLYg==", "cpu": [ "x64" ], @@ -2299,9 +2385,9 @@ } }, "node_modules/esbuild-darwin-arm64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.48.tgz", - "integrity": "sha512-bFjnNEXjhZT+IZ8RvRGNJthLWNHV5JkCtuOFOnjvo5pC0sk2/QVk0Qc06g2PV3J0TcU6kaPC3RN9yy9w2PSLEA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.49.tgz", + "integrity": "sha512-XMaqDxO846srnGlUSJnwbijV29MTKUATmOLyQSfswbK/2X5Uv28M9tTLUJcKKxzoo9lnkYPsx2o8EJcTYwCs/A==", "cpu": [ "arm64" ], @@ -2315,9 +2401,9 @@ } }, "node_modules/esbuild-freebsd-64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.48.tgz", - "integrity": "sha512-1NOlwRxmOsnPcWOGTB10JKAkYSb2nue0oM1AfHWunW/mv3wERfJmnYlGzL3UAOIUXZqW8GeA2mv+QGwq7DToqA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.49.tgz", + "integrity": "sha512-NJ5Q6AjV879mOHFri+5lZLTp5XsO2hQ+KSJYLbfY9DgCu8s6/Zl2prWXVANYTeCDLlrIlNNYw8y34xqyLDKOmQ==", "cpu": [ "x64" ], @@ -2331,9 +2417,9 @@ } }, "node_modules/esbuild-freebsd-arm64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.48.tgz", - "integrity": "sha512-gXqKdO8wabVcYtluAbikDH2jhXp+Klq5oCD5qbVyUG6tFiGhrC9oczKq3vIrrtwcxDQqK6+HDYK8Zrd4bCA9Gw==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.49.tgz", + "integrity": "sha512-lFLtgXnAc3eXYqj5koPlBZvEbBSOSUbWO3gyY/0+4lBdRqELyz4bAuamHvmvHW5swJYL7kngzIZw6kdu25KGOA==", "cpu": [ "arm64" ], @@ -2347,9 +2433,9 @@ } }, "node_modules/esbuild-linux-32": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.48.tgz", - "integrity": "sha512-ghGyDfS289z/LReZQUuuKq9KlTiTspxL8SITBFQFAFRA/IkIvDpnZnCAKTCjGXAmUqroMQfKJXMxyjJA69c/nQ==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.49.tgz", + "integrity": "sha512-zTTH4gr2Kb8u4QcOpTDVn7Z8q7QEIvFl/+vHrI3cF6XOJS7iEI1FWslTo3uofB2+mn6sIJEQD9PrNZKoAAMDiA==", "cpu": [ "ia32" ], @@ -2363,9 +2449,9 @@ } }, "node_modules/esbuild-linux-64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.48.tgz", - "integrity": "sha512-vni3p/gppLMVZLghI7oMqbOZdGmLbbKR23XFARKnszCIBpEMEDxOMNIKPmMItQrmH/iJrL1z8Jt2nynY0bE1ug==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.49.tgz", + "integrity": "sha512-hYmzRIDzFfLrB5c1SknkxzM8LdEUOusp6M2TnuQZJLRtxTgyPnZZVtyMeCLki0wKgYPXkFsAVhi8vzo2mBNeTg==", "cpu": [ "x64" ], @@ -2379,9 +2465,9 @@ } }, "node_modules/esbuild-linux-arm": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.48.tgz", - "integrity": "sha512-+VfSV7Akh1XUiDNXgqgY1cUP1i2vjI+BmlyXRfVz5AfV3jbpde8JTs5Q9sYgaoq5cWfuKfoZB/QkGOI+QcL1Tw==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.49.tgz", + "integrity": "sha512-iE3e+ZVv1Qz1Sy0gifIsarJMQ89Rpm9mtLSRtG3AH0FPgAzQ5Z5oU6vYzhc/3gSPi2UxdCOfRhw2onXuFw/0lg==", "cpu": [ "arm" ], @@ -2395,9 +2481,9 @@ } }, "node_modules/esbuild-linux-arm64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.48.tgz", - "integrity": "sha512-3CFsOlpoxlKPRevEHq8aAntgYGYkE1N9yRYAcPyng/p4Wyx0tPR5SBYsxLKcgPB9mR8chHEhtWYz6EZ+H199Zw==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.49.tgz", + "integrity": "sha512-KLQ+WpeuY+7bxukxLz5VgkAAVQxUv67Ft4DmHIPIW+2w3ObBPQhqNoeQUHxopoW/aiOn3m99NSmSV+bs4BSsdA==", "cpu": [ "arm64" ], @@ -2411,9 +2497,9 @@ } }, "node_modules/esbuild-linux-mips64le": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.48.tgz", - "integrity": "sha512-cs0uOiRlPp6ymknDnjajCgvDMSsLw5mST2UXh+ZIrXTj2Ifyf2aAP3Iw4DiqgnyYLV2O/v/yWBJx+WfmKEpNLA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.49.tgz", + "integrity": "sha512-n+rGODfm8RSum5pFIqFQVQpYBw+AztL8s6o9kfx7tjfK0yIGF6tm5HlG6aRjodiiKkH2xAiIM+U4xtQVZYU4rA==", "cpu": [ "mips64el" ], @@ -2427,9 +2513,9 @@ } }, "node_modules/esbuild-linux-ppc64le": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.48.tgz", - "integrity": "sha512-+2F0vJMkuI0Wie/wcSPDCqXvSFEELH7Jubxb7mpWrA/4NpT+/byjxDz0gG6R1WJoeDefcrMfpBx4GFNN1JQorQ==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.49.tgz", + "integrity": "sha512-WP9zR4HX6iCBmMFH+XHHng2LmdoIeUmBpL4aL2TR8ruzXyT4dWrJ5BSbT8iNo6THN8lod6GOmYDLq/dgZLalGw==", "cpu": [ "ppc64" ], @@ -2443,9 +2529,9 @@ } }, "node_modules/esbuild-linux-riscv64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.48.tgz", - "integrity": "sha512-BmaK/GfEE+5F2/QDrIXteFGKnVHGxlnK9MjdVKMTfvtmudjY3k2t8NtlY4qemKSizc+QwyombGWTBDc76rxePA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.49.tgz", + "integrity": "sha512-h66ORBz+Dg+1KgLvzTVQEA1LX4XBd1SK0Fgbhhw4akpG/YkN8pS6OzYI/7SGENiN6ao5hETRDSkVcvU9NRtkMQ==", "cpu": [ "riscv64" ], @@ -2459,9 +2545,9 @@ } }, "node_modules/esbuild-linux-s390x": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.48.tgz", - "integrity": "sha512-tndw/0B9jiCL+KWKo0TSMaUm5UWBLsfCKVdbfMlb3d5LeV9WbijZ8Ordia8SAYv38VSJWOEt6eDCdOx8LqkC4g==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.49.tgz", + "integrity": "sha512-DhrUoFVWD+XmKO1y7e4kNCqQHPs6twz6VV6Uezl/XHYGzM60rBewBF5jlZjG0nCk5W/Xy6y1xWeopkrhFFM0sQ==", "cpu": [ "s390x" ], @@ -2475,9 +2561,9 @@ } }, "node_modules/esbuild-netbsd-64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.48.tgz", - "integrity": "sha512-V9hgXfwf/T901Lr1wkOfoevtyNkrxmMcRHyticybBUHookznipMOHoF41Al68QBsqBxnITCEpjjd4yAos7z9Tw==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.49.tgz", + "integrity": "sha512-BXaUwFOfCy2T+hABtiPUIpWjAeWK9P8O41gR4Pg73hpzoygVGnj0nI3YK4SJhe52ELgtdgWP/ckIkbn2XaTxjQ==", "cpu": [ "x64" ], @@ -2491,9 +2577,9 @@ } }, "node_modules/esbuild-openbsd-64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.48.tgz", - "integrity": "sha512-+IHf4JcbnnBl4T52egorXMatil/za0awqzg2Vy6FBgPcBpisDWT2sVz/tNdrK9kAqj+GZG/jZdrOkj7wsrNTKA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.49.tgz", + "integrity": "sha512-lP06UQeLDGmVPw9Rg437Btu6J9/BmyhdoefnQ4gDEJTtJvKtQaUcOQrhjTq455ouZN4EHFH1h28WOJVANK41kA==", "cpu": [ "x64" ], @@ -2507,9 +2593,9 @@ } }, "node_modules/esbuild-sunos-64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.48.tgz", - "integrity": "sha512-77m8bsr5wOpOWbGi9KSqDphcq6dFeJyun8TA+12JW/GAjyfTwVtOnN8DOt6DSPUfEV+ltVMNqtXUeTeMAxl5KA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.49.tgz", + "integrity": "sha512-4c8Zowp+V3zIWje329BeLbGh6XI9c/rqARNaj5yPHdC61pHI9UNdDxT3rePPJeWcEZVKjkiAS6AP6kiITp7FSw==", "cpu": [ "x64" ], @@ -2523,9 +2609,9 @@ } }, "node_modules/esbuild-windows-32": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.48.tgz", - "integrity": "sha512-EPgRuTPP8vK9maxpTGDe5lSoIBHGKO/AuxDncg5O3NkrPeLNdvvK8oywB0zGaAZXxYWfNNSHskvvDgmfVTguhg==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.49.tgz", + "integrity": "sha512-q7Rb+J9yHTeKr9QTPDYkqfkEj8/kcKz9lOabDuvEXpXuIcosWCJgo5Z7h/L4r7rbtTH4a8U2FGKb6s1eeOHmJA==", "cpu": [ "ia32" ], @@ -2539,9 +2625,9 @@ } }, "node_modules/esbuild-windows-64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.48.tgz", - "integrity": "sha512-YmpXjdT1q0b8ictSdGwH3M8VCoqPpK1/UArze3X199w6u8hUx3V8BhAi1WjbsfDYRBanVVtduAhh2sirImtAvA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.49.tgz", + "integrity": "sha512-+Cme7Ongv0UIUTniPqfTX6mJ8Deo7VXw9xN0yJEN1lQMHDppTNmKwAM3oGbD/Vqff+07K2gN0WfNkMohmG+dVw==", "cpu": [ "x64" ], @@ -2555,9 +2641,9 @@ } }, "node_modules/esbuild-windows-arm64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.48.tgz", - "integrity": "sha512-HHaOMCsCXp0rz5BT2crTka6MPWVno121NKApsGs/OIW5QC0ggC69YMGs1aJct9/9FSUF4A1xNE/cLvgB5svR4g==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.49.tgz", + "integrity": "sha512-v+HYNAXzuANrCbbLFJ5nmO3m5y2PGZWLe3uloAkLt87aXiO2mZr3BTmacZdjwNkNEHuH3bNtN8cak+mzVjVPfA==", "cpu": [ "arm64" ], @@ -2732,6 +2818,33 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gauge": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", @@ -2773,6 +2886,20 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", @@ -2782,6 +2909,22 @@ "node": ">=0.10.0" } }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -2919,6 +3062,15 @@ "node": ">= 0.4.0" } }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2928,6 +3080,45 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -3078,10 +3269,24 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", - "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", "dev": true }, "node_modules/is-arrayish": { @@ -3090,6 +3295,18 @@ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -3102,6 +3319,34 @@ "node": ">=8" } }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-core-module": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", @@ -3114,6 +3359,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3150,6 +3410,18 @@ "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "dev": true }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -3159,6 +3431,21 @@ "node": ">=0.12.0" } }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -3168,12 +3455,82 @@ "node": ">=0.10.0" } }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", "dev": true }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -3817,6 +4174,42 @@ "node": ">=0.10.0" } }, + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -4030,9 +4423,9 @@ } }, "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", "dev": true }, "node_modules/punycode": { @@ -4198,6 +4591,23 @@ "node": ">=8" } }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -4300,9 +4710,9 @@ } }, "node_modules/rollup": { - "version": "2.75.7", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.75.7.tgz", - "integrity": "sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ==", + "version": "2.77.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.0.tgz", + "integrity": "sha512-vL8xjY4yOQEw79DvyXLijhnhh+R/O9zpF/LEgkCebZFtb6ELeN9H3/2T0r8+mp+fFTBHZ5qGpOpW2ela2zRt3g==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -4412,9 +4822,9 @@ } }, "node_modules/sass": { - "version": "1.53.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.53.0.tgz", - "integrity": "sha512-zb/oMirbKhUgRQ0/GFz8TSAwRq2IlR29vOUJZOx0l8sV+CkHUfHa4u5nqrG+1VceZp7Jfj59SVW9ogdhTvJDcQ==", + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.54.0.tgz", + "integrity": "sha512-C4zp79GCXZfK0yoHZg+GxF818/aclhp9F48XBu/+bm9vXEVAYov9iU3FBVRMq3Hx3OA4jfKL+p2K9180mEh0xQ==", "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -4498,6 +4908,20 @@ "node": ">=8" } }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -4529,12 +4953,12 @@ } }, "node_modules/socks": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", - "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz", + "integrity": "sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==", "dev": true, "dependencies": { - "ip": "^1.1.5", + "ip": "^2.0.0", "smart-buffer": "^4.2.0" }, "engines": { @@ -4726,6 +5150,53 @@ "node": ">=8" } }, + "node_modules/string.prototype.matchall": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", + "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.1", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -4775,9 +5246,9 @@ } }, "node_modules/svelte": { - "version": "3.48.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.48.0.tgz", - "integrity": "sha512-fN2YRm/bGumvjUpu6yI3BpvZnpIm9I6A7HR4oUNYd7ggYyIwSA/BX7DJ+UXXffLp6XNcUijyLvttbPVCYa/3xQ==", + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.49.0.tgz", + "integrity": "sha512-+lmjic1pApJWDfPCpUUTc1m8azDqYCG1JN9YEngrx/hUyIcFJo6VZhj0A1Ai0wqoHcEIuQy+e9tk+4uDgdtsFA==", "dev": true, "engines": { "node": ">= 8" @@ -4817,6 +5288,12 @@ "svelte": ">=3.19.0" } }, + "node_modules/svelte-icon": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/svelte-icon/-/svelte-icon-1.2.4.tgz", + "integrity": "sha512-fDdTKQAaWUFRRR1f4l65ynXdoAcsR8ikL8G9hOh7gGrjlx/44Ka6flEJHR5mCKoAN/A11n8pd96QcKZpxvmbIQ==", + "dev": true + }, "node_modules/svelte-material-ui": { "version": "6.0.0-beta.16", "resolved": "https://registry.npmjs.org/svelte-material-ui/-/svelte-material-ui-6.0.0-beta.16.tgz", @@ -4941,10 +5418,16 @@ "sourcemap-codec": "^1.4.8" } }, + "node_modules/svelte-tiny-virtual-list": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/svelte-tiny-virtual-list/-/svelte-tiny-virtual-list-2.0.5.tgz", + "integrity": "sha512-xg9ckb8UeeIme4/5qlwCrl2QNmUZ8SCQYZn3Ji83cUsoASqRNy3KWjpmNmzYvPDqCHSZjruBBsoB7t5hwuzw5g==", + "dev": true + }, "node_modules/svelte2tsx": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.5.11.tgz", - "integrity": "sha512-Is95G1wqNvEUJZ9DITRS2zfMwVJRZztMduPs1vJJ0cm65WUg/avBl5vBXjHycQL/qmFpaqa3NG4qWnf7bCHPag==", + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.5.12.tgz", + "integrity": "sha512-43ayMivmh1IDCgb+4YDf54YuOJZGCUKFpp37RbfjGgNU+Pmb9HhP+zRXa1pMh4mwSTBfqZS0FbJZP3Q8CSxvvg==", "dev": true, "dependencies": { "dedent-js": "^1.0.1", @@ -5070,6 +5553,21 @@ "node": ">=4.2.0" } }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/unique-filename": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", @@ -5138,21 +5636,21 @@ } }, "node_modules/vite": { - "version": "2.9.13", - "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.13.tgz", - "integrity": "sha512-AsOBAaT0AD7Mhe8DuK+/kE4aWYFMx/i0ZNi98hJclxb4e0OhQcZYUrvLjIaQ8e59Ui7txcvKMiJC1yftqpQoDw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.0.2.tgz", + "integrity": "sha512-TAqydxW/w0U5AoL5AsD9DApTvGb2iNbGs3sN4u2VdT1GFkQVUfgUldt+t08TZgi23uIauh1TUOQJALduo9GXqw==", "dev": true, "dependencies": { - "esbuild": "^0.14.27", - "postcss": "^8.4.13", - "resolve": "^1.22.0", - "rollup": "^2.59.0" + "esbuild": "^0.14.47", + "postcss": "^8.4.14", + "resolve": "^1.22.1", + "rollup": "^2.75.6" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": ">=12.2.0" + "node": "^14.18.0 || >=16.0.0" }, "optionalDependencies": { "fsevents": "~2.3.2" @@ -5160,7 +5658,8 @@ "peerDependencies": { "less": "*", "sass": "*", - "stylus": "*" + "stylus": "*", + "terser": "^5.4.0" }, "peerDependenciesMeta": { "less": { @@ -5171,6 +5670,9 @@ }, "stylus": { "optional": true + }, + "terser": { + "optional": true } } }, @@ -5205,6 +5707,22 @@ "node": ">= 8" } }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -5375,9 +5893,9 @@ "dev": true }, "@jridgewell/resolve-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz", - "integrity": "sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true }, "@jridgewell/sourcemap-codec": { @@ -6744,27 +7262,26 @@ } }, "@sveltejs/kit": { - "version": "1.0.0-next.357", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.357.tgz", - "integrity": "sha512-nCAehVybIEpQNnPu61V/EFVdfDb1nBSiQUfW9EcSSDEUbyAMCVBOKZZuzQ0qQDp3xniqRkyDzpBA4wN+ADxHBw==", + "version": "1.0.0-next.392", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.392.tgz", + "integrity": "sha512-od4rDJ/Soq0I7mda7sTbAnNKERHSDEGNa7QBpLA859xgBkwC1JnEIymYOh9dm+hMyHhB0bUoRoaur0qxKLqOOw==", "dev": true, "requires": { - "@sveltejs/vite-plugin-svelte": "^1.0.0-next.48", + "@sveltejs/vite-plugin-svelte": "^1.0.1", "chokidar": "^3.5.3", - "sade": "^1.8.1", - "vite": "^2.9.10" + "sade": "^1.8.1" } }, "@sveltejs/vite-plugin-svelte": { - "version": "1.0.0-next.49", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.0-next.49.tgz", - "integrity": "sha512-AKh0Ka8EDgidnxWUs8Hh2iZLZovkETkefO99XxZ4sW4WGJ7VFeBx5kH/NIIGlaNHLcrIvK3CK0HkZwC3Cici0A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.1.tgz", + "integrity": "sha512-PorCgUounn0VXcpeJu+hOweZODKmGuLHsLomwqSj+p26IwjjGffmYQfVHtiTWq+NqaUuuHWWG7vPge6UFw4Aeg==", "dev": true, "requires": { "@rollup/pluginutils": "^4.2.1", "debug": "^4.3.4", "deepmerge": "^4.2.2", - "kleur": "^4.1.4", + "kleur": "^4.1.5", "magic-string": "^0.26.2", "svelte-hmr": "^0.14.12" } @@ -6788,9 +7305,9 @@ "dev": true }, "@types/node": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.1.tgz", - "integrity": "sha512-CmR8+Tsy95hhwtZBKJBs0/FFq4XX7sDZHlGGf+0q+BRZfMbOTkzkj0AFAuTyXbObDIoanaBBW0+KEW+m3N16Wg==", + "version": "18.0.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.6.tgz", + "integrity": "sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw==", "dev": true }, "@types/normalize-package-data": { @@ -7020,6 +7537,16 @@ "unique-filename": "^1.1.1" } }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -7211,6 +7738,16 @@ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", "dev": true }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -7282,6 +7819,48 @@ "is-arrayish": "^0.2.1" } }, + "es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, "es6-promise": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", @@ -7289,170 +7868,170 @@ "dev": true }, "esbuild": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.48.tgz", - "integrity": "sha512-w6N1Yn5MtqK2U1/WZTX9ZqUVb8IOLZkZ5AdHkT6x3cHDMVsYWC7WPdiLmx19w3i4Rwzy5LqsEMtVihG3e4rFzA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.49.tgz", + "integrity": "sha512-/TlVHhOaq7Yz8N1OJrjqM3Auzo5wjvHFLk+T8pIue+fhnhIMpfAzsG6PLVMbFveVxqD2WOp3QHei+52IMUNmCw==", "dev": true, "requires": { - "esbuild-android-64": "0.14.48", - "esbuild-android-arm64": "0.14.48", - "esbuild-darwin-64": "0.14.48", - "esbuild-darwin-arm64": "0.14.48", - "esbuild-freebsd-64": "0.14.48", - "esbuild-freebsd-arm64": "0.14.48", - "esbuild-linux-32": "0.14.48", - "esbuild-linux-64": "0.14.48", - "esbuild-linux-arm": "0.14.48", - "esbuild-linux-arm64": "0.14.48", - "esbuild-linux-mips64le": "0.14.48", - "esbuild-linux-ppc64le": "0.14.48", - "esbuild-linux-riscv64": "0.14.48", - "esbuild-linux-s390x": "0.14.48", - "esbuild-netbsd-64": "0.14.48", - "esbuild-openbsd-64": "0.14.48", - "esbuild-sunos-64": "0.14.48", - "esbuild-windows-32": "0.14.48", - "esbuild-windows-64": "0.14.48", - "esbuild-windows-arm64": "0.14.48" + "esbuild-android-64": "0.14.49", + "esbuild-android-arm64": "0.14.49", + "esbuild-darwin-64": "0.14.49", + "esbuild-darwin-arm64": "0.14.49", + "esbuild-freebsd-64": "0.14.49", + "esbuild-freebsd-arm64": "0.14.49", + "esbuild-linux-32": "0.14.49", + "esbuild-linux-64": "0.14.49", + "esbuild-linux-arm": "0.14.49", + "esbuild-linux-arm64": "0.14.49", + "esbuild-linux-mips64le": "0.14.49", + "esbuild-linux-ppc64le": "0.14.49", + "esbuild-linux-riscv64": "0.14.49", + "esbuild-linux-s390x": "0.14.49", + "esbuild-netbsd-64": "0.14.49", + "esbuild-openbsd-64": "0.14.49", + "esbuild-sunos-64": "0.14.49", + "esbuild-windows-32": "0.14.49", + "esbuild-windows-64": "0.14.49", + "esbuild-windows-arm64": "0.14.49" } }, "esbuild-android-64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.48.tgz", - "integrity": "sha512-3aMjboap/kqwCUpGWIjsk20TtxVoKck8/4Tu19rubh7t5Ra0Yrpg30Mt1QXXlipOazrEceGeWurXKeFJgkPOUg==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.49.tgz", + "integrity": "sha512-vYsdOTD+yi+kquhBiFWl3tyxnj2qZJsl4tAqwhT90ktUdnyTizgle7TjNx6Ar1bN7wcwWqZ9QInfdk2WVagSww==", "dev": true, "optional": true }, "esbuild-android-arm64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.48.tgz", - "integrity": "sha512-vptI3K0wGALiDq+EvRuZotZrJqkYkN5282iAfcffjI5lmGG9G1ta/CIVauhY42MBXwEgDJkweiDcDMRLzBZC4g==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.49.tgz", + "integrity": "sha512-g2HGr/hjOXCgSsvQZ1nK4nW/ei8JUx04Li74qub9qWrStlysaVmadRyTVuW32FGIpLQyc5sUjjZopj49eGGM2g==", "dev": true, "optional": true }, "esbuild-darwin-64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.48.tgz", - "integrity": "sha512-gGQZa4+hab2Va/Zww94YbshLuWteyKGD3+EsVon8EWTWhnHFRm5N9NbALNbwi/7hQ/hM1Zm4FuHg+k6BLsl5UA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.49.tgz", + "integrity": "sha512-3rvqnBCtX9ywso5fCHixt2GBCUsogNp9DjGmvbBohh31Ces34BVzFltMSxJpacNki96+WIcX5s/vum+ckXiLYg==", "dev": true, "optional": true }, "esbuild-darwin-arm64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.48.tgz", - "integrity": "sha512-bFjnNEXjhZT+IZ8RvRGNJthLWNHV5JkCtuOFOnjvo5pC0sk2/QVk0Qc06g2PV3J0TcU6kaPC3RN9yy9w2PSLEA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.49.tgz", + "integrity": "sha512-XMaqDxO846srnGlUSJnwbijV29MTKUATmOLyQSfswbK/2X5Uv28M9tTLUJcKKxzoo9lnkYPsx2o8EJcTYwCs/A==", "dev": true, "optional": true }, "esbuild-freebsd-64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.48.tgz", - "integrity": "sha512-1NOlwRxmOsnPcWOGTB10JKAkYSb2nue0oM1AfHWunW/mv3wERfJmnYlGzL3UAOIUXZqW8GeA2mv+QGwq7DToqA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.49.tgz", + "integrity": "sha512-NJ5Q6AjV879mOHFri+5lZLTp5XsO2hQ+KSJYLbfY9DgCu8s6/Zl2prWXVANYTeCDLlrIlNNYw8y34xqyLDKOmQ==", "dev": true, "optional": true }, "esbuild-freebsd-arm64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.48.tgz", - "integrity": "sha512-gXqKdO8wabVcYtluAbikDH2jhXp+Klq5oCD5qbVyUG6tFiGhrC9oczKq3vIrrtwcxDQqK6+HDYK8Zrd4bCA9Gw==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.49.tgz", + "integrity": "sha512-lFLtgXnAc3eXYqj5koPlBZvEbBSOSUbWO3gyY/0+4lBdRqELyz4bAuamHvmvHW5swJYL7kngzIZw6kdu25KGOA==", "dev": true, "optional": true }, "esbuild-linux-32": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.48.tgz", - "integrity": "sha512-ghGyDfS289z/LReZQUuuKq9KlTiTspxL8SITBFQFAFRA/IkIvDpnZnCAKTCjGXAmUqroMQfKJXMxyjJA69c/nQ==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.49.tgz", + "integrity": "sha512-zTTH4gr2Kb8u4QcOpTDVn7Z8q7QEIvFl/+vHrI3cF6XOJS7iEI1FWslTo3uofB2+mn6sIJEQD9PrNZKoAAMDiA==", "dev": true, "optional": true }, "esbuild-linux-64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.48.tgz", - "integrity": "sha512-vni3p/gppLMVZLghI7oMqbOZdGmLbbKR23XFARKnszCIBpEMEDxOMNIKPmMItQrmH/iJrL1z8Jt2nynY0bE1ug==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.49.tgz", + "integrity": "sha512-hYmzRIDzFfLrB5c1SknkxzM8LdEUOusp6M2TnuQZJLRtxTgyPnZZVtyMeCLki0wKgYPXkFsAVhi8vzo2mBNeTg==", "dev": true, "optional": true }, "esbuild-linux-arm": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.48.tgz", - "integrity": "sha512-+VfSV7Akh1XUiDNXgqgY1cUP1i2vjI+BmlyXRfVz5AfV3jbpde8JTs5Q9sYgaoq5cWfuKfoZB/QkGOI+QcL1Tw==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.49.tgz", + "integrity": "sha512-iE3e+ZVv1Qz1Sy0gifIsarJMQ89Rpm9mtLSRtG3AH0FPgAzQ5Z5oU6vYzhc/3gSPi2UxdCOfRhw2onXuFw/0lg==", "dev": true, "optional": true }, "esbuild-linux-arm64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.48.tgz", - "integrity": "sha512-3CFsOlpoxlKPRevEHq8aAntgYGYkE1N9yRYAcPyng/p4Wyx0tPR5SBYsxLKcgPB9mR8chHEhtWYz6EZ+H199Zw==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.49.tgz", + "integrity": "sha512-KLQ+WpeuY+7bxukxLz5VgkAAVQxUv67Ft4DmHIPIW+2w3ObBPQhqNoeQUHxopoW/aiOn3m99NSmSV+bs4BSsdA==", "dev": true, "optional": true }, "esbuild-linux-mips64le": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.48.tgz", - "integrity": "sha512-cs0uOiRlPp6ymknDnjajCgvDMSsLw5mST2UXh+ZIrXTj2Ifyf2aAP3Iw4DiqgnyYLV2O/v/yWBJx+WfmKEpNLA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.49.tgz", + "integrity": "sha512-n+rGODfm8RSum5pFIqFQVQpYBw+AztL8s6o9kfx7tjfK0yIGF6tm5HlG6aRjodiiKkH2xAiIM+U4xtQVZYU4rA==", "dev": true, "optional": true }, "esbuild-linux-ppc64le": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.48.tgz", - "integrity": "sha512-+2F0vJMkuI0Wie/wcSPDCqXvSFEELH7Jubxb7mpWrA/4NpT+/byjxDz0gG6R1WJoeDefcrMfpBx4GFNN1JQorQ==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.49.tgz", + "integrity": "sha512-WP9zR4HX6iCBmMFH+XHHng2LmdoIeUmBpL4aL2TR8ruzXyT4dWrJ5BSbT8iNo6THN8lod6GOmYDLq/dgZLalGw==", "dev": true, "optional": true }, "esbuild-linux-riscv64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.48.tgz", - "integrity": "sha512-BmaK/GfEE+5F2/QDrIXteFGKnVHGxlnK9MjdVKMTfvtmudjY3k2t8NtlY4qemKSizc+QwyombGWTBDc76rxePA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.49.tgz", + "integrity": "sha512-h66ORBz+Dg+1KgLvzTVQEA1LX4XBd1SK0Fgbhhw4akpG/YkN8pS6OzYI/7SGENiN6ao5hETRDSkVcvU9NRtkMQ==", "dev": true, "optional": true }, "esbuild-linux-s390x": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.48.tgz", - "integrity": "sha512-tndw/0B9jiCL+KWKo0TSMaUm5UWBLsfCKVdbfMlb3d5LeV9WbijZ8Ordia8SAYv38VSJWOEt6eDCdOx8LqkC4g==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.49.tgz", + "integrity": "sha512-DhrUoFVWD+XmKO1y7e4kNCqQHPs6twz6VV6Uezl/XHYGzM60rBewBF5jlZjG0nCk5W/Xy6y1xWeopkrhFFM0sQ==", "dev": true, "optional": true }, "esbuild-netbsd-64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.48.tgz", - "integrity": "sha512-V9hgXfwf/T901Lr1wkOfoevtyNkrxmMcRHyticybBUHookznipMOHoF41Al68QBsqBxnITCEpjjd4yAos7z9Tw==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.49.tgz", + "integrity": "sha512-BXaUwFOfCy2T+hABtiPUIpWjAeWK9P8O41gR4Pg73hpzoygVGnj0nI3YK4SJhe52ELgtdgWP/ckIkbn2XaTxjQ==", "dev": true, "optional": true }, "esbuild-openbsd-64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.48.tgz", - "integrity": "sha512-+IHf4JcbnnBl4T52egorXMatil/za0awqzg2Vy6FBgPcBpisDWT2sVz/tNdrK9kAqj+GZG/jZdrOkj7wsrNTKA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.49.tgz", + "integrity": "sha512-lP06UQeLDGmVPw9Rg437Btu6J9/BmyhdoefnQ4gDEJTtJvKtQaUcOQrhjTq455ouZN4EHFH1h28WOJVANK41kA==", "dev": true, "optional": true }, "esbuild-sunos-64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.48.tgz", - "integrity": "sha512-77m8bsr5wOpOWbGi9KSqDphcq6dFeJyun8TA+12JW/GAjyfTwVtOnN8DOt6DSPUfEV+ltVMNqtXUeTeMAxl5KA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.49.tgz", + "integrity": "sha512-4c8Zowp+V3zIWje329BeLbGh6XI9c/rqARNaj5yPHdC61pHI9UNdDxT3rePPJeWcEZVKjkiAS6AP6kiITp7FSw==", "dev": true, "optional": true }, "esbuild-windows-32": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.48.tgz", - "integrity": "sha512-EPgRuTPP8vK9maxpTGDe5lSoIBHGKO/AuxDncg5O3NkrPeLNdvvK8oywB0zGaAZXxYWfNNSHskvvDgmfVTguhg==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.49.tgz", + "integrity": "sha512-q7Rb+J9yHTeKr9QTPDYkqfkEj8/kcKz9lOabDuvEXpXuIcosWCJgo5Z7h/L4r7rbtTH4a8U2FGKb6s1eeOHmJA==", "dev": true, "optional": true }, "esbuild-windows-64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.48.tgz", - "integrity": "sha512-YmpXjdT1q0b8ictSdGwH3M8VCoqPpK1/UArze3X199w6u8hUx3V8BhAi1WjbsfDYRBanVVtduAhh2sirImtAvA==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.49.tgz", + "integrity": "sha512-+Cme7Ongv0UIUTniPqfTX6mJ8Deo7VXw9xN0yJEN1lQMHDppTNmKwAM3oGbD/Vqff+07K2gN0WfNkMohmG+dVw==", "dev": true, "optional": true }, "esbuild-windows-arm64": { - "version": "0.14.48", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.48.tgz", - "integrity": "sha512-HHaOMCsCXp0rz5BT2crTka6MPWVno121NKApsGs/OIW5QC0ggC69YMGs1aJct9/9FSUF4A1xNE/cLvgB5svR4g==", + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.49.tgz", + "integrity": "sha512-v+HYNAXzuANrCbbLFJ5nmO3m5y2PGZWLe3uloAkLt87aXiO2mZr3BTmacZdjwNkNEHuH3bNtN8cak+mzVjVPfA==", "dev": true, "optional": true }, @@ -7584,6 +8163,24 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true + }, "gauge": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", @@ -7616,12 +8213,33 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==", "dev": true }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -7727,12 +8345,42 @@ "function-bind": "^1.1.1" } }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -7855,10 +8503,21 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, "ip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", - "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", "dev": true }, "is-arrayish": { @@ -7867,6 +8526,15 @@ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -7876,6 +8544,22 @@ "binary-extensions": "^2.0.0" } }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true + }, "is-core-module": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", @@ -7885,6 +8569,15 @@ "has": "^1.0.3" } }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -7912,24 +8605,85 @@ "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "dev": true }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "dev": true }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", "dev": true }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -8429,6 +9183,30 @@ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -8584,9 +9362,9 @@ } }, "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", "dev": true }, "punycode": { @@ -8706,6 +9484,17 @@ "strip-indent": "^3.0.0" } }, + "regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, "request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -8779,9 +9568,9 @@ } }, "rollup": { - "version": "2.75.7", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.75.7.tgz", - "integrity": "sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ==", + "version": "2.77.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.0.tgz", + "integrity": "sha512-vL8xjY4yOQEw79DvyXLijhnhh+R/O9zpF/LEgkCebZFtb6ELeN9H3/2T0r8+mp+fFTBHZ5qGpOpW2ela2zRt3g==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -8850,9 +9639,9 @@ } }, "sass": { - "version": "1.53.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.53.0.tgz", - "integrity": "sha512-zb/oMirbKhUgRQ0/GFz8TSAwRq2IlR29vOUJZOx0l8sV+CkHUfHa4u5nqrG+1VceZp7Jfj59SVW9ogdhTvJDcQ==", + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.54.0.tgz", + "integrity": "sha512-C4zp79GCXZfK0yoHZg+GxF818/aclhp9F48XBu/+bm9vXEVAYov9iU3FBVRMq3Hx3OA4jfKL+p2K9180mEh0xQ==", "dev": true, "requires": { "chokidar": ">=3.0.0 <4.0.0", @@ -8912,6 +9701,17 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, "signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -8936,12 +9736,12 @@ } }, "socks": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", - "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz", + "integrity": "sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==", "dev": true, "requires": { - "ip": "^1.1.5", + "ip": "^2.0.0", "smart-buffer": "^4.2.0" } }, @@ -9105,6 +9905,44 @@ "strip-ansi": "^6.0.1" } }, + "string.prototype.matchall": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", + "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.1", + "side-channel": "^1.0.4" + } + }, + "string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -9139,9 +9977,9 @@ "dev": true }, "svelte": { - "version": "3.48.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.48.0.tgz", - "integrity": "sha512-fN2YRm/bGumvjUpu6yI3BpvZnpIm9I6A7HR4oUNYd7ggYyIwSA/BX7DJ+UXXffLp6XNcUijyLvttbPVCYa/3xQ==", + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.49.0.tgz", + "integrity": "sha512-+lmjic1pApJWDfPCpUUTc1m8azDqYCG1JN9YEngrx/hUyIcFJo6VZhj0A1Ai0wqoHcEIuQy+e9tk+4uDgdtsFA==", "dev": true }, "svelte-check": { @@ -9167,6 +10005,12 @@ "dev": true, "requires": {} }, + "svelte-icon": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/svelte-icon/-/svelte-icon-1.2.4.tgz", + "integrity": "sha512-fDdTKQAaWUFRRR1f4l65ynXdoAcsR8ikL8G9hOh7gGrjlx/44Ka6flEJHR5mCKoAN/A11n8pd96QcKZpxvmbIQ==", + "dev": true + }, "svelte-material-ui": { "version": "6.0.0-beta.16", "resolved": "https://registry.npmjs.org/svelte-material-ui/-/svelte-material-ui-6.0.0-beta.16.tgz", @@ -9241,10 +10085,16 @@ } } }, + "svelte-tiny-virtual-list": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/svelte-tiny-virtual-list/-/svelte-tiny-virtual-list-2.0.5.tgz", + "integrity": "sha512-xg9ckb8UeeIme4/5qlwCrl2QNmUZ8SCQYZn3Ji83cUsoASqRNy3KWjpmNmzYvPDqCHSZjruBBsoB7t5hwuzw5g==", + "dev": true + }, "svelte2tsx": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.5.11.tgz", - "integrity": "sha512-Is95G1wqNvEUJZ9DITRS2zfMwVJRZztMduPs1vJJ0cm65WUg/avBl5vBXjHycQL/qmFpaqa3NG4qWnf7bCHPag==", + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.5.12.tgz", + "integrity": "sha512-43ayMivmh1IDCgb+4YDf54YuOJZGCUKFpp37RbfjGgNU+Pmb9HhP+zRXa1pMh4mwSTBfqZS0FbJZP3Q8CSxvvg==", "dev": true, "requires": { "dedent-js": "^1.0.1", @@ -9338,6 +10188,18 @@ "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", "dev": true }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, "unique-filename": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", @@ -9399,16 +10261,16 @@ } }, "vite": { - "version": "2.9.13", - "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.13.tgz", - "integrity": "sha512-AsOBAaT0AD7Mhe8DuK+/kE4aWYFMx/i0ZNi98hJclxb4e0OhQcZYUrvLjIaQ8e59Ui7txcvKMiJC1yftqpQoDw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.0.2.tgz", + "integrity": "sha512-TAqydxW/w0U5AoL5AsD9DApTvGb2iNbGs3sN4u2VdT1GFkQVUfgUldt+t08TZgi23uIauh1TUOQJALduo9GXqw==", "dev": true, "requires": { - "esbuild": "^0.14.27", + "esbuild": "^0.14.47", "fsevents": "~2.3.2", - "postcss": "^8.4.13", - "resolve": "^1.22.0", - "rollup": "^2.59.0" + "postcss": "^8.4.14", + "resolve": "^1.22.1", + "rollup": "^2.75.6" } }, "webidl-conversions": { @@ -9436,6 +10298,19 @@ "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", diff --git a/src/svelte-components/package.json b/src/svelte-components/package.json index f507672..2700285 100644 --- a/src/svelte-components/package.json +++ b/src/svelte-components/package.json @@ -11,18 +11,21 @@ "check": "svelte-check --tsconfig ./tsconfig.json" }, "devDependencies": { - "@sveltejs/kit": "^1.0.0-next.357", - "@sveltejs/vite-plugin-svelte": "^1.0.0-next.49", + "@sveltejs/kit": "^1.0.0-next.392", + "@sveltejs/vite-plugin-svelte": "^1.0.1", "@tsconfig/svelte": "^3.0.0", "node-sass": "^7.0.1", "polyfill-object.fromentries": "^1.0.1", "smui-theme": "^6.0.0-beta.16", - "svelte": "^3.48.0", + "string.prototype.matchall": "^4.0.7", + "svelte": "^3.49.0", "svelte-check": "^2.8.0", + "svelte-icon": "^1.2.4", "svelte-material-ui": "^6.0.0-beta.16", "svelte-preprocess": "^4.10.7", + "svelte-tiny-virtual-list": "^2.0.5", "tslib": "^2.4.0", "typescript": "^4.7.4", - "vite": "^2.9.13" + "vite": "^3.0.2" } } diff --git a/src/svelte-components/public/material-symbols-outlined.css b/src/svelte-components/public/material-symbols-outlined.css deleted file mode 100644 index b40236d..0000000 --- a/src/svelte-components/public/material-symbols-outlined.css +++ /dev/null @@ -1,28 +0,0 @@ -/* To browse the icons in material-symbols, see https://marella.me/material-symbols/demo/ */ - -@font-face { - font-family: "Material Symbols Outlined"; - font-style: normal; - font-weight: 100 700; - font-display: block; - src: url("./fonts/material-symbols-outlined.woff2") format("woff2"); - } - .material-symbols-outlined { - font-family: "Material Symbols Outlined"; - font-weight: normal; - font-style: normal; - font-size: 24px; - line-height: 1; - letter-spacing: normal; - text-transform: none; - display: inline-block; - white-space: nowrap; - word-wrap: normal; - direction: ltr; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-rendering: optimizeLegibility; - font-feature-settings: "liga"; - - font-variation-settings: "FILL" 1, "wght" 400, "GRAD" 0, "opsz" 48; - } diff --git a/src/svelte-components/src/components/AdminNetworkView.svelte b/src/svelte-components/src/components/AdminNetworkView.svelte index 285e2cb..37accb8 100644 --- a/src/svelte-components/src/components/AdminNetworkView.svelte +++ b/src/svelte-components/src/components/AdminNetworkView.svelte @@ -1,204 +1,210 @@
    -

    Network Info

    +

    Network Info

    -
    -
    - - - - {$networkInfo.hostname} - - - +
    +
    + + + + {$networkInfo.hostname} + + + +
    -
    -
    -
    - - - {#each $networkInfo.ipAddresses as ipAddress} -
    - - {ipAddress} - -
    - {/each} -
    +
    +
    + + + {#each $networkInfo.ipAddresses as ipAddress} +
    + + {ipAddress} + +
    + {/each} +
    +
    -
    -
    -
    - -
    - - - {#if $networkInfo.wifi.networks.length === 0} - - Scanning... - - {:else} - {#each $networkInfo.wifi.networks as network} - onNetworkSelected(network)} - > - - wifi - - {getWifiStrengthIcon(network)} - - - {network.Name} - {#if network.Encryption !== "Open"} - - lock - - {/if} - - {/each} - {/if} - - - - Click on a Wi-Fi network to connect or disconnect. - -
    +
    +
    + +
    + + + {#if $networkInfo.wifi.networks.length === 0} + + Scanning... + + {:else} + {#each $networkInfo.wifi.networks as network} + + onNetworkSelected(network)} + > + + + + + {network.Name} + {#if network.Encryption !== "Open"} + + + + {/if} + + {/each} + {/if} + + + + Click on a Wi-Fi network to connect or disconnect. + +
    +
    -
    diff --git a/src/svelte-components/src/components/ConfigTemplatedInput.svelte b/src/svelte-components/src/components/ConfigTemplatedInput.svelte new file mode 100644 index 0000000..1d5fa4a --- /dev/null +++ b/src/svelte-components/src/components/ConfigTemplatedInput.svelte @@ -0,0 +1,131 @@ + + +{#if template} +
    + + + {#if template.values} + + {:else if template.type === "bool"} + + {:else if template.type === "float"} + + {:else if template.type === "int"} + + {:else if template.type === "string"} + + {:else if template.type == "text"} +