From b3d6eaa3a0b126712eae25c1b91925d030a2d900 Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Thu, 7 Apr 2022 18:06:40 -0400
Subject: added RecordingView

---
 .../views/nodes/RecordingBox/RecordingView.tsx     | 326 +++++++++++++++++++++
 1 file changed, 326 insertions(+)
 create mode 100644 src/client/views/nodes/RecordingBox/RecordingView.tsx

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
new file mode 100644
index 000000000..15f8c8626
--- /dev/null
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -0,0 +1,326 @@
+import * as React from 'react';
+import "./RecordingView.scss";
+import { ReactElement, useCallback, useEffect, useRef, useState } from "react";
+import { ProgressBar } from "./ProgressBar"
+import { MdBackspace } from 'react-icons/md';
+import { FaCheckCircle } from 'react-icons/fa';
+import { IconContext } from "react-icons";
+
+
+enum RecordingStatus {
+      Recording,
+      Stopped,
+      Paused
+}
+
+interface VideoSegment {
+      chunks: any[],
+      endTime: number
+}
+
+const MAXTIME = 1000;
+
+export function RecordingView() {
+
+      const [recording, setRecording] = useState(false);
+      const recordingTimerRef = useRef<number>(0);
+      const [recordingTimer, setRecordingTimer] = useState(0); // unit is 0.01 second
+      const [playing, setPlaying] = useState(false);
+      const [progress, setProgress] = useState(0);
+      const [speed, setSpeed] = useState(1);
+      const [muted, setMuted] = useState(false);
+
+      const [videos, setVideos] = useState<VideoSegment[]>([]);
+      // const [videos, setVideos] = useState<string[]>([]);
+      const [currentVid, setCurrentVid] = useState<number>(0);
+      const recorder = useRef<MediaRecorder | null>(null);
+      const videoElementRef = useRef<HTMLVideoElement | null>(null);
+
+      const [finished, setFinished] = useState<Boolean>(false)
+
+      
+
+      const DEFAULT_MEDIA_CONSTRAINTS = {
+            video: {
+                  width: 1280,
+                  height: 720,
+            },
+            audio: {
+                  echoCancellation: true,
+                  noiseSuppression: true,
+                  sampleRate: 44100
+            }
+      }
+
+      useEffect(() => {
+
+            if (finished) {
+                  let allVideoChunks : any = []
+                  console.log(videos)
+                  videos.forEach((vid) => {
+                        console.log(vid.chunks)
+                        allVideoChunks = allVideoChunks.concat(vid.chunks)
+                  })
+
+                  console.log(allVideoChunks)
+
+                  const blob = new Blob(allVideoChunks, {
+                              type: 'video/webm'
+                  })
+                  const blobUrl = URL.createObjectURL(blob)
+
+                  videoElementRef.current!.srcObject = null
+                  videoElementRef.current!.src = blobUrl
+                  videoElementRef.current!.muted = false
+            }
+            
+
+      }, [finished])
+
+      useEffect(() => {
+            // check if the browser supports media devices on first load
+            if (!navigator.mediaDevices) {
+                  console.log('This browser does not support getUserMedia.')
+            }
+            console.log('This device has the correct media devices.')
+      }, [])
+
+      useEffect(() => {
+            // get access to the video element on every render
+            // videoElement = document.getElementById('video') as HTMLVideoElement;
+            videoElementRef.current = document.getElementById('video') as HTMLVideoElement;
+      })
+
+      // useEffect(() => {
+      //       if (playing) {
+      //             videoElement!.srcObject = null
+      //             // videoElement!.src = videos[currentVid].url
+      //             videoElement!.muted = false
+      //             videoElement!.play()
+      //       } else {
+      //             videoElement!.pause();
+      //       }
+      // }, [playing, videoElement]);
+
+      useEffect(() => {
+            let interval: any = null;
+            if (recording) {
+                  interval = setInterval(() => {
+                        setRecordingTimer(unit => unit + 1);
+                  }, 10);
+            } else if (!recording && recordingTimer !== 0) {
+                  clearInterval(interval);
+            }
+            return () => clearInterval(interval);
+      }, [recording])
+
+      useEffect(() => {
+            setVideoProgressHelper(recordingTimer)
+            recordingTimerRef.current = recordingTimer;
+      }, [recordingTimer])
+
+      const setVideoProgressHelper = (progress: number) => {
+            const newProgress = (progress / MAXTIME) * 100;
+            setProgress(newProgress)
+      }
+      const startShowingStream = async (mediaConstraints = DEFAULT_MEDIA_CONSTRAINTS) => {
+            const stream = await navigator.mediaDevices.getUserMedia(mediaConstraints)
+
+            videoElementRef.current!.src = ""
+            videoElementRef.current!.srcObject = stream
+            videoElementRef.current!.muted = true
+
+            return stream
+      }
+
+      const record = async () => {
+            const stream = await startShowingStream();
+            recorder.current = new MediaRecorder(stream)
+
+            // temporary chunks of video
+            let chunks: any = []
+            recorder.current.ondataavailable = (event: any) => {
+                  // store the video chunks as it is recording
+                  console.log("data available")
+                  if (event.data.size > 0) {
+                        chunks.push(event.data)
+                  }
+            }
+
+            recorder.current.onstart = (event: any) => {
+                  console.log("on start")
+                  setRecording(true);
+            }
+
+            recorder.current.onstop = () => {
+                  // if we have a last portion
+                  if (chunks.length > 1) {
+                        // append the current portion to the video pieces
+                        setVideos(videos => [...videos, {chunks: chunks, endTime: recordingTimerRef.current}]) 
+                  }
+
+                  // reset the temporary chunks
+                  chunks = []
+                  setRecording(false);
+                  setFinished(true);
+            }
+
+            // recording paused
+            recorder.current.onpause = (event: any) => {
+                  // append the current portion to the video pieces
+                  console.log(chunks)
+                  setVideos(videos => [...videos, {chunks: chunks, endTime: recordingTimerRef.current}])
+
+                  // reset the temporary chunks
+                  chunks = []
+                  setRecording(false);
+            }
+
+            recorder.current.onresume = async (event: any) => {
+                  console.log(event)
+                  await startShowingStream();
+                  setRecording(true);
+            }
+
+            recorder.current.start(200)
+      }
+
+
+      const stop = () => {
+            if (recorder.current) {
+                  if (recorder.current.state !== "inactive") {
+                        recorder.current.stop();
+                        // recorder.current.stream.getTracks().forEach((track: any) => track.stop())
+                  }
+            }
+      }
+
+      const pause = () => {
+            if (recorder.current) {
+                  if (recorder.current.state === "recording") {
+                        recorder.current.pause();
+                  }
+            }
+      }
+
+      const startOrResume = () => {
+          console.log('[RecordingView.tsx] startOrResume')
+            if (!recorder.current || recorder.current.state === "inactive") {
+                  record();
+            } else if (recorder.current.state === "paused") {
+                  recorder.current.resume();
+            }
+      }
+
+      const playSegment = (idx: number) => {
+            console.log(idx)
+            let currentChunks = videos[idx].chunks
+            console.log(currentChunks)
+
+            const blob = new Blob(currentChunks, {
+                  type: 'video/webm'
+            })
+            const blobUrl = URL.createObjectURL(blob)
+            console.log(blobUrl)
+
+            videoElementRef.current!.srcObject = null
+            videoElementRef.current!.src = blobUrl
+            videoElementRef.current!.muted = false
+      }
+
+      const clearPrevious = () => {
+            const numVideos = videos.length
+            setRecordingTimer(numVideos == 1 ? 0 : videos[numVideos - 2].endTime)
+            setVideoProgressHelper(numVideos == 1 ? 0 : videos[numVideos - 2].endTime)
+            setVideos(videos.filter((_, idx) => idx !== numVideos - 1));
+      }
+
+      // const handleVideoProgress = (event: any) => {
+      //       const manualChange = Number(event.target.value);
+      //       videoElement!.currentTime = (videoElement!.duration / 100) * manualChange;
+      //       setProgress(manualChange)
+      // };
+
+      // const handleVideoSpeed = (event: any) => {
+      //       const newSpeed = Number(event.target.value);
+      //       videoElement!.playbackRate = speed;
+      //       setSpeed(newSpeed)
+      // };
+
+      const handleOnTimeUpdate = () => {
+            if (playing) {
+                  setVideoProgressHelper(videoElementRef.current!.currentTime)
+            }
+      };
+
+      const millisecondToMinuteSecond = (milliseconds: number) => {
+            const toTwoDigit = (digit: number) => {
+                  return String(digit).length == 1 ? "0" + digit : digit
+            }
+            const minutes = Math.floor(( milliseconds % (1000 * 60 * 60)) / (1000 * 60));
+            const seconds = Math.floor((milliseconds % (1000 * 60)) / 1000);
+            return toTwoDigit(minutes) + " : " + toTwoDigit(seconds);
+      }
+
+      
+
+
+      useEffect(() => {
+            console.log(videos.map((elt) => elt.endTime / MAXTIME * 100))
+            console.log(videos)
+      }, [videos])
+
+      return (
+            <div className="recording-container">
+                  <div className="video-wrapper">
+                        <video id="video"
+                              autoPlay
+                              muted
+                              onTimeUpdate={handleOnTimeUpdate}
+                        />
+                        <div className="recording-sign">
+                              <span className="dot"/>
+                              <p className="timer">{millisecondToMinuteSecond(recordingTimer * 10)}</p>
+                        </div>
+                        <div className="controls">
+                              
+                              <div className="controls-inner-container">
+                                    <div className="record-button-wrapper">
+                                          {recording ? 
+                                          <button className="stop-button" onClick={pause}/> :
+                                          <button className="record-button" onClick={startOrResume}/>
+                                          }
+                                    </div>
+                                    {!recording && videos.length > 0 ? 
+
+                                    <div className="video-edit-wrapper">
+                                          <IconContext.Provider value={{ color: "grey", className: "video-edit-buttons" }}>
+                                                <MdBackspace onClick={clearPrevious}/>
+                                          </IconContext.Provider>
+                                          <IconContext.Provider value={{ color: "#cc1c08", className: "video-edit-buttons" }}>
+                                                <FaCheckCircle onClick={stop}/>
+                                          </IconContext.Provider>
+                                    </div>
+                                    
+                                     : <></>}
+                                    
+                              </div>
+                              
+                              <ProgressBar 
+                                    progress={progress} 
+                                    marks={videos.map((elt) => elt.endTime / MAXTIME * 100)}
+                                    playSegment={playSegment}
+                              />
+
+                              {/* <button className="mute-btn" onClick={() => setMuted(!muted)}>
+                                          {!muted ? (
+                                                <i className="bx bxs-volume-full"></i>
+                                          ) : (
+                                                <i className="bx bxs-volume-mute"></i>
+                                          )}
+                                    </button>  */}
+                        </div>
+
+                  </div>
+            </div>)
+}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 7d59a4fee343598f4b5a4adde97c3845e051df11 Mon Sep 17 00:00:00 2001
From: Jenny Yu <jennyyu212@outlook.com>
Date: Wed, 20 Apr 2022 23:52:56 -0400
Subject: feat: styling + play entire video after finish

---
 package-lock.json                                  | 5853 +++++++++-----------
 .../views/nodes/RecordingBox/ProgressBar.tsx       |   51 +-
 .../views/nodes/RecordingBox/RecordingView.scss    |  307 +-
 .../views/nodes/RecordingBox/RecordingView.tsx     |   97 +-
 4 files changed, 2917 insertions(+), 3391 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/package-lock.json b/package-lock.json
index d84e8a572..01763e9b6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,107 +5,62 @@
     "requires": true,
     "dependencies": {
         "@babel/code-frame": {
-            "version": "7.8.3",
-            "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
-            "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
+            "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==",
             "requires": {
-                "@babel/highlight": "^7.8.3"
+                "@babel/highlight": "^7.16.7"
             }
         },
         "@babel/generator": {
-            "version": "7.9.6",
-            "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz",
-            "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==",
+            "version": "7.17.9",
+            "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.9.tgz",
+            "integrity": "sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ==",
             "requires": {
-                "@babel/types": "^7.9.6",
+                "@babel/types": "^7.17.0",
                 "jsesc": "^2.5.1",
-                "lodash": "^4.17.13",
                 "source-map": "^0.5.0"
-            },
-            "dependencies": {
-                "@babel/types": {
-                    "version": "7.9.6",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
-                    "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
-                    "requires": {
-                        "@babel/helper-validator-identifier": "^7.9.5",
-                        "lodash": "^4.17.13",
-                        "to-fast-properties": "^2.0.0"
-                    }
-                }
             }
         },
         "@babel/helper-annotate-as-pure": {
-            "version": "7.10.4",
-            "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz",
-            "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==",
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz",
+            "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==",
             "requires": {
-                "@babel/types": "^7.10.4"
-            },
-            "dependencies": {
-                "@babel/helper-validator-identifier": {
-                    "version": "7.10.4",
-                    "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
-                    "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw=="
-                },
-                "@babel/types": {
-                    "version": "7.10.5",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.5.tgz",
-                    "integrity": "sha512-ixV66KWfCI6GKoA/2H9v6bQdbfXEwwpOdQ8cRvb4F+eyvhlaHxWFMQB4+3d9QFJXZsiiiqVrewNV0DFEQpyT4Q==",
-                    "requires": {
-                        "@babel/helper-validator-identifier": "^7.10.4",
-                        "lodash": "^4.17.19",
-                        "to-fast-properties": "^2.0.0"
-                    }
-                },
-                "lodash": {
-                    "version": "4.17.19",
-                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
-                    "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
-                }
+                "@babel/types": "^7.16.7"
+            }
+        },
+        "@babel/helper-environment-visitor": {
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz",
+            "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==",
+            "requires": {
+                "@babel/types": "^7.16.7"
             }
         },
         "@babel/helper-function-name": {
-            "version": "7.9.5",
-            "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
-            "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
+            "version": "7.17.9",
+            "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz",
+            "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==",
             "requires": {
-                "@babel/helper-get-function-arity": "^7.8.3",
-                "@babel/template": "^7.8.3",
-                "@babel/types": "^7.9.5"
+                "@babel/template": "^7.16.7",
+                "@babel/types": "^7.17.0"
             }
         },
-        "@babel/helper-get-function-arity": {
-            "version": "7.8.3",
-            "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz",
-            "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==",
+        "@babel/helper-hoist-variables": {
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz",
+            "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==",
             "requires": {
-                "@babel/types": "^7.8.3"
+                "@babel/types": "^7.16.7"
             }
         },
         "@babel/helper-module-imports": {
-            "version": "7.10.3",
-            "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.3.tgz",
-            "integrity": "sha512-Jtqw5M9pahLSUWA+76nhK9OG8nwYXzhQzVIGFoNaHnXF/r4l7kz4Fl0UAW7B6mqC5myoJiBP5/YQlXQTMfHI9w==",
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz",
+            "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==",
             "requires": {
-                "@babel/types": "^7.10.3"
-            },
-            "dependencies": {
-                "@babel/helper-validator-identifier": {
-                    "version": "7.10.3",
-                    "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz",
-                    "integrity": "sha512-bU8JvtlYpJSBPuj1VUmKpFGaDZuLxASky3LhaKj3bmpSTY6VWooSM8msk+Z0CZoErFye2tlABF6yDkT3FOPAXw=="
-                },
-                "@babel/types": {
-                    "version": "7.10.3",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.3.tgz",
-                    "integrity": "sha512-nZxaJhBXBQ8HVoIcGsf9qWep3Oh3jCENK54V4mRF7qaJabVsAYdbTtmSD8WmAp1R6ytPiu5apMwSXyxB1WlaBA==",
-                    "requires": {
-                        "@babel/helper-validator-identifier": "^7.10.3",
-                        "lodash": "^4.17.13",
-                        "to-fast-properties": "^2.0.0"
-                    }
-                }
+                "@babel/types": "^7.16.7"
             }
         },
         "@babel/helper-plugin-utils": {
@@ -114,32 +69,32 @@
             "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA=="
         },
         "@babel/helper-split-export-declaration": {
-            "version": "7.8.3",
-            "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz",
-            "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==",
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz",
+            "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==",
             "requires": {
-                "@babel/types": "^7.8.3"
+                "@babel/types": "^7.16.7"
             }
         },
         "@babel/helper-validator-identifier": {
-            "version": "7.9.5",
-            "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz",
-            "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g=="
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
+            "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw=="
         },
         "@babel/highlight": {
-            "version": "7.9.0",
-            "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
-            "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
+            "version": "7.17.9",
+            "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz",
+            "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==",
             "requires": {
-                "@babel/helper-validator-identifier": "^7.9.0",
+                "@babel/helper-validator-identifier": "^7.16.7",
                 "chalk": "^2.0.0",
                 "js-tokens": "^4.0.0"
             }
         },
         "@babel/parser": {
-            "version": "7.9.6",
-            "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
-            "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q=="
+            "version": "7.17.9",
+            "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz",
+            "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg=="
         },
         "@babel/plugin-syntax-jsx": {
             "version": "7.16.7",
@@ -150,87 +105,82 @@
             }
         },
         "@babel/runtime": {
-            "version": "7.9.2",
-            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz",
-            "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==",
+            "version": "7.17.9",
+            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz",
+            "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==",
             "requires": {
                 "regenerator-runtime": "^0.13.4"
             }
         },
         "@babel/runtime-corejs3": {
-            "version": "7.17.2",
-            "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.2.tgz",
-            "integrity": "sha512-NcKtr2epxfIrNM4VOmPKO46TvDMCBhgi2CrSHaEarrz+Plk2K5r9QemmOFTGpZaoKnWoGH5MO+CzeRsih/Fcgg==",
+            "version": "7.17.9",
+            "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.9.tgz",
+            "integrity": "sha512-WxYHHUWF2uZ7Hp1K+D1xQgbgkGUfA+5UPOegEXGt2Y5SMog/rYCVaifLZDbw8UkNXozEqqrZTy6bglL7xTaCOw==",
             "requires": {
                 "core-js-pure": "^3.20.2",
                 "regenerator-runtime": "^0.13.4"
             }
         },
         "@babel/template": {
-            "version": "7.8.6",
-            "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
-            "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz",
+            "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==",
             "requires": {
-                "@babel/code-frame": "^7.8.3",
-                "@babel/parser": "^7.8.6",
-                "@babel/types": "^7.8.6"
+                "@babel/code-frame": "^7.16.7",
+                "@babel/parser": "^7.16.7",
+                "@babel/types": "^7.16.7"
             }
         },
         "@babel/traverse": {
-            "version": "7.9.6",
-            "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz",
-            "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==",
-            "requires": {
-                "@babel/code-frame": "^7.8.3",
-                "@babel/generator": "^7.9.6",
-                "@babel/helper-function-name": "^7.9.5",
-                "@babel/helper-split-export-declaration": "^7.8.3",
-                "@babel/parser": "^7.9.6",
-                "@babel/types": "^7.9.6",
+            "version": "7.17.9",
+            "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.9.tgz",
+            "integrity": "sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw==",
+            "requires": {
+                "@babel/code-frame": "^7.16.7",
+                "@babel/generator": "^7.17.9",
+                "@babel/helper-environment-visitor": "^7.16.7",
+                "@babel/helper-function-name": "^7.17.9",
+                "@babel/helper-hoist-variables": "^7.16.7",
+                "@babel/helper-split-export-declaration": "^7.16.7",
+                "@babel/parser": "^7.17.9",
+                "@babel/types": "^7.17.0",
                 "debug": "^4.1.0",
-                "globals": "^11.1.0",
-                "lodash": "^4.17.13"
+                "globals": "^11.1.0"
             },
             "dependencies": {
-                "@babel/types": {
-                    "version": "7.9.6",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
-                    "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
-                    "requires": {
-                        "@babel/helper-validator-identifier": "^7.9.5",
-                        "lodash": "^4.17.13",
-                        "to-fast-properties": "^2.0.0"
-                    }
-                },
                 "debug": {
-                    "version": "4.1.1",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+                    "version": "4.3.4",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+                    "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
                     "requires": {
-                        "ms": "^2.1.1"
+                        "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=="
                 }
             }
         },
         "@babel/types": {
-            "version": "7.9.5",
-            "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz",
-            "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==",
+            "version": "7.17.0",
+            "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz",
+            "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==",
             "requires": {
-                "@babel/helper-validator-identifier": "^7.9.5",
-                "lodash": "^4.17.13",
+                "@babel/helper-validator-identifier": "^7.16.7",
                 "to-fast-properties": "^2.0.0"
             }
         },
         "@discoveryjs/json-ext": {
-            "version": "0.5.6",
-            "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz",
-            "integrity": "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA=="
+            "version": "0.5.7",
+            "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
+            "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw=="
         },
         "@emotion/babel-plugin": {
-            "version": "11.7.2",
-            "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.7.2.tgz",
-            "integrity": "sha512-6mGSCWi9UzXut/ZAN6lGFu33wGR3SJisNl3c0tvlmb8XChH1b2SUvxvnOh7hvLpqyRdHHU9AiazV3Cwbk5SXKQ==",
+            "version": "11.9.2",
+            "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.9.2.tgz",
+            "integrity": "sha512-Pr/7HGH6H6yKgnVFNEj2MVlreu3ADqftqjqwUvDy/OJzKFgxKeTQ+eeUf20FOTuHVkDON2iNa25rAXVYtWJCjw==",
             "requires": {
                 "@babel/helper-module-imports": "^7.12.13",
                 "@babel/plugin-syntax-jsx": "^7.12.13",
@@ -246,45 +196,15 @@
                 "stylis": "4.0.13"
             },
             "dependencies": {
-                "@babel/helper-module-imports": {
-                    "version": "7.16.7",
-                    "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz",
-                    "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==",
-                    "requires": {
-                        "@babel/types": "^7.16.7"
-                    }
-                },
-                "@babel/helper-validator-identifier": {
-                    "version": "7.16.7",
-                    "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
-                    "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw=="
-                },
-                "@babel/runtime": {
-                    "version": "7.17.2",
-                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz",
-                    "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==",
-                    "requires": {
-                        "regenerator-runtime": "^0.13.4"
-                    }
-                },
-                "@babel/types": {
-                    "version": "7.17.0",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz",
-                    "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==",
-                    "requires": {
-                        "@babel/helper-validator-identifier": "^7.16.7",
-                        "to-fast-properties": "^2.0.0"
-                    }
-                },
                 "@emotion/memoize": {
                     "version": "0.7.5",
                     "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz",
                     "integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ=="
                 },
                 "@emotion/serialize": {
-                    "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz",
-                    "integrity": "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==",
+                    "version": "1.0.3",
+                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.3.tgz",
+                    "integrity": "sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA==",
                     "requires": {
                         "@emotion/hash": "^0.8.0",
                         "@emotion/memoize": "^0.7.4",
@@ -299,19 +219,14 @@
                     "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ=="
                 },
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
+                    "version": "3.0.11",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
+                    "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
                 },
                 "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=="
-                },
-                "stylis": {
-                    "version": "4.0.13",
-                    "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz",
-                    "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
                 }
             }
         },
@@ -352,13 +267,13 @@
             }
         },
         "@emotion/css": {
-            "version": "11.7.1",
-            "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.7.1.tgz",
-            "integrity": "sha512-RUUgPlMZunlc7SE5A6Hg+VWRzb2cU6O9xlV78KCFgcnl25s7Qz/20oQg71iKudpLqk7xj0vhbJlwcJJMT0BOZg==",
+            "version": "11.9.0",
+            "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.9.0.tgz",
+            "integrity": "sha512-S9UjCxSrxEHawOLnWw4upTwfYKb0gVQdatHejn3W9kPyXxmKv3HmjVfJ84kDLmdX8jR20OuDQwaJ4Um24qD9vA==",
             "requires": {
                 "@emotion/babel-plugin": "^11.7.1",
                 "@emotion/cache": "^11.7.1",
-                "@emotion/serialize": "^1.0.0",
+                "@emotion/serialize": "^1.0.3",
                 "@emotion/sheet": "^1.0.3",
                 "@emotion/utils": "^1.0.0"
             },
@@ -376,9 +291,9 @@
                     }
                 },
                 "@emotion/serialize": {
-                    "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz",
-                    "integrity": "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==",
+                    "version": "1.0.3",
+                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.3.tgz",
+                    "integrity": "sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA==",
                     "requires": {
                         "@emotion/hash": "^0.8.0",
                         "@emotion/memoize": "^0.7.4",
@@ -398,14 +313,9 @@
                     "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ=="
                 },
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
-                },
-                "stylis": {
-                    "version": "4.0.13",
-                    "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz",
-                    "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
+                    "version": "3.0.11",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
+                    "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
                 }
             }
         },
@@ -415,11 +325,11 @@
             "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
         },
         "@emotion/is-prop-valid": {
-            "version": "0.8.8",
-            "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
-            "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.1.2.tgz",
+            "integrity": "sha512-3QnhqeL+WW88YjYbQL5gUIkthuMw7a0NGbZ7wfFVk2kg/CK5w8w5FFa0RzWjyY1+sujN0NWbtSHH6OJmWHtJpQ==",
             "requires": {
-                "@emotion/memoize": "0.7.4"
+                "@emotion/memoize": "^0.7.4"
             }
         },
         "@emotion/memoize": {
@@ -428,28 +338,19 @@
             "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw=="
         },
         "@emotion/react": {
-            "version": "11.8.1",
-            "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.8.1.tgz",
-            "integrity": "sha512-XGaie4nRxmtP1BZYBXqC5JGqMYF2KRKKI7vjqNvQxyRpekVAZhb6QqrElmZCAYXH1L90lAelADSVZC4PFsrJ8Q==",
+            "version": "11.9.0",
+            "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.9.0.tgz",
+            "integrity": "sha512-lBVSF5d0ceKtfKCDQJveNAtkC7ayxpVlgOohLgXqRwqWr9bOf4TZAFFyIcNngnV6xK6X4x2ZeXq7vliHkoVkxQ==",
             "requires": {
                 "@babel/runtime": "^7.13.10",
                 "@emotion/babel-plugin": "^11.7.1",
                 "@emotion/cache": "^11.7.1",
-                "@emotion/serialize": "^1.0.2",
-                "@emotion/sheet": "^1.1.0",
+                "@emotion/serialize": "^1.0.3",
                 "@emotion/utils": "^1.1.0",
                 "@emotion/weak-memoize": "^0.2.5",
                 "hoist-non-react-statics": "^3.3.1"
             },
             "dependencies": {
-                "@babel/runtime": {
-                    "version": "7.17.2",
-                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz",
-                    "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==",
-                    "requires": {
-                        "regenerator-runtime": "^0.13.4"
-                    }
-                },
                 "@emotion/cache": {
                     "version": "11.7.1",
                     "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.7.1.tgz",
@@ -463,9 +364,9 @@
                     }
                 },
                 "@emotion/serialize": {
-                    "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz",
-                    "integrity": "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==",
+                    "version": "1.0.3",
+                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.3.tgz",
+                    "integrity": "sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA==",
                     "requires": {
                         "@emotion/hash": "^0.8.0",
                         "@emotion/memoize": "^0.7.4",
@@ -485,14 +386,9 @@
                     "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ=="
                 },
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
-                },
-                "stylis": {
-                    "version": "4.0.13",
-                    "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz",
-                    "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
+                    "version": "3.0.11",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
+                    "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
                 }
             }
         },
@@ -525,26 +421,10 @@
                 "@emotion/utils": "^1.1.0"
             },
             "dependencies": {
-                "@babel/runtime": {
-                    "version": "7.17.2",
-                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz",
-                    "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==",
-                    "requires": {
-                        "regenerator-runtime": "^0.13.4"
-                    }
-                },
-                "@emotion/is-prop-valid": {
-                    "version": "1.1.2",
-                    "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.1.2.tgz",
-                    "integrity": "sha512-3QnhqeL+WW88YjYbQL5gUIkthuMw7a0NGbZ7wfFVk2kg/CK5w8w5FFa0RzWjyY1+sujN0NWbtSHH6OJmWHtJpQ==",
-                    "requires": {
-                        "@emotion/memoize": "^0.7.4"
-                    }
-                },
                 "@emotion/serialize": {
-                    "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz",
-                    "integrity": "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==",
+                    "version": "1.0.3",
+                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.3.tgz",
+                    "integrity": "sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA==",
                     "requires": {
                         "@emotion/hash": "^0.8.0",
                         "@emotion/memoize": "^0.7.4",
@@ -559,9 +439,9 @@
                     "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ=="
                 },
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
+                    "version": "3.0.11",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
+                    "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
                 }
             }
         },
@@ -644,56 +524,29 @@
             }
         },
         "@fortawesome/react-fontawesome": {
-            "version": "0.1.17",
-            "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.17.tgz",
-            "integrity": "sha512-dX43Z5IvMaW7fwzU8farosYjKNGfRb2HB/DgjVBHeJZ/NSnuuaujPPx0YOdcAq+n3mqn70tyCde2HM1mqbhiuw==",
+            "version": "0.1.18",
+            "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.18.tgz",
+            "integrity": "sha512-RwLIB4TZw0M9gvy5u+TusAA0afbwM4JQIimNH/j3ygd6aIvYPQLqXMhC9ErY26J23rDPyDZldIfPq/HpTTJ/tQ==",
             "requires": {
                 "prop-types": "^15.8.1"
-            },
-            "dependencies": {
-                "prop-types": {
-                    "version": "15.8.1",
-                    "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
-                    "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
-                    "requires": {
-                        "loose-envify": "^1.4.0",
-                        "object-assign": "^4.1.1",
-                        "react-is": "^16.13.1"
-                    }
-                }
             }
         },
         "@googlemaps/js-api-loader": {
-            "version": "1.12.8",
-            "resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.12.8.tgz",
-            "integrity": "sha512-h1RNVIJkHWL4UrdJo8fwECJwSRg8CSIfTEtPdzvThcji7tAPvVBDVBPzvPKhvl8e8mWEGPhnYOt6kPfSxJL+vQ==",
+            "version": "1.13.10",
+            "resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.13.10.tgz",
+            "integrity": "sha512-11AF8SdXca1+trN7kDYiPqwxcjQjet/e/A20PPR2hMHQIZ0ktxd4VsqbsSDLj1BZW1bke0FnZ4zY0KYmgWZ9cg==",
             "requires": {
                 "fast-deep-equal": "^3.1.3"
-            },
-            "dependencies": {
-                "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=="
-                }
             }
         },
         "@googlemaps/markerclusterer": {
-            "version": "1.0.12",
-            "resolved": "https://registry.npmjs.org/@googlemaps/markerclusterer/-/markerclusterer-1.0.12.tgz",
-            "integrity": "sha512-DSmN2w1ZoI+PBWfNCKYcr+zalP0uaaKIU08+UgebJYZ96X+J6CdUpD+xOVwBV1OJDiIXkneHquOZnT+V6dm+Sg==",
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/@googlemaps/markerclusterer/-/markerclusterer-2.0.2.tgz",
+            "integrity": "sha512-wApQwUZgxTDK69zkeNTZm6w5POEnpWPFOy+eRMRvgAdUCU7ky8siwoXbX3vChnCFHjVgIKLrC0YNjVCBJXLfLQ==",
             "requires": {
-                "@turf/clusters-dbscan": "^6.4.0",
-                "@turf/clusters-kmeans": "^6.4.0",
                 "fast-deep-equal": "^3.1.3",
+                "fast-equals": "^3.0.0",
                 "supercluster": "^7.1.3"
-            },
-            "dependencies": {
-                "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=="
-                }
             }
         },
         "@hig/flyout": {
@@ -717,9 +570,9 @@
             }
         },
         "@hig/theme-data": {
-            "version": "2.23.1",
-            "resolved": "https://registry.npmjs.org/@hig/theme-data/-/theme-data-2.23.1.tgz",
-            "integrity": "sha512-Yca1iCIs8U1dpkLW1VNiKOJW9fCJdb70f1dc61+R+HO1QJ8jMBu5eOpmQE1NKotJmcazhsXpo6xC11yV1crE4w==",
+            "version": "2.25.0",
+            "resolved": "https://registry.npmjs.org/@hig/theme-data/-/theme-data-2.25.0.tgz",
+            "integrity": "sha512-zjTY7NHVuA/h+PuaGFH7gvRlOMoGw0x8atroWnWoN/kLxAROqLjEJqfNcGT+iRCDapCarFwp2Q9GCecz1COz6g==",
             "requires": {
                 "tinycolor2": "^1.4.1"
             }
@@ -763,14 +616,14 @@
             "integrity": "sha512-6SJfx949YEWooh/CUPpJ+F491y4BYJmknz4hUN1+RHvKoUEynKbRmhnwbk/VLmh4OthLLDNCyWXfbh4DG1cTXA=="
         },
         "@mapbox/node-pre-gyp": {
-            "version": "1.0.8",
-            "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.8.tgz",
-            "integrity": "sha512-CMGKi28CF+qlbXh26hDe6NxCd7amqeAzEqnS6IHeO6LoaKyM/n+Xw3HT1COdq8cuioOdlKdqn/hCmqPUOMOywg==",
+            "version": "1.0.9",
+            "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz",
+            "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==",
             "requires": {
-                "detect-libc": "^1.0.3",
+                "detect-libc": "^2.0.0",
                 "https-proxy-agent": "^5.0.0",
                 "make-dir": "^3.1.0",
-                "node-fetch": "^2.6.5",
+                "node-fetch": "^2.6.7",
                 "nopt": "^5.0.0",
                 "npmlog": "^5.0.1",
                 "rimraf": "^3.0.2",
@@ -778,104 +631,6 @@
                 "tar": "^6.1.11"
             },
             "dependencies": {
-                "ansi-regex": {
-                    "version": "5.0.1",
-                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-                    "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
-                },
-                "are-we-there-yet": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
-                    "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
-                    "requires": {
-                        "delegates": "^1.0.0",
-                        "readable-stream": "^3.6.0"
-                    }
-                },
-                "chownr": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
-                    "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="
-                },
-                "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=="
-                },
-                "fs-minipass": {
-                    "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
-                    "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
-                    "requires": {
-                        "minipass": "^3.0.0"
-                    }
-                },
-                "gauge": {
-                    "version": "3.0.2",
-                    "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
-                    "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
-                    "requires": {
-                        "aproba": "^1.0.3 || ^2.0.0",
-                        "color-support": "^1.1.2",
-                        "console-control-strings": "^1.0.0",
-                        "has-unicode": "^2.0.1",
-                        "object-assign": "^4.1.1",
-                        "signal-exit": "^3.0.0",
-                        "string-width": "^4.2.3",
-                        "strip-ansi": "^6.0.1",
-                        "wide-align": "^1.1.2"
-                    }
-                },
-                "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=="
-                },
-                "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==",
-                    "requires": {
-                        "yallist": "^4.0.0"
-                    }
-                },
-                "make-dir": {
-                    "version": "3.1.0",
-                    "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
-                    "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
-                    "requires": {
-                        "semver": "^6.0.0"
-                    },
-                    "dependencies": {
-                        "semver": {
-                            "version": "6.3.0",
-                            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-                            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
-                        }
-                    }
-                },
-                "minipass": {
-                    "version": "3.1.6",
-                    "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
-                    "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
-                    "requires": {
-                        "yallist": "^4.0.0"
-                    }
-                },
-                "minizlib": {
-                    "version": "2.1.2",
-                    "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
-                    "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
-                    "requires": {
-                        "minipass": "^3.0.0",
-                        "yallist": "^4.0.0"
-                    }
-                },
-                "mkdirp": {
-                    "version": "1.0.4",
-                    "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
-                    "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
-                },
                 "node-fetch": {
                     "version": "2.6.7",
                     "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
@@ -884,100 +639,26 @@
                         "whatwg-url": "^5.0.0"
                     }
                 },
-                "nopt": {
-                    "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
-                    "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
-                    "requires": {
-                        "abbrev": "1"
-                    }
-                },
-                "npmlog": {
-                    "version": "5.0.1",
-                    "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
-                    "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
-                    "requires": {
-                        "are-we-there-yet": "^2.0.0",
-                        "console-control-strings": "^1.1.0",
-                        "gauge": "^3.0.0",
-                        "set-blocking": "^2.0.0"
-                    }
-                },
                 "semver": {
-                    "version": "7.3.5",
-                    "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
-                    "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+                    "version": "7.3.7",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+                    "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
                     "requires": {
                         "lru-cache": "^6.0.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==",
-                    "requires": {
-                        "emoji-regex": "^8.0.0",
-                        "is-fullwidth-code-point": "^3.0.0",
-                        "strip-ansi": "^6.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==",
-                    "requires": {
-                        "ansi-regex": "^5.0.1"
-                    }
-                },
-                "tar": {
-                    "version": "6.1.11",
-                    "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
-                    "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
-                    "requires": {
-                        "chownr": "^2.0.0",
-                        "fs-minipass": "^2.0.0",
-                        "minipass": "^3.0.0",
-                        "minizlib": "^2.1.1",
-                        "mkdirp": "^1.0.3",
-                        "yallist": "^4.0.0"
-                    }
-                },
-                "tr46": {
-                    "version": "0.0.3",
-                    "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
-                    "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
-                },
-                "webidl-conversions": {
-                    "version": "3.0.1",
-                    "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
-                    "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
-                },
-                "whatwg-url": {
-                    "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
-                    "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
-                    "requires": {
-                        "tr46": "~0.0.3",
-                        "webidl-conversions": "^3.0.0"
-                    }
-                },
-                "yallist": {
-                    "version": "4.0.0",
-                    "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-                    "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
                 }
             }
         },
         "@material-ui/core": {
-            "version": "4.12.3",
-            "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.3.tgz",
-            "integrity": "sha512-sdpgI/PL56QVsEJldwEe4FFaFTLUqN+rd7sSZiRCdx2E/C7z5yK0y/khAWVBH24tXwto7I1hCzNWfJGZIYJKnw==",
+            "version": "4.12.4",
+            "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.4.tgz",
+            "integrity": "sha512-tr7xekNlM9LjA6pagJmL8QCgZXaubWUwkJnoYcMKd4gw/t4XiyvnTkjdGrUVicyB2BsdaAv1tvow45bPM4sSwQ==",
             "requires": {
                 "@babel/runtime": "^7.4.4",
-                "@material-ui/styles": "^4.11.4",
-                "@material-ui/system": "^4.12.1",
+                "@material-ui/styles": "^4.11.5",
+                "@material-ui/system": "^4.12.2",
                 "@material-ui/types": "5.1.0",
-                "@material-ui/utils": "^4.11.2",
+                "@material-ui/utils": "^4.11.3",
                 "@types/react-transition-group": "^4.2.0",
                 "clsx": "^1.0.4",
                 "hoist-non-react-statics": "^3.3.2",
@@ -988,9 +669,9 @@
             },
             "dependencies": {
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
+                    "version": "3.0.11",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
+                    "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
                 },
                 "dom-helpers": {
                     "version": "5.2.1",
@@ -1015,14 +696,14 @@
             }
         },
         "@material-ui/styles": {
-            "version": "4.11.4",
-            "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz",
-            "integrity": "sha512-KNTIZcnj/zprG5LW0Sao7zw+yG3O35pviHzejMdcSGCdWbiO8qzRgOYL8JAxAsWBKOKYwVZxXtHWaB5T2Kvxew==",
+            "version": "4.11.5",
+            "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.5.tgz",
+            "integrity": "sha512-o/41ot5JJiUsIETME9wVLAJrmIWL3j0R0Bj2kCOLbSfqEkKf0fmaPt+5vtblUh5eXr2S+J/8J3DaCb10+CzPGA==",
             "requires": {
                 "@babel/runtime": "^7.4.4",
                 "@emotion/hash": "^0.8.0",
                 "@material-ui/types": "5.1.0",
-                "@material-ui/utils": "^4.11.2",
+                "@material-ui/utils": "^4.11.3",
                 "clsx": "^1.0.4",
                 "csstype": "^2.5.2",
                 "hoist-non-react-statics": "^3.3.2",
@@ -1038,12 +719,12 @@
             }
         },
         "@material-ui/system": {
-            "version": "4.12.1",
-            "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.1.tgz",
-            "integrity": "sha512-lUdzs4q9kEXZGhbN7BptyiS1rLNHe6kG9o8Y307HCvF4sQxbCgpL2qi+gUk+yI8a2DNk48gISEQxoxpgph0xIw==",
+            "version": "4.12.2",
+            "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.2.tgz",
+            "integrity": "sha512-6CSKu2MtmiJgcCGf6nBQpM8fLkuB9F55EKfbdTC80NND5wpTmKzwdhLYLH3zL4cLlK0gVaaltW7/wMuyTnN0Lw==",
             "requires": {
                 "@babel/runtime": "^7.4.4",
-                "@material-ui/utils": "^4.11.2",
+                "@material-ui/utils": "^4.11.3",
                 "csstype": "^2.5.2",
                 "prop-types": "^15.7.2"
             }
@@ -1054,9 +735,9 @@
             "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A=="
         },
         "@material-ui/utils": {
-            "version": "4.11.2",
-            "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.2.tgz",
-            "integrity": "sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==",
+            "version": "4.11.3",
+            "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.3.tgz",
+            "integrity": "sha512-ZuQPV4rBK/V1j2dIkSSEcH5uT6AaHuKWFfotADHsC0wVL1NLd2WkFCm4ZZbX33iO4ydl6V0GPngKm8HZQ2oujg==",
             "requires": {
                 "@babel/runtime": "^7.4.4",
                 "prop-types": "^15.7.2",
@@ -1064,27 +745,34 @@
             }
         },
         "@react-google-maps/api": {
-            "version": "2.7.0",
-            "resolved": "https://registry.npmjs.org/@react-google-maps/api/-/api-2.7.0.tgz",
-            "integrity": "sha512-Fb/l7aR69ObYvzhpt1d1931454ylRkTPKF1C8GfLvXtg19wc36zTev2Afbahd+qAdyKuQyDdf5/SQyMjYBHI/A==",
-            "requires": {
-                "@googlemaps/js-api-loader": "1.12.8",
-                "@googlemaps/markerclusterer": "1.0.12",
-                "@react-google-maps/infobox": "2.6.0",
-                "@react-google-maps/marker-clusterer": "2.6.0",
-                "@types/google.maps": "3.46.1",
+            "version": "2.8.1",
+            "resolved": "https://registry.npmjs.org/@react-google-maps/api/-/api-2.8.1.tgz",
+            "integrity": "sha512-JH35zv21socmbkEi/xTbNiXO794mGCFHXtxNeNY77ZvP2BtCzj2oXFTwGCslUUb1YMb/Aahka7sk7YR1vBAWOA==",
+            "requires": {
+                "@googlemaps/js-api-loader": "1.13.10",
+                "@googlemaps/markerclusterer": "2.0.2",
+                "@react-google-maps/infobox": "2.8.0",
+                "@react-google-maps/marker-clusterer": "2.9.0",
+                "@types/google.maps": "3.48.3",
                 "invariant": "2.2.4"
             }
         },
         "@react-google-maps/infobox": {
-            "version": "2.6.0",
-            "resolved": "https://registry.npmjs.org/@react-google-maps/infobox/-/infobox-2.6.0.tgz",
-            "integrity": "sha512-2dXVZsuZ2PjelVg+slpUSYPnvoSIySwf4P/wScGijjqu6bpvhyX9AivitsF7zHfbwnZ0gAPX1Q8xtQhKgawkEg=="
+            "version": "2.8.0",
+            "resolved": "https://registry.npmjs.org/@react-google-maps/infobox/-/infobox-2.8.0.tgz",
+            "integrity": "sha512-OzLnJfPZnOJGRsS93Arq80ndLk7Etw07uyAqo5IPtS12Qs9rlm5+L3jDUdZKC3URlWEifHLeCykQbCVWHpA+pg=="
         },
         "@react-google-maps/marker-clusterer": {
-            "version": "2.6.0",
-            "resolved": "https://registry.npmjs.org/@react-google-maps/marker-clusterer/-/marker-clusterer-2.6.0.tgz",
-            "integrity": "sha512-EjeoCM+U/6W9qoGWqurcDbCubqTEDTFET7Jd3XcLHqTLvFAE473x2YbQg98mJXKNgPKcPTNEcTiYYGiIz9tEjA=="
+            "version": "2.9.0",
+            "resolved": "https://registry.npmjs.org/@react-google-maps/marker-clusterer/-/marker-clusterer-2.9.0.tgz",
+            "integrity": "sha512-BJJH2OXdUreVNdfTCuuO2oHoqBmXSnXtIQvbRYj3LwZ27nnzfY87D/KEUPXnCXj/56kEeVlBbvAbcKKeMRmkSw==",
+            "dependencies": {
+                "@typescript/lib-dom": {
+                    "version": "npm:@types/web@0.0.61",
+                    "resolved": "https://registry.npmjs.org/@types/web/-/web-0.0.61.tgz",
+                    "integrity": "sha512-lQ4M3OSh8eFj55fz1RJsLhCubET/7duOXoKcxVaUXYXyxikD9BA+WWrqAn5CjJxrc82b7zFY4OCVIeVdkPLaGg=="
+                }
+            }
         },
         "@react-three/fiber": {
             "version": "6.2.3",
@@ -1101,16 +789,6 @@
                 "use-asset": "^1.0.4",
                 "utility-types": "^3.10.0",
                 "zustand": "^3.5.1"
-            },
-            "dependencies": {
-                "@babel/runtime": {
-                    "version": "7.17.2",
-                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz",
-                    "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==",
-                    "requires": {
-                        "regenerator-runtime": "^0.13.4"
-                    }
-                }
             }
         },
         "@rkusa/linebreak": {
@@ -1126,12 +804,6 @@
             "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
             "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="
         },
-        "@socket.io/component-emitter": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.0.0.tgz",
-            "integrity": "sha512-2pTGuibAXJswAPJjaKisthqS/NOK5ypG4LYT6tEAV0S/mxW0zOIvYvGK0V8w8+SHxAm6vRMSjqSalFXeBAqs+Q==",
-            "dev": true
-        },
         "@szmarczak/http-timer": {
             "version": "5.0.1",
             "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz",
@@ -1140,68 +812,6 @@
                 "defer-to-connect": "^2.0.1"
             }
         },
-        "@turf/clone": {
-            "version": "6.5.0",
-            "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-6.5.0.tgz",
-            "integrity": "sha512-mzVtTFj/QycXOn6ig+annKrM6ZlimreKYz6f/GSERytOpgzodbQyOgkfwru100O1KQhhjSudKK4DsQ0oyi9cTw==",
-            "requires": {
-                "@turf/helpers": "^6.5.0"
-            }
-        },
-        "@turf/clusters-dbscan": {
-            "version": "6.5.0",
-            "resolved": "https://registry.npmjs.org/@turf/clusters-dbscan/-/clusters-dbscan-6.5.0.tgz",
-            "integrity": "sha512-SxZEE4kADU9DqLRiT53QZBBhu8EP9skviSyl+FGj08Y01xfICM/RR9ACUdM0aEQimhpu+ZpRVcUK+2jtiCGrYQ==",
-            "requires": {
-                "@turf/clone": "^6.5.0",
-                "@turf/distance": "^6.5.0",
-                "@turf/helpers": "^6.5.0",
-                "@turf/meta": "^6.5.0",
-                "density-clustering": "1.3.0"
-            }
-        },
-        "@turf/clusters-kmeans": {
-            "version": "6.5.0",
-            "resolved": "https://registry.npmjs.org/@turf/clusters-kmeans/-/clusters-kmeans-6.5.0.tgz",
-            "integrity": "sha512-DwacD5+YO8kwDPKaXwT9DV46tMBVNsbi1IzdajZu1JDSWoN7yc7N9Qt88oi+p30583O0UPVkAK+A10WAQv4mUw==",
-            "requires": {
-                "@turf/clone": "^6.5.0",
-                "@turf/helpers": "^6.5.0",
-                "@turf/invariant": "^6.5.0",
-                "@turf/meta": "^6.5.0",
-                "skmeans": "0.9.7"
-            }
-        },
-        "@turf/distance": {
-            "version": "6.5.0",
-            "resolved": "https://registry.npmjs.org/@turf/distance/-/distance-6.5.0.tgz",
-            "integrity": "sha512-xzykSLfoURec5qvQJcfifw/1mJa+5UwByZZ5TZ8iaqjGYN0vomhV9aiSLeYdUGtYRESZ+DYC/OzY+4RclZYgMg==",
-            "requires": {
-                "@turf/helpers": "^6.5.0",
-                "@turf/invariant": "^6.5.0"
-            }
-        },
-        "@turf/helpers": {
-            "version": "6.5.0",
-            "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-6.5.0.tgz",
-            "integrity": "sha512-VbI1dV5bLFzohYYdgqwikdMVpe7pJ9X3E+dlr425wa2/sMJqYDhTO++ec38/pcPvPE6oD9WEEeU3Xu3gza+VPw=="
-        },
-        "@turf/invariant": {
-            "version": "6.5.0",
-            "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-6.5.0.tgz",
-            "integrity": "sha512-Wv8PRNCtPD31UVbdJE/KVAWKe7l6US+lJItRR/HOEW3eh+U/JwRCSUl/KZ7bmjM/C+zLNoreM2TU6OoLACs4eg==",
-            "requires": {
-                "@turf/helpers": "^6.5.0"
-            }
-        },
-        "@turf/meta": {
-            "version": "6.5.0",
-            "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-6.5.0.tgz",
-            "integrity": "sha512-RrArvtsV0vdsCBegoBtOalgdSOfkBrTJ07VkpiCnq/491W67hnMWmDu7e6Ztw0C3WldRYTXkg3SumfdzZxLBHA==",
-            "requires": {
-                "@turf/helpers": "^6.5.0"
-            }
-        },
         "@types/adm-zip": {
             "version": "0.4.34",
             "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.4.34.tgz",
@@ -1238,14 +848,14 @@
             "dev": true
         },
         "@types/babel-types": {
-            "version": "7.0.7",
-            "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.7.tgz",
-            "integrity": "sha512-dBtBbrc+qTHy1WdfHYjBwRln4+LWqASWakLHsWHR2NWHIFkv4W3O070IGoGLEBrJBvct3r0L1BUPuvURi7kYUQ=="
+            "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.5",
-            "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.5.tgz",
-            "integrity": "sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w==",
+            "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": "*"
             }
@@ -1278,11 +888,18 @@
             }
         },
         "@types/bson": {
-            "version": "4.2.0",
-            "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.2.0.tgz",
-            "integrity": "sha512-ELCPqAdroMdcuxqwMgUpifQyRoTpyYCNr1V9xKyF40VsBobsj+BbWNRvwGchMgBPGqkw655ypkjj2MEF5ywVwg==",
+            "version": "4.0.5",
+            "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.5.tgz",
+            "integrity": "sha512-vVLwMUqhYJSQ/WKcE60eFqcyuWse5fGH+NMAXHuKrUAPoryq3ATxk5o4bgYNtg5aOM4APVg7Hnb3ASqUYG0PKg==",
             "requires": {
-                "bson": "*"
+                "@types/node": "*"
+            },
+            "dependencies": {
+                "@types/node": {
+                    "version": "17.0.25",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.25.tgz",
+                    "integrity": "sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w=="
+                }
             }
         },
         "@types/cacheable-request": {
@@ -1294,8 +911,15 @@
                 "@types/keyv": "*",
                 "@types/node": "*",
                 "@types/responselike": "*"
-            }
-        },
+            },
+            "dependencies": {
+                "@types/node": {
+                    "version": "17.0.25",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.25.tgz",
+                    "integrity": "sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w=="
+                }
+            }
+        },
         "@types/caseless": {
             "version": "0.12.2",
             "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
@@ -1303,9 +927,9 @@
             "dev": true
         },
         "@types/chai": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz",
-            "integrity": "sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw==",
+            "version": "4.3.1",
+            "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.1.tgz",
+            "integrity": "sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ==",
             "dev": true
         },
         "@types/color": {
@@ -1329,12 +953,13 @@
         "@types/color-name": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
-            "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
+            "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
+            "dev": true
         },
         "@types/connect": {
-            "version": "3.4.33",
-            "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz",
-            "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==",
+            "version": "3.4.35",
+            "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
+            "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
             "dev": true,
             "requires": {
                 "@types/node": "*"
@@ -1531,6 +1156,13 @@
             "requires": {
                 "@types/events": "*",
                 "@types/node": "*"
+            },
+            "dependencies": {
+                "@types/node": {
+                    "version": "17.0.25",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.25.tgz",
+                    "integrity": "sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w=="
+                }
             }
         },
         "@types/geojson": {
@@ -1566,9 +1198,9 @@
             }
         },
         "@types/google.maps": {
-            "version": "3.46.1",
-            "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.46.1.tgz",
-            "integrity": "sha512-GAa5ZWYgXG50yLXybb7A824esGm/L0LKHS7qD0qkP0IA/Qp5r922P9tmYcbCkGEf3Zgf7Ukbp7l08/IGIJuQwQ=="
+            "version": "3.48.3",
+            "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.48.3.tgz",
+            "integrity": "sha512-JQuLWAEXDorNfarQy22WbIezbPKhLnsTBnDw25vyg61USZLTK8KqE1glNyASKn2v2mUOcEIWFMNHX5hNzjuw/g=="
         },
         "@types/hoist-non-react-statics": {
             "version": "3.3.1",
@@ -1577,6 +1209,23 @@
             "requires": {
                 "@types/react": "*",
                 "hoist-non-react-statics": "^3.3.0"
+            },
+            "dependencies": {
+                "@types/react": {
+                    "version": "18.0.5",
+                    "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.5.tgz",
+                    "integrity": "sha512-UPxNGInDCIKlfqBrm8LDXYWNfLHwIdisWcsH5GpMyGjhEDLFgTtlRBaoWuCua9HcyuE0rMkmAeZ3FXV1pYLIYQ==",
+                    "requires": {
+                        "@types/prop-types": "*",
+                        "@types/scheduler": "*",
+                        "csstype": "^3.0.2"
+                    }
+                },
+                "csstype": {
+                    "version": "3.0.11",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
+                    "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
+                }
             }
         },
         "@types/html-minifier-terser": {
@@ -1606,12 +1255,24 @@
                 "@types/node": "*",
                 "@types/parse5": "*",
                 "@types/tough-cookie": "*"
+            },
+            "dependencies": {
+                "@types/node": {
+                    "version": "17.0.25",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.25.tgz",
+                    "integrity": "sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w=="
+                }
             }
         },
+        "@types/json-buffer": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/@types/json-buffer/-/json-buffer-3.0.0.tgz",
+            "integrity": "sha512-3YP80IxxFJB4b5tYC2SUPwkg0XQLiu0nWvhRgEatgjf+29IcWO9X1k8xRv5DGssJ/lCrjYTjQPcobJr2yWIVuQ=="
+        },
         "@types/json-schema": {
-            "version": "7.0.9",
-            "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
-            "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ=="
+            "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=="
         },
         "@types/keygrip": {
             "version": "1.0.2",
@@ -1620,11 +1281,18 @@
             "dev": true
         },
         "@types/keyv": {
-            "version": "3.1.3",
-            "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz",
-            "integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==",
+            "version": "3.1.4",
+            "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
+            "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
             "requires": {
                 "@types/node": "*"
+            },
+            "dependencies": {
+                "@types/node": {
+                    "version": "17.0.25",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.25.tgz",
+                    "integrity": "sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w=="
+                }
             }
         },
         "@types/libxmljs": {
@@ -1637,9 +1305,9 @@
             }
         },
         "@types/lodash": {
-            "version": "4.14.179",
-            "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.179.tgz",
-            "integrity": "sha512-uwc1x90yCKqGcIOAT6DwOSuxnrAbpkdPsUOZtwrXb4D/6wZs+6qG7QnIawDuZWg0sWpxl+ltIKCaLoMlna678w==",
+            "version": "4.14.182",
+            "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz",
+            "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==",
             "dev": true
         },
         "@types/mime": {
@@ -1676,6 +1344,13 @@
             "requires": {
                 "@types/bson": "*",
                 "@types/node": "*"
+            },
+            "dependencies": {
+                "@types/node": {
+                    "version": "17.0.25",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.25.tgz",
+                    "integrity": "sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w=="
+                }
             }
         },
         "@types/mongoose": {
@@ -1690,7 +1365,8 @@
         "@types/node": {
             "version": "10.17.60",
             "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz",
-            "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw=="
+            "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==",
+            "dev": true
         },
         "@types/nodemailer": {
             "version": "4.6.8",
@@ -1788,9 +1464,9 @@
             }
         },
         "@types/prop-types": {
-            "version": "15.7.4",
-            "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz",
-            "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ=="
+            "version": "15.7.5",
+            "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
+            "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
         },
         "@types/prosemirror-commands": {
             "version": "1.0.4",
@@ -1888,9 +1564,9 @@
             }
         },
         "@types/prosemirror-transform": {
-            "version": "1.1.5",
-            "resolved": "https://registry.npmjs.org/@types/prosemirror-transform/-/prosemirror-transform-1.1.5.tgz",
-            "integrity": "sha512-Wr2HXaEF4JPklWpC17RTxE6PxyU54Taqk5FMhK1ojgcN93J+GpkYW8s0mD3rl7KfTmlhVwZPCHE9o0cYf2Go5A==",
+            "version": "1.1.6",
+            "resolved": "https://registry.npmjs.org/@types/prosemirror-transform/-/prosemirror-transform-1.1.6.tgz",
+            "integrity": "sha512-7HwXOWc5vZQqIfEUUVAz13lPgBqAWJTv89qEpzAtBFB6hOszFmhsvQ02Jqe2LvKauAoJDa3Qpv/dbJAmgyiTuQ==",
             "dev": true,
             "requires": {
                 "@types/prosemirror-model": "*"
@@ -1929,9 +1605,10 @@
             }
         },
         "@types/react": {
-            "version": "16.14.23",
-            "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.23.tgz",
-            "integrity": "sha512-WngBZLuSkP4IAgPi0HOsGCHo6dn3CcuLQnCfC17VbA7YBgipZiZoTOhObwl/93DsFW0Y2a/ZXeonpW4DxirEJg==",
+            "version": "16.14.25",
+            "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.25.tgz",
+            "integrity": "sha512-cXRVHd7vBT5v1is72mmvmsg9stZrbJO04DJqFeh3Yj2tVKO6vmxg5BI+ybI6Ls7ROXRG3aFbZj9x0WA3ZAoDQw==",
+            "dev": true,
             "requires": {
                 "@types/prop-types": "*",
                 "@types/scheduler": "*",
@@ -1939,9 +1616,10 @@
             },
             "dependencies": {
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
+                    "version": "3.0.11",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
+                    "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==",
+                    "dev": true
                 }
             }
         },
@@ -2019,22 +1697,56 @@
             }
         },
         "@types/react-reconciler": {
-            "version": "0.26.4",
-            "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.26.4.tgz",
-            "integrity": "sha512-bdx4aIBkQRDAnzc23JBFeZmVpmfLJHfHikmQukEt9qs4bQtq9f+PDbNwhR9u74FkIUyIDz1I1qJ8OF6RwadKpw==",
+            "version": "0.26.6",
+            "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.26.6.tgz",
+            "integrity": "sha512-N8MpyC6PJksD+CbMaZ1GW1t940+L4K+f7soiNKcKfgOgof3xWLvs5nPRQ/Q0P6QwDX0GH1PT1MsiQh2FtUY6aw==",
             "requires": {
                 "@types/react": "*"
+            },
+            "dependencies": {
+                "@types/react": {
+                    "version": "18.0.5",
+                    "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.5.tgz",
+                    "integrity": "sha512-UPxNGInDCIKlfqBrm8LDXYWNfLHwIdisWcsH5GpMyGjhEDLFgTtlRBaoWuCua9HcyuE0rMkmAeZ3FXV1pYLIYQ==",
+                    "requires": {
+                        "@types/prop-types": "*",
+                        "@types/scheduler": "*",
+                        "csstype": "^3.0.2"
+                    }
+                },
+                "csstype": {
+                    "version": "3.0.11",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
+                    "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
+                }
             }
         },
         "@types/react-redux": {
-            "version": "7.1.22",
-            "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.22.tgz",
-            "integrity": "sha512-GxIA1kM7ClU73I6wg9IRTVwSO9GS+SAKZKe0Enj+82HMU6aoESFU2HNAdNi3+J53IaOHPiUfT3kSG4L828joDQ==",
+            "version": "7.1.24",
+            "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz",
+            "integrity": "sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ==",
             "requires": {
                 "@types/hoist-non-react-statics": "^3.3.0",
                 "@types/react": "*",
                 "hoist-non-react-statics": "^3.3.0",
                 "redux": "^4.0.0"
+            },
+            "dependencies": {
+                "@types/react": {
+                    "version": "18.0.5",
+                    "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.5.tgz",
+                    "integrity": "sha512-UPxNGInDCIKlfqBrm8LDXYWNfLHwIdisWcsH5GpMyGjhEDLFgTtlRBaoWuCua9HcyuE0rMkmAeZ3FXV1pYLIYQ==",
+                    "requires": {
+                        "@types/prop-types": "*",
+                        "@types/scheduler": "*",
+                        "csstype": "^3.0.2"
+                    }
+                },
+                "csstype": {
+                    "version": "3.0.11",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
+                    "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
+                }
             }
         },
         "@types/react-select": {
@@ -2054,6 +1766,23 @@
             "integrity": "sha512-fVQXjy/EYDbgraScgjDONA291McKqGrw0R0NeK639fx2bS4T19TnXMjg3FjOPlkI3qYTQtFTPADlRYysaQIMpA==",
             "requires": {
                 "@types/react": "*"
+            },
+            "dependencies": {
+                "@types/react": {
+                    "version": "18.0.5",
+                    "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.5.tgz",
+                    "integrity": "sha512-UPxNGInDCIKlfqBrm8LDXYWNfLHwIdisWcsH5GpMyGjhEDLFgTtlRBaoWuCua9HcyuE0rMkmAeZ3FXV1pYLIYQ==",
+                    "requires": {
+                        "@types/prop-types": "*",
+                        "@types/scheduler": "*",
+                        "csstype": "^3.0.2"
+                    }
+                },
+                "csstype": {
+                    "version": "3.0.11",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
+                    "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
+                }
             }
         },
         "@types/react-transition-group": {
@@ -2062,6 +1791,23 @@
             "integrity": "sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug==",
             "requires": {
                 "@types/react": "*"
+            },
+            "dependencies": {
+                "@types/react": {
+                    "version": "18.0.5",
+                    "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.5.tgz",
+                    "integrity": "sha512-UPxNGInDCIKlfqBrm8LDXYWNfLHwIdisWcsH5GpMyGjhEDLFgTtlRBaoWuCua9HcyuE0rMkmAeZ3FXV1pYLIYQ==",
+                    "requires": {
+                        "@types/prop-types": "*",
+                        "@types/scheduler": "*",
+                        "csstype": "^3.0.2"
+                    }
+                },
+                "csstype": {
+                    "version": "3.0.11",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
+                    "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
+                }
             }
         },
         "@types/reactcss": {
@@ -2083,6 +1829,19 @@
                 "@types/node": "*",
                 "@types/tough-cookie": "*",
                 "form-data": "^2.5.0"
+            },
+            "dependencies": {
+                "form-data": {
+                    "version": "2.5.1",
+                    "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
+                    "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
+                    "dev": true,
+                    "requires": {
+                        "asynckit": "^0.4.0",
+                        "combined-stream": "^1.0.6",
+                        "mime-types": "^2.1.12"
+                    }
+                }
             }
         },
         "@types/request-promise": {
@@ -2101,6 +1860,13 @@
             "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==",
             "requires": {
                 "@types/node": "*"
+            },
+            "dependencies": {
+                "@types/node": {
+                    "version": "17.0.25",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.25.tgz",
+                    "integrity": "sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w=="
+                }
             }
         },
         "@types/reveal": {
@@ -2222,9 +1988,9 @@
             "integrity": "sha512-6JqTgijtfXcTJik8NtiNxr2L90ex6ElM00qilOGeUcrEsJLOdzLJSIkXHUYS+KPAYQYtRJQKD6XaXds3HjS+gg=="
         },
         "@types/tough-cookie": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.1.tgz",
-            "integrity": "sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg=="
+            "version": "4.0.2",
+            "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz",
+            "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw=="
         },
         "@types/typescript": {
             "version": "2.0.0",
@@ -2236,9 +2002,9 @@
             }
         },
         "@types/uglify-js": {
-            "version": "3.13.1",
-            "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.1.tgz",
-            "integrity": "sha512-O3MmRAk6ZuAKa9CHgg0Pr0+lUOqoMLpc9AS4R8ano2auvsg7IE8syF3Xh/NPr26TWklxYcqoEEFdzLLs1fV9PQ==",
+            "version": "3.13.2",
+            "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.2.tgz",
+            "integrity": "sha512-/xFrPIo+4zOeNGtVMbf9rUm0N+i4pDf1ynExomqtokIJmVzR3962lJ1UE+MmexMkA0cmN9oTzg5Xcbwge0Ij2Q==",
             "dev": true,
             "requires": {
                 "source-map": "^0.6.1"
@@ -2310,14 +2076,6 @@
                 "@types/connect": "*",
                 "tapable": "^2.2.0",
                 "webpack": "^5"
-            },
-            "dependencies": {
-                "tapable": {
-                    "version": "2.2.1",
-                    "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
-                    "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
-                    "dev": true
-                }
             }
         },
         "@types/webpack-sources": {
@@ -2345,6 +2103,23 @@
             "integrity": "sha512-e1DZGD+eH19BnllTWCGXAdrMa2kI53wEMuhn/d+wUmnu8//ZI6BiuK/EPdw07fI4+tlyo5qdPZdXdpkoXHJVOw==",
             "requires": {
                 "@types/react": "*"
+            },
+            "dependencies": {
+                "@types/react": {
+                    "version": "18.0.5",
+                    "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.5.tgz",
+                    "integrity": "sha512-UPxNGInDCIKlfqBrm8LDXYWNfLHwIdisWcsH5GpMyGjhEDLFgTtlRBaoWuCua9HcyuE0rMkmAeZ3FXV1pYLIYQ==",
+                    "requires": {
+                        "@types/prop-types": "*",
+                        "@types/scheduler": "*",
+                        "csstype": "^3.0.2"
+                    }
+                },
+                "csstype": {
+                    "version": "3.0.11",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
+                    "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
+                }
             }
         },
         "@types/xregexp": {
@@ -2357,12 +2132,20 @@
             }
         },
         "@types/yauzl": {
-            "version": "2.9.1",
-            "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz",
-            "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==",
+            "version": "2.10.0",
+            "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz",
+            "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==",
             "optional": true,
             "requires": {
                 "@types/node": "*"
+            },
+            "dependencies": {
+                "@types/node": {
+                    "version": "17.0.25",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.25.tgz",
+                    "integrity": "sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w==",
+                    "optional": true
+                }
             }
         },
         "@types/youtube": {
@@ -2574,9 +2357,9 @@
             "integrity": "sha512-nQvrCBu7K2pSSEtIM0EEF03FVjcczCXInMt3moLNFbjlWx6bZrX72uT6/1uAXDbnzGUAx9gTyDiQ+vrFi663oA=="
         },
         "abab": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz",
-            "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==",
+            "version": "2.0.6",
+            "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
+            "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
             "dev": true
         },
         "abbrev": {
@@ -2599,27 +2382,12 @@
             "requires": {
                 "mime-types": "~2.1.34",
                 "negotiator": "0.6.3"
-            },
-            "dependencies": {
-                "mime-db": {
-                    "version": "1.51.0",
-                    "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
-                    "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
-                },
-                "mime-types": {
-                    "version": "2.1.34",
-                    "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
-                    "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
-                    "requires": {
-                        "mime-db": "1.51.0"
-                    }
-                }
             }
         },
         "acorn": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
-            "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo="
+            "version": "8.7.0",
+            "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
+            "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ=="
         },
         "acorn-globals": {
             "version": "3.1.0",
@@ -2664,27 +2432,32 @@
             "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8="
         },
         "agent-base": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz",
-            "integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==",
+            "version": "6.0.2",
+            "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+            "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
             "requires": {
                 "debug": "4"
             },
             "dependencies": {
                 "debug": {
-                    "version": "4.1.1",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+                    "version": "4.3.4",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+                    "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
                     "requires": {
-                        "ms": "^2.1.1"
+                        "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=="
                 }
             }
         },
         "ajv": {
-            "version": "6.12.2",
-            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
-            "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+            "version": "6.12.6",
+            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+            "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
             "requires": {
                 "fast-deep-equal": "^3.1.1",
                 "fast-json-stable-stringify": "^2.0.0",
@@ -2706,9 +2479,9 @@
             },
             "dependencies": {
                 "ajv": {
-                    "version": "8.10.0",
-                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz",
-                    "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==",
+                    "version": "8.11.0",
+                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
+                    "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
                     "requires": {
                         "fast-deep-equal": "^3.1.1",
                         "json-schema-traverse": "^1.0.0",
@@ -2724,9 +2497,9 @@
             }
         },
         "ajv-keywords": {
-            "version": "3.4.1",
-            "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
-            "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ=="
+            "version": "3.5.2",
+            "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+            "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ=="
         },
         "align-text": {
             "version": "0.1.4",
@@ -2793,9 +2566,9 @@
             "dev": true
         },
         "ansi-regex": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
-            "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz",
+            "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw=="
         },
         "ansi-styles": {
             "version": "3.2.1",
@@ -2830,9 +2603,9 @@
             }
         },
         "aproba": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
-            "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+            "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ=="
         },
         "archiver": {
             "version": "3.1.1",
@@ -2882,28 +2655,12 @@
             }
         },
         "are-we-there-yet": {
-            "version": "1.1.5",
-            "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
-            "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
+            "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
             "requires": {
                 "delegates": "^1.0.0",
-                "readable-stream": "^2.0.6"
-            },
-            "dependencies": {
-                "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"
-                    }
-                }
+                "readable-stream": "^3.6.0"
             }
         },
         "arg": {
@@ -2956,9 +2713,9 @@
             },
             "dependencies": {
                 "@types/node": {
-                    "version": "12.12.37",
-                    "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.37.tgz",
-                    "integrity": "sha512-4mXKoDptrXAwZErQHrLzpe0FN/0Wmf5JRniSVIdwUrtDf9wnmEV1teCNLBo/TwuXhkK/bVegoEn/wmb+x0AuPg=="
+                    "version": "12.20.48",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.48.tgz",
+                    "integrity": "sha512-4kxzqkrpwYtn6okJUcb2lfUu9ilnb3yhUOH6qX3nug8D2DupZ2drIkff2yJzYcNJVl3begnlcaBJ7tqiTTzjnQ=="
                 },
                 "glob": {
                     "version": "7.1.3",
@@ -2973,6 +2730,14 @@
                         "path-is-absolute": "^1.0.0"
                     }
                 },
+                "minimatch": {
+                    "version": "3.0.4",
+                    "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+                    "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+                    "requires": {
+                        "brace-expansion": "^1.1.7"
+                    }
+                },
                 "mocha": {
                     "version": "6.2.3",
                     "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz",
@@ -3088,9 +2853,9 @@
             "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
         },
         "async": {
-            "version": "2.6.3",
-            "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
-            "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+            "version": "2.6.4",
+            "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
+            "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
             "requires": {
                 "lodash": "^4.17.14"
             }
@@ -3140,6 +2905,25 @@
                 "mkdirp": "^0.5.1",
                 "source-map-support": "^0.5.3",
                 "webpack-log": "^1.2.0"
+            },
+            "dependencies": {
+                "enhanced-resolve": {
+                    "version": "4.5.0",
+                    "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz",
+                    "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==",
+                    "dev": true,
+                    "requires": {
+                        "graceful-fs": "^4.1.2",
+                        "memory-fs": "^0.5.0",
+                        "tapable": "^1.0.0"
+                    }
+                },
+                "tapable": {
+                    "version": "1.1.3",
+                    "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+                    "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
+                    "dev": true
+                }
             }
         },
         "aws-sign2": {
@@ -3158,29 +2942,6 @@
             "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
             "requires": {
                 "follow-redirects": "1.5.10"
-            },
-            "dependencies": {
-                "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"
-                    }
-                },
-                "follow-redirects": {
-                    "version": "1.5.10",
-                    "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
-                    "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
-                    "requires": {
-                        "debug": "=3.1.0"
-                    }
-                },
-                "ms": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
-                }
             }
         },
         "babel": {
@@ -3275,14 +3036,15 @@
             }
         },
         "babel-plugin-styled-components": {
-            "version": "1.10.7",
-            "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.10.7.tgz",
-            "integrity": "sha512-MBMHGcIA22996n9hZRf/UJLVVgkEOITuR2SvjHLb5dSTUyR4ZRGn+ngITapes36FI3WLxZHfRhkA1ffHxihOrg==",
+            "version": "2.0.7",
+            "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz",
+            "integrity": "sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==",
             "requires": {
-                "@babel/helper-annotate-as-pure": "^7.0.0",
-                "@babel/helper-module-imports": "^7.0.0",
+                "@babel/helper-annotate-as-pure": "^7.16.0",
+                "@babel/helper-module-imports": "^7.16.0",
                 "babel-plugin-syntax-jsx": "^6.18.0",
-                "lodash": "^4.17.11"
+                "lodash": "^4.17.11",
+                "picomatch": "^2.3.0"
             }
         },
         "babel-plugin-syntax-jsx": {
@@ -3340,9 +3102,9 @@
             "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
         },
         "balanced-match": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
-            "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+            "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
         },
         "base": {
             "version": "0.11.2",
@@ -3405,9 +3167,9 @@
             "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI="
         },
         "base64-js": {
-            "version": "1.3.1",
-            "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
-            "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
+            "version": "1.5.1",
+            "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+            "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
         },
         "base64id": {
             "version": "2.0.0",
@@ -3454,19 +3216,28 @@
             "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="
         },
         "bignumber.js": {
-            "version": "7.2.1",
-            "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz",
-            "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ=="
+            "version": "9.0.2",
+            "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz",
+            "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw=="
         },
         "binary-extensions": {
             "version": "1.13.1",
             "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
             "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw=="
         },
+        "bindings": {
+            "version": "1.5.0",
+            "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+            "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+            "optional": true,
+            "requires": {
+                "file-uri-to-path": "1.0.0"
+            }
+        },
         "bl": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.2.tgz",
-            "integrity": "sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ==",
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+            "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
             "requires": {
                 "buffer": "^5.5.0",
                 "inherits": "^2.0.4",
@@ -3497,20 +3268,22 @@
             "integrity": "sha512-6sTGh1OiUmuH8ftAYvUzALivoOmcnahinGmjZFI4puZVowXoKTn/bXtth7N1skW5AlezEOfjgFH4lNXHeNRQog=="
         },
         "body-parser": {
-            "version": "1.19.2",
-            "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz",
-            "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==",
+            "version": "1.20.0",
+            "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
+            "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==",
             "requires": {
                 "bytes": "3.1.2",
                 "content-type": "~1.0.4",
                 "debug": "2.6.9",
-                "depd": "~1.1.2",
-                "http-errors": "1.8.1",
+                "depd": "2.0.0",
+                "destroy": "1.2.0",
+                "http-errors": "2.0.0",
                 "iconv-lite": "0.4.24",
-                "on-finished": "~2.3.0",
-                "qs": "6.9.7",
-                "raw-body": "2.4.3",
-                "type-is": "~1.6.18"
+                "on-finished": "2.4.1",
+                "qs": "6.10.3",
+                "raw-body": "2.5.1",
+                "type-is": "~1.6.18",
+                "unpipe": "1.0.0"
             },
             "dependencies": {
                 "debug": {
@@ -3521,15 +3294,26 @@
                         "ms": "2.0.0"
                     }
                 },
+                "iconv-lite": {
+                    "version": "0.4.24",
+                    "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+                    "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+                    "requires": {
+                        "safer-buffer": ">= 2.1.2 < 3"
+                    }
+                },
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
                     "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
                 },
                 "qs": {
-                    "version": "6.9.7",
-                    "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz",
-                    "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw=="
+                    "version": "6.10.3",
+                    "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
+                    "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
+                    "requires": {
+                        "side-channel": "^1.0.4"
+                    }
                 }
             }
         },
@@ -3624,11 +3408,6 @@
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
-                },
-                "is-extendable": {
-                    "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-                    "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
                 }
             }
         },
@@ -3649,32 +3428,32 @@
             "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="
         },
         "browserslist": {
-            "version": "4.19.3",
-            "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz",
-            "integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==",
+            "version": "4.20.2",
+            "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz",
+            "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==",
             "requires": {
-                "caniuse-lite": "^1.0.30001312",
-                "electron-to-chromium": "^1.4.71",
+                "caniuse-lite": "^1.0.30001317",
+                "electron-to-chromium": "^1.4.84",
                 "escalade": "^3.1.1",
                 "node-releases": "^2.0.2",
                 "picocolors": "^1.0.0"
             }
         },
         "bson": {
-            "version": "4.6.1",
-            "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.1.tgz",
-            "integrity": "sha512-I1LQ7Hz5zgwR4QquilLNZwbhPw0Apx7i7X9kGMBTsqPdml/03Q9NBtD9nt/19ahjlphktQImrnderxqpzeVDjw==",
+            "version": "4.6.3",
+            "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.3.tgz",
+            "integrity": "sha512-rAqP5hcUVJhXP2MCSNVsf0oM2OGU1So6A9pVRDYayvJ5+hygXHQApf87wd5NlhPM1J9RJnbqxIG/f8QTzRoQ4A==",
             "requires": {
                 "buffer": "^5.6.0"
             }
         },
         "buffer": {
-            "version": "5.6.0",
-            "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz",
-            "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==",
+            "version": "5.7.1",
+            "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+            "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
             "requires": {
-                "base64-js": "^1.0.2",
-                "ieee754": "^1.1.4"
+                "base64-js": "^1.3.1",
+                "ieee754": "^1.1.13"
             }
         },
         "buffer-crc32": {
@@ -3688,9 +3467,9 @@
             "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
         },
         "buffer-from": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
-            "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
+            "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-indexof": {
             "version": "1.1.1",
@@ -3712,10 +3491,9 @@
             }
         },
         "builtin-modules": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
-            "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
-            "dev": true
+            "version": "3.2.0",
+            "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz",
+            "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA=="
         },
         "bytes": {
             "version": "3.1.2",
@@ -3743,6 +3521,12 @@
                 "y18n": "^4.0.0"
             },
             "dependencies": {
+                "chownr": {
+                    "version": "1.1.4",
+                    "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+                    "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+                    "dev": true
+                },
                 "lru-cache": {
                     "version": "4.1.5",
                     "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
@@ -3831,685 +3615,176 @@
         },
         "caller-callsite": {
             "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
-            "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
-            "requires": {
-                "callsites": "^2.0.0"
-            },
-            "dependencies": {
-                "callsites": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
-                    "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA="
-                }
-            }
-        },
-        "caller-path": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
-            "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
-            "requires": {
-                "caller-callsite": "^2.0.0"
-            }
-        },
-        "callsites": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
-            "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
-        },
-        "camel-case": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
-            "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
-            "requires": {
-                "pascal-case": "^3.1.2",
-                "tslib": "^2.0.3"
-            },
-            "dependencies": {
-                "tslib": {
-                    "version": "2.3.1",
-                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
-                    "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
-                }
-            }
-        },
-        "camelcase": {
-            "version": "5.3.1",
-            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
-            "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
-        },
-        "camelcase-keys": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
-            "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
-            "requires": {
-                "camelcase": "^2.0.0",
-                "map-obj": "^1.0.0"
-            },
-            "dependencies": {
-                "camelcase": {
-                    "version": "2.1.1",
-                    "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
-                    "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
-                }
-            }
-        },
-        "camelize": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
-            "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
-        },
-        "caniuse-lite": {
-            "version": "1.0.30001312",
-            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz",
-            "integrity": "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ=="
-        },
-        "canvas": {
-            "version": "2.9.0",
-            "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.9.0.tgz",
-            "integrity": "sha512-0l93g7uxp7rMyr7H+XRQ28A3ud0dKIUTIEkUe1Dxh4rjUYN7B93+SjC3r1PDKA18xcQN87OFGgUnyw7LSgNLSQ==",
-            "requires": {
-                "@mapbox/node-pre-gyp": "^1.0.0",
-                "nan": "^2.15.0",
-                "simple-get": "^3.0.3"
-            },
-            "dependencies": {
-                "nan": {
-                    "version": "2.15.0",
-                    "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
-                    "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
-                }
-            }
-        },
-        "capture-stack-trace": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz",
-            "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw=="
-        },
-        "caseless": {
-            "version": "0.12.0",
-            "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
-            "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
-        },
-        "center-align": {
-            "version": "0.1.3",
-            "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
-            "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
-            "requires": {
-                "align-text": "^0.1.3",
-                "lazy-cache": "^1.0.3"
-            }
-        },
-        "chai": {
-            "version": "4.3.6",
-            "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
-            "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
-            "requires": {
-                "assertion-error": "^1.1.0",
-                "check-error": "^1.0.2",
-                "deep-eql": "^3.0.1",
-                "get-func-name": "^2.0.0",
-                "loupe": "^2.3.1",
-                "pathval": "^1.1.1",
-                "type-detect": "^4.0.5"
-            }
-        },
-        "chain-function": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/chain-function/-/chain-function-1.0.1.tgz",
-            "integrity": "sha512-SxltgMwL9uCko5/ZCLiyG2B7R9fY4pDZUw7hJ4MhirdjBLosoDqkWABi3XMucddHdLiFJMb7PD2MZifZriuMTg=="
-        },
-        "chalk": {
-            "version": "2.4.2",
-            "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-            "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-            "requires": {
-                "ansi-styles": "^3.2.1",
-                "escape-string-regexp": "^1.0.5",
-                "supports-color": "^5.3.0"
-            }
-        },
-        "change-emitter": {
-            "version": "0.1.6",
-            "resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz",
-            "integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU="
-        },
-        "character-parser": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz",
-            "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=",
-            "requires": {
-                "is-regex": "^1.0.3"
-            }
-        },
-        "check-error": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
-            "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
-        },
-        "child_process": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz",
-            "integrity": "sha1-sffn/HPSXn/R1FWtyU4UODAYK1o="
-        },
-        "chokidar": {
-            "version": "2.1.8",
-            "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
-            "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
-            "requires": {
-                "anymatch": "^2.0.0",
-                "async-each": "^1.0.1",
-                "braces": "^2.3.2",
-                "fsevents": "^1.2.7",
-                "glob-parent": "^3.1.0",
-                "inherits": "^2.0.3",
-                "is-binary-path": "^1.0.0",
-                "is-glob": "^4.0.0",
-                "normalize-path": "^3.0.0",
-                "path-is-absolute": "^1.0.0",
-                "readdirp": "^2.2.1",
-                "upath": "^1.1.1"
-            },
-            "dependencies": {
-                "bindings": {
-                    "version": "1.5.0",
-                    "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
-                    "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
-                    "optional": true,
-                    "requires": {
-                        "file-uri-to-path": "1.0.0"
-                    }
-                },
-                "fsevents": {
-                    "version": "1.2.12",
-                    "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.12.tgz",
-                    "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==",
-                    "optional": true,
-                    "requires": {
-                        "bindings": "^1.5.0",
-                        "nan": "^2.12.1",
-                        "node-pre-gyp": "*"
-                    },
-                    "dependencies": {
-                        "abbrev": {
-                            "version": "1.1.1",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "ansi-regex": {
-                            "version": "2.1.1",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "aproba": {
-                            "version": "1.2.0",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "are-we-there-yet": {
-                            "version": "1.1.5",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "delegates": "^1.0.0",
-                                "readable-stream": "^2.0.6"
-                            }
-                        },
-                        "balanced-match": {
-                            "version": "1.0.0",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "brace-expansion": {
-                            "version": "1.1.11",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "balanced-match": "^1.0.0",
-                                "concat-map": "0.0.1"
-                            }
-                        },
-                        "chownr": {
-                            "version": "1.1.4",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "code-point-at": {
-                            "version": "1.1.0",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "concat-map": {
-                            "version": "0.0.1",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "console-control-strings": {
-                            "version": "1.1.0",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "core-util-is": {
-                            "version": "1.0.2",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "debug": {
-                            "version": "3.2.6",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "ms": "^2.1.1"
-                            }
-                        },
-                        "deep-extend": {
-                            "version": "0.6.0",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "delegates": {
-                            "version": "1.0.0",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "detect-libc": {
-                            "version": "1.0.3",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "fs-minipass": {
-                            "version": "1.2.7",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "minipass": "^2.6.0"
-                            }
-                        },
-                        "fs.realpath": {
-                            "version": "1.0.0",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "gauge": {
-                            "version": "2.7.4",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "aproba": "^1.0.3",
-                                "console-control-strings": "^1.0.0",
-                                "has-unicode": "^2.0.0",
-                                "object-assign": "^4.1.0",
-                                "signal-exit": "^3.0.0",
-                                "string-width": "^1.0.1",
-                                "strip-ansi": "^3.0.1",
-                                "wide-align": "^1.1.0"
-                            }
-                        },
-                        "glob": {
-                            "version": "7.1.6",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "fs.realpath": "^1.0.0",
-                                "inflight": "^1.0.4",
-                                "inherits": "2",
-                                "minimatch": "^3.0.4",
-                                "once": "^1.3.0",
-                                "path-is-absolute": "^1.0.0"
-                            }
-                        },
-                        "has-unicode": {
-                            "version": "2.0.1",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "iconv-lite": {
-                            "version": "0.4.24",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "safer-buffer": ">= 2.1.2 < 3"
-                            }
-                        },
-                        "ignore-walk": {
-                            "version": "3.0.3",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "minimatch": "^3.0.4"
-                            }
-                        },
-                        "inflight": {
-                            "version": "1.0.6",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "once": "^1.3.0",
-                                "wrappy": "1"
-                            }
-                        },
-                        "inherits": {
-                            "version": "2.0.4",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "ini": {
-                            "version": "1.3.5",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "is-fullwidth-code-point": {
-                            "version": "1.0.0",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "number-is-nan": "^1.0.0"
-                            }
-                        },
-                        "isarray": {
-                            "version": "1.0.0",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "minimatch": {
-                            "version": "3.0.4",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "brace-expansion": "^1.1.7"
-                            }
-                        },
-                        "minimist": {
-                            "version": "1.2.5",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "minipass": {
-                            "version": "2.9.0",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "safe-buffer": "^5.1.2",
-                                "yallist": "^3.0.0"
-                            }
-                        },
-                        "minizlib": {
-                            "version": "1.3.3",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "minipass": "^2.9.0"
-                            }
-                        },
-                        "mkdirp": {
-                            "version": "0.5.3",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "minimist": "^1.2.5"
-                            }
-                        },
-                        "ms": {
-                            "version": "2.1.2",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "needle": {
-                            "version": "2.3.3",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "debug": "^3.2.6",
-                                "iconv-lite": "^0.4.4",
-                                "sax": "^1.2.4"
-                            }
-                        },
-                        "node-pre-gyp": {
-                            "version": "0.14.0",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "detect-libc": "^1.0.2",
-                                "mkdirp": "^0.5.1",
-                                "needle": "^2.2.1",
-                                "nopt": "^4.0.1",
-                                "npm-packlist": "^1.1.6",
-                                "npmlog": "^4.0.2",
-                                "rc": "^1.2.7",
-                                "rimraf": "^2.6.1",
-                                "semver": "^5.3.0",
-                                "tar": "^4.4.2"
-                            }
-                        },
-                        "nopt": {
-                            "version": "4.0.3",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "abbrev": "1",
-                                "osenv": "^0.1.4"
-                            }
-                        },
-                        "npm-bundled": {
-                            "version": "1.1.1",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "npm-normalize-package-bin": "^1.0.1"
-                            }
-                        },
-                        "npm-normalize-package-bin": {
-                            "version": "1.0.1",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "npm-packlist": {
-                            "version": "1.4.8",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "ignore-walk": "^3.0.1",
-                                "npm-bundled": "^1.0.1",
-                                "npm-normalize-package-bin": "^1.0.1"
-                            }
-                        },
-                        "npmlog": {
-                            "version": "4.1.2",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "are-we-there-yet": "~1.1.2",
-                                "console-control-strings": "~1.1.0",
-                                "gauge": "~2.7.3",
-                                "set-blocking": "~2.0.0"
-                            }
-                        },
-                        "number-is-nan": {
-                            "version": "1.0.1",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "object-assign": {
-                            "version": "4.1.1",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "once": {
-                            "version": "1.4.0",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "wrappy": "1"
-                            }
-                        },
-                        "os-homedir": {
-                            "version": "1.0.2",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "os-tmpdir": {
-                            "version": "1.0.2",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "osenv": {
-                            "version": "0.1.5",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "os-homedir": "^1.0.0",
-                                "os-tmpdir": "^1.0.0"
-                            }
-                        },
-                        "path-is-absolute": {
-                            "version": "1.0.1",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "process-nextick-args": {
-                            "version": "2.0.1",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "rc": {
-                            "version": "1.2.8",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "deep-extend": "^0.6.0",
-                                "ini": "~1.3.0",
-                                "minimist": "^1.2.0",
-                                "strip-json-comments": "~2.0.1"
-                            }
-                        },
-                        "readable-stream": {
-                            "version": "2.3.7",
-                            "bundled": true,
-                            "optional": 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"
-                            }
-                        },
-                        "rimraf": {
-                            "version": "2.7.1",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "glob": "^7.1.3"
-                            }
-                        },
-                        "safe-buffer": {
-                            "version": "5.1.2",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "safer-buffer": {
-                            "version": "2.1.2",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "sax": {
-                            "version": "1.2.4",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "semver": {
-                            "version": "5.7.1",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "set-blocking": {
-                            "version": "2.0.0",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "signal-exit": {
-                            "version": "3.0.2",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "string-width": {
-                            "version": "1.0.2",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "code-point-at": "^1.0.0",
-                                "is-fullwidth-code-point": "^1.0.0",
-                                "strip-ansi": "^3.0.0"
-                            }
-                        },
-                        "string_decoder": {
-                            "version": "1.1.1",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "safe-buffer": "~5.1.0"
-                            }
-                        },
-                        "strip-ansi": {
-                            "version": "3.0.1",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "ansi-regex": "^2.0.0"
-                            }
-                        },
-                        "strip-json-comments": {
-                            "version": "2.0.1",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "tar": {
-                            "version": "4.4.13",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "chownr": "^1.1.1",
-                                "fs-minipass": "^1.2.5",
-                                "minipass": "^2.8.6",
-                                "minizlib": "^1.2.1",
-                                "mkdirp": "^0.5.0",
-                                "safe-buffer": "^5.1.2",
-                                "yallist": "^3.0.3"
-                            }
-                        },
-                        "util-deprecate": {
-                            "version": "1.0.2",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "wide-align": {
-                            "version": "1.1.3",
-                            "bundled": true,
-                            "optional": true,
-                            "requires": {
-                                "string-width": "^1.0.2 || 2"
-                            }
-                        },
-                        "wrappy": {
-                            "version": "1.0.2",
-                            "bundled": true,
-                            "optional": true
-                        },
-                        "yallist": {
-                            "version": "3.1.1",
-                            "bundled": true,
-                            "optional": true
-                        }
-                    }
+            "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
+            "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+            "requires": {
+                "callsites": "^2.0.0"
+            },
+            "dependencies": {
+                "callsites": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+                    "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA="
+                }
+            }
+        },
+        "caller-path": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
+            "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+            "requires": {
+                "caller-callsite": "^2.0.0"
+            }
+        },
+        "callsites": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+            "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
+        },
+        "camel-case": {
+            "version": "4.1.2",
+            "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
+            "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
+            "requires": {
+                "pascal-case": "^3.1.2",
+                "tslib": "^2.0.3"
+            }
+        },
+        "camelcase": {
+            "version": "5.3.1",
+            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+            "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
+        },
+        "camelcase-keys": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+            "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+            "requires": {
+                "camelcase": "^2.0.0",
+                "map-obj": "^1.0.0"
+            },
+            "dependencies": {
+                "camelcase": {
+                    "version": "2.1.1",
+                    "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+                    "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
                 }
             }
         },
+        "camelize": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
+            "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
+        },
+        "caniuse-lite": {
+            "version": "1.0.30001332",
+            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001332.tgz",
+            "integrity": "sha512-10T30NYOEQtN6C11YGg411yebhvpnC6Z102+B95eAsN0oB6KUs01ivE8u+G6FMIRtIrVlYXhL+LUwQ3/hXwDWw=="
+        },
+        "canvas": {
+            "version": "2.9.1",
+            "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.9.1.tgz",
+            "integrity": "sha512-vSQti1uG/2gjv3x6QLOZw7TctfufaerTWbVe+NSduHxxLGB+qf3kFgQ6n66DSnuoINtVUjrLLIK2R+lxrBG07A==",
+            "requires": {
+                "@mapbox/node-pre-gyp": "^1.0.0",
+                "nan": "^2.15.0",
+                "simple-get": "^3.0.3"
+            }
+        },
+        "capture-stack-trace": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz",
+            "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw=="
+        },
+        "caseless": {
+            "version": "0.12.0",
+            "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+            "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
+        },
+        "center-align": {
+            "version": "0.1.3",
+            "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
+            "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
+            "requires": {
+                "align-text": "^0.1.3",
+                "lazy-cache": "^1.0.3"
+            }
+        },
+        "chai": {
+            "version": "4.3.6",
+            "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
+            "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
+            "requires": {
+                "assertion-error": "^1.1.0",
+                "check-error": "^1.0.2",
+                "deep-eql": "^3.0.1",
+                "get-func-name": "^2.0.0",
+                "loupe": "^2.3.1",
+                "pathval": "^1.1.1",
+                "type-detect": "^4.0.5"
+            }
+        },
+        "chain-function": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/chain-function/-/chain-function-1.0.1.tgz",
+            "integrity": "sha512-SxltgMwL9uCko5/ZCLiyG2B7R9fY4pDZUw7hJ4MhirdjBLosoDqkWABi3XMucddHdLiFJMb7PD2MZifZriuMTg=="
+        },
+        "chalk": {
+            "version": "2.4.2",
+            "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+            "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+            "requires": {
+                "ansi-styles": "^3.2.1",
+                "escape-string-regexp": "^1.0.5",
+                "supports-color": "^5.3.0"
+            }
+        },
+        "change-emitter": {
+            "version": "0.1.6",
+            "resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz",
+            "integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU="
+        },
+        "character-parser": {
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz",
+            "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=",
+            "requires": {
+                "is-regex": "^1.0.3"
+            }
+        },
+        "check-error": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+            "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
+        },
+        "child_process": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz",
+            "integrity": "sha1-sffn/HPSXn/R1FWtyU4UODAYK1o="
+        },
+        "chokidar": {
+            "version": "2.1.8",
+            "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+            "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+            "requires": {
+                "anymatch": "^2.0.0",
+                "async-each": "^1.0.1",
+                "braces": "^2.3.2",
+                "fsevents": "^1.2.7",
+                "glob-parent": "^3.1.0",
+                "inherits": "^2.0.3",
+                "is-binary-path": "^1.0.0",
+                "is-glob": "^4.0.0",
+                "normalize-path": "^3.0.0",
+                "path-is-absolute": "^1.0.0",
+                "readdirp": "^2.2.1",
+                "upath": "^1.1.1"
+            }
+        },
         "chownr": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
-            "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+            "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="
         },
         "chrome": {
             "version": "0.1.0",
@@ -4563,14 +3838,14 @@
             }
         },
         "classnames": {
-            "version": "2.2.6",
-            "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
-            "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
+            "version": "2.3.1",
+            "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
+            "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA=="
         },
         "clean-css": {
-            "version": "4.2.3",
-            "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
-            "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==",
+            "version": "5.3.0",
+            "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz",
+            "integrity": "sha512-YYuuxv4H/iNb1Z/5IbMRoxgrzjWGhOEFfd+groZ5dMCVkpENiMZmwspdrzBo9286JjM1gZJPAyL7ZIdzuvu2AQ==",
             "requires": {
                 "source-map": "~0.6.0"
             },
@@ -4628,9 +3903,9 @@
             },
             "dependencies": {
                 "ansi-regex": {
-                    "version": "4.1.0",
-                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-                    "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+                    "version": "4.1.1",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+                    "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="
                 },
                 "string-width": {
                     "version": "3.1.0",
@@ -4772,9 +4047,9 @@
             }
         },
         "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=="
+            "version": "8.3.0",
+            "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+            "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="
         },
         "commondir": {
             "version": "1.0.1",
@@ -4797,6 +4072,15 @@
             "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
             "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM="
         },
+        "compress-brotli": {
+            "version": "1.3.6",
+            "resolved": "https://registry.npmjs.org/compress-brotli/-/compress-brotli-1.3.6.tgz",
+            "integrity": "sha512-au99/GqZtUtiCBliqLFbWlhnCxn+XSYjwZ77q6mKN4La4qOXDoLVPZ50iXr0WmAyMxl8yqoq3Yq4OeQNPPkyeQ==",
+            "requires": {
+                "@types/json-buffer": "~3.0.0",
+                "json-buffer": "~3.0.1"
+            }
+        },
         "compress-commons": {
             "version": "2.1.1",
             "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-2.1.1.tgz",
@@ -4904,16 +4188,31 @@
             }
         },
         "configstore": {
-            "version": "3.1.2",
-            "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz",
-            "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==",
+            "version": "3.1.5",
+            "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.5.tgz",
+            "integrity": "sha512-nlOhI4+fdzoK5xmJ+NY+1gZK56bwEaWZr8fYuXohZ9Vkc1o3a4T/R3M+yE/w7x/ZVJ1zF8c+oaOvF0dztdUgmA==",
             "requires": {
-                "dot-prop": "^4.1.0",
+                "dot-prop": "^4.2.1",
                 "graceful-fs": "^4.1.2",
                 "make-dir": "^1.0.0",
                 "unique-string": "^1.0.0",
                 "write-file-atomic": "^2.0.0",
                 "xdg-basedir": "^3.0.0"
+            },
+            "dependencies": {
+                "make-dir": {
+                    "version": "1.3.0",
+                    "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+                    "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+                    "requires": {
+                        "pify": "^3.0.0"
+                    }
+                },
+                "pify": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+                    "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
+                }
             }
         },
         "connect-flash": {
@@ -5070,13 +4369,6 @@
             "requires": {
                 "depd": "~2.0.0",
                 "keygrip": "~1.1.0"
-            },
-            "dependencies": {
-                "depd": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
-                    "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
-                }
             }
         },
         "copy-concurrently": {
@@ -5093,6 +4385,12 @@
                 "run-queue": "^1.0.0"
             },
             "dependencies": {
+                "aproba": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                    "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+                    "dev": true
+                },
                 "rimraf": {
                     "version": "2.7.1",
                     "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
@@ -5139,6 +4437,12 @@
                     "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
                     "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
                     "dev": true
+                },
+                "serialize-javascript": {
+                    "version": "1.9.1",
+                    "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz",
+                    "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==",
+                    "dev": true
                 }
             }
         },
@@ -5148,14 +4452,14 @@
             "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
         },
         "core-js-pure": {
-            "version": "3.21.1",
-            "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.1.tgz",
-            "integrity": "sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ=="
+            "version": "3.22.1",
+            "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.22.1.tgz",
+            "integrity": "sha512-TChjCtgcMDc8t12RiwAsThjqrS/VpBlEvDgL009ot4HESzBo3h2FSZNa6ZS1nWKZEPDoulnszxUll9n0/spflQ=="
         },
         "core-util-is": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
-            "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+            "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
         },
         "cors": {
             "version": "2.8.5",
@@ -5268,25 +4572,6 @@
                     "requires": {
                         "whatwg-url": "^5.0.0"
                     }
-                },
-                "tr46": {
-                    "version": "0.0.3",
-                    "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
-                    "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
-                },
-                "webidl-conversions": {
-                    "version": "3.0.1",
-                    "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
-                    "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
-                },
-                "whatwg-url": {
-                    "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
-                    "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
-                    "requires": {
-                        "tr46": "~0.0.3",
-                        "webidl-conversions": "^3.0.0"
-                    }
                 }
             }
         },
@@ -5359,37 +4644,24 @@
                 "postcss-modules-values": "^2.0.0",
                 "postcss-value-parser": "^3.3.0",
                 "schema-utils": "^1.0.0"
-            },
-            "dependencies": {
-                "schema-utils": {
-                    "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
-                    "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
-                    "dev": true,
-                    "requires": {
-                        "ajv": "^6.1.0",
-                        "ajv-errors": "^1.0.0",
-                        "ajv-keywords": "^3.1.0"
-                    }
-                }
             }
         },
         "css-select": {
-            "version": "4.2.1",
-            "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz",
-            "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==",
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
+            "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
             "requires": {
                 "boolbase": "^1.0.0",
-                "css-what": "^5.1.0",
-                "domhandler": "^4.3.0",
+                "css-what": "^6.0.1",
+                "domhandler": "^4.3.1",
                 "domutils": "^2.8.0",
                 "nth-check": "^2.0.1"
             },
             "dependencies": {
                 "dom-serializer": {
-                    "version": "1.3.2",
-                    "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
-                    "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
+                    "version": "1.4.1",
+                    "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
+                    "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
                     "requires": {
                         "domelementtype": "^2.0.1",
                         "domhandler": "^4.2.0",
@@ -5397,14 +4669,14 @@
                     }
                 },
                 "domelementtype": {
-                    "version": "2.2.0",
-                    "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
-                    "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
+                    "version": "2.3.0",
+                    "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+                    "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
                 },
                 "domhandler": {
-                    "version": "4.3.0",
-                    "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
-                    "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
+                    "version": "4.3.1",
+                    "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
+                    "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
                     "requires": {
                         "domelementtype": "^2.2.0"
                     }
@@ -5446,9 +4718,9 @@
             }
         },
         "css-what": {
-            "version": "5.1.0",
-            "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz",
-            "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw=="
+            "version": "6.1.0",
+            "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
+            "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw=="
         },
         "cssesc": {
             "version": "3.0.0",
@@ -5463,9 +4735,9 @@
             "dev": true
         },
         "cssstyle": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.2.0.tgz",
-            "integrity": "sha512-sEb3XFPx3jNnCAMtqrXPDeSgQr+jojtCeNf8cvMNMh1cG970+lljssvQDzPq6lmmJu2Vhqood/gtEomBiHOGnA==",
+            "version": "2.3.0",
+            "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz",
+            "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==",
             "dev": true,
             "requires": {
                 "cssom": "~0.3.6"
@@ -5480,9 +4752,9 @@
             }
         },
         "csstype": {
-            "version": "2.6.19",
-            "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.19.tgz",
-            "integrity": "sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ=="
+            "version": "2.6.20",
+            "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz",
+            "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA=="
         },
         "currently-unhandled": {
             "version": "0.4.1",
@@ -5504,9 +4776,12 @@
             "dev": true
         },
         "d3-array": {
-            "version": "1.2.4",
-            "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
-            "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
+            "version": "2.12.1",
+            "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
+            "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
+            "requires": {
+                "internmap": "^1.0.0"
+            }
         },
         "d3-axis": {
             "version": "2.1.0",
@@ -5565,16 +4840,6 @@
                 "d3-interpolate": "1.2.0 - 2",
                 "d3-time": "^2.1.1",
                 "d3-time-format": "2 - 3"
-            },
-            "dependencies": {
-                "d3-array": {
-                    "version": "2.12.1",
-                    "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
-                    "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
-                    "requires": {
-                        "internmap": "^1.0.0"
-                    }
-                }
             }
         },
         "d3-selection": {
@@ -5596,16 +4861,6 @@
             "integrity": "sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==",
             "requires": {
                 "d3-array": "2"
-            },
-            "dependencies": {
-                "d3-array": {
-                    "version": "2.12.1",
-                    "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
-                    "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
-                    "requires": {
-                        "internmap": "^1.0.0"
-                    }
-                }
             }
         },
         "d3-time-format": {
@@ -5662,6 +4917,34 @@
                 "abab": "^2.0.0",
                 "whatwg-mimetype": "^2.2.0",
                 "whatwg-url": "^7.0.0"
+            },
+            "dependencies": {
+                "tr46": {
+                    "version": "1.0.1",
+                    "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
+                    "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
+                    "dev": true,
+                    "requires": {
+                        "punycode": "^2.1.0"
+                    }
+                },
+                "webidl-conversions": {
+                    "version": "4.0.2",
+                    "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
+                    "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
+                    "dev": true
+                },
+                "whatwg-url": {
+                    "version": "7.1.0",
+                    "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
+                    "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
+                    "dev": true,
+                    "requires": {
+                        "lodash.sortby": "^4.7.0",
+                        "tr46": "^1.0.1",
+                        "webidl-conversions": "^4.0.2"
+                    }
+                }
             }
         },
         "date-fns": {
@@ -5732,9 +5015,9 @@
             "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
         },
         "deep-is": {
-            "version": "0.1.3",
-            "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
-            "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+            "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
         },
         "deepmerge": {
@@ -5797,11 +5080,12 @@
             "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg=="
         },
         "define-properties": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
-            "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
+            "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
             "requires": {
-                "object-keys": "^1.0.12"
+                "has-property-descriptors": "^1.0.0",
+                "object-keys": "^1.1.1"
             }
         },
         "define-property": {
@@ -5877,6 +5161,12 @@
                         }
                     }
                 },
+                "pify": {
+                    "version": "4.0.1",
+                    "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+                    "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+                    "dev": true
+                },
                 "rimraf": {
                     "version": "2.7.1",
                     "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
@@ -5903,11 +5193,6 @@
             "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz",
             "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw=="
         },
-        "density-clustering": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/density-clustering/-/density-clustering-1.3.0.tgz",
-            "integrity": "sha1-3J9ZyPCrl+FiSsZJMP0xlIF9ysU="
-        },
         "depcheck": {
             "version": "0.9.2",
             "resolved": "https://registry.npmjs.org/depcheck/-/depcheck-0.9.2.tgz",
@@ -5933,24 +5218,18 @@
             },
             "dependencies": {
                 "ansi-regex": {
-                    "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
-                    "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
+                    "version": "5.0.1",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+                    "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
                 },
                 "ansi-styles": {
-                    "version": "4.2.1",
-                    "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
-                    "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+                    "version": "4.3.0",
+                    "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+                    "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
                     "requires": {
-                        "@types/color-name": "^1.1.1",
                         "color-convert": "^2.0.1"
                     }
                 },
-                "builtin-modules": {
-                    "version": "3.1.0",
-                    "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz",
-                    "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw=="
-                },
                 "cliui": {
                     "version": "6.0.0",
                     "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
@@ -5986,11 +5265,11 @@
                     }
                 },
                 "debug": {
-                    "version": "4.1.1",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+                    "version": "4.3.4",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+                    "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
                     "requires": {
-                        "ms": "^2.1.1"
+                        "ms": "2.1.2"
                     }
                 },
                 "emoji-regex": {
@@ -6029,6 +5308,11 @@
                         "p-locate": "^4.1.0"
                     }
                 },
+                "ms": {
+                    "version": "2.1.2",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+                    "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+                },
                 "p-locate": {
                     "version": "4.1.0",
                     "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
@@ -6057,21 +5341,21 @@
                     "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
                 },
                 "string-width": {
-                    "version": "4.2.0",
-                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
-                    "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+                    "version": "4.2.3",
+                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+                    "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
                     "requires": {
                         "emoji-regex": "^8.0.0",
                         "is-fullwidth-code-point": "^3.0.0",
-                        "strip-ansi": "^6.0.0"
+                        "strip-ansi": "^6.0.1"
                     }
                 },
                 "strip-ansi": {
-                    "version": "6.0.0",
-                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
-                    "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+                    "version": "6.0.1",
+                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+                    "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
                     "requires": {
-                        "ansi-regex": "^5.0.0"
+                        "ansi-regex": "^5.0.1"
                     }
                 },
                 "wrap-ansi": {
@@ -6085,9 +5369,9 @@
                     }
                 },
                 "yargs": {
-                    "version": "15.3.1",
-                    "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz",
-                    "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==",
+                    "version": "15.4.1",
+                    "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+                    "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
                     "requires": {
                         "cliui": "^6.0.0",
                         "decamelize": "^1.2.0",
@@ -6099,7 +5383,7 @@
                         "string-width": "^4.2.0",
                         "which-module": "^2.0.0",
                         "y18n": "^4.0.0",
-                        "yargs-parser": "^18.1.1"
+                        "yargs-parser": "^18.1.2"
                     }
                 },
                 "yargs-parser": {
@@ -6114,9 +5398,9 @@
             }
         },
         "depd": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
-            "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+            "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
         },
         "deps-regex": {
             "version": "0.1.4",
@@ -6124,14 +5408,14 @@
             "integrity": "sha1-UYZnt2kUYKXn4KNBvnbrfOgJAYQ="
         },
         "destroy": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
-            "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+            "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
         },
         "detect-libc": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
-            "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
+            "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w=="
         },
         "detect-node": {
             "version": "2.1.0",
@@ -6231,14 +5515,14 @@
             },
             "dependencies": {
                 "domelementtype": {
-                    "version": "2.0.1",
-                    "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz",
-                    "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ=="
+                    "version": "2.3.0",
+                    "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+                    "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
                 },
                 "entities": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz",
-                    "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw=="
+                    "version": "2.2.0",
+                    "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
+                    "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
                 }
             }
         },
@@ -6254,6 +5538,14 @@
             "dev": true,
             "requires": {
                 "webidl-conversions": "^4.0.2"
+            },
+            "dependencies": {
+                "webidl-conversions": {
+                    "version": "4.0.2",
+                    "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
+                    "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
+                    "dev": true
+                }
             }
         },
         "domhandler": {
@@ -6280,19 +5572,12 @@
             "requires": {
                 "no-case": "^3.0.4",
                 "tslib": "^2.0.3"
-            },
-            "dependencies": {
-                "tslib": {
-                    "version": "2.3.1",
-                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
-                    "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
-                }
             }
         },
         "dot-prop": {
-            "version": "4.2.0",
-            "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
-            "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
+            "version": "4.2.1",
+            "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz",
+            "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==",
             "requires": {
                 "is-obj": "^1.0.0"
             }
@@ -6374,9 +5659,9 @@
             "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
         },
         "electron-to-chromium": {
-            "version": "1.4.75",
-            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.75.tgz",
-            "integrity": "sha512-LxgUNeu3BVU7sXaKjUDD9xivocQLxFtq6wgERrutdY/yIOps3ODOZExK1jg8DTEg4U8TUCb5MLGeWFOYuxjF3Q=="
+            "version": "1.4.116",
+            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.116.tgz",
+            "integrity": "sha512-sy2ol5DTH0sy8xvAglyHFxsNFXFsOBfa6rGmrtjiSdQOp53ossspduOzU+5Lx23H7GxEjjvtSF36XqkajV6Z5A=="
         },
         "emoji-regex": {
             "version": "7.0.3",
@@ -6403,11 +5688,11 @@
             "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
         },
         "encoding": {
-            "version": "0.1.12",
-            "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
-            "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
+            "version": "0.1.13",
+            "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
+            "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
             "requires": {
-                "iconv-lite": "~0.4.13"
+                "iconv-lite": "^0.6.2"
             }
         },
         "end-of-stream": {
@@ -6497,14 +5782,13 @@
             }
         },
         "enhanced-resolve": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz",
-            "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==",
+            "version": "5.9.3",
+            "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz",
+            "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==",
             "dev": true,
             "requires": {
-                "graceful-fs": "^4.1.2",
-                "memory-fs": "^0.5.0",
-                "tapable": "^1.0.0"
+                "graceful-fs": "^4.2.4",
+                "tapable": "^2.2.0"
             }
         },
         "entities": {
@@ -6518,17 +5802,17 @@
             "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw=="
         },
         "equation-editor-react": {
-            "version": "git+ssh://git@github.com/bobzel/equation-editor-react.git#75915e852b4b36a6a4cd3e1cbc80598da6b65227",
-            "from": "equation-editor-react@github:bobzel/equation-editor-react#useLocally",
+            "version": "github:bobzel/equation-editor-react#75915e852b4b36a6a4cd3e1cbc80598da6b65227",
+            "from": "github:bobzel/equation-editor-react#useLocally",
             "requires": {
                 "jquery": "^3.4.1",
                 "mathquill": "^0.10.1-a"
             }
         },
         "errno": {
-            "version": "0.1.7",
-            "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
-            "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+            "version": "0.1.8",
+            "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
+            "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
             "dev": true,
             "requires": {
                 "prr": "~1.0.1"
@@ -6543,21 +5827,43 @@
             }
         },
         "es-abstract": {
-            "version": "1.17.5",
-            "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
-            "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
+            "version": "1.19.5",
+            "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.5.tgz",
+            "integrity": "sha512-Aa2G2+Rd3b6kxEUKTF4TaW67czBLyAv3z7VOhYRU50YBx+bbsYZ9xQP4lMNazePuFlybXI0V4MruPos7qUo5fA==",
             "requires": {
+                "call-bind": "^1.0.2",
                 "es-to-primitive": "^1.2.1",
                 "function-bind": "^1.1.1",
+                "get-intrinsic": "^1.1.1",
+                "get-symbol-description": "^1.0.0",
                 "has": "^1.0.3",
-                "has-symbols": "^1.0.1",
-                "is-callable": "^1.1.5",
-                "is-regex": "^1.0.5",
-                "object-inspect": "^1.7.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.0",
-                "string.prototype.trimleft": "^2.1.1",
-                "string.prototype.trimright": "^2.1.1"
+                "object.assign": "^4.1.2",
+                "string.prototype.trimend": "^1.0.4",
+                "string.prototype.trimstart": "^1.0.4",
+                "unbox-primitive": "^1.0.1"
+            },
+            "dependencies": {
+                "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"
+                    }
+                }
             }
         },
         "es-module-lexer": {
@@ -6576,40 +5882,6 @@
                 "is-symbol": "^1.0.2"
             }
         },
-        "es5-ext": {
-            "version": "0.10.59",
-            "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.59.tgz",
-            "integrity": "sha512-cOgyhW0tIJyQY1Kfw6Kr0viu9ZlUctVchRMZ7R0HiH3dxTSp5zJDLecwxUqPUrGKMsgBI1wd1FL+d9Jxfi4cLw==",
-            "dev": true,
-            "requires": {
-                "es6-iterator": "^2.0.3",
-                "es6-symbol": "^3.1.3",
-                "next-tick": "^1.1.0"
-            }
-        },
-        "es6-iterator": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
-            "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
-            "dev": true,
-            "requires": {
-                "d": "1",
-                "es5-ext": "^0.10.35",
-                "es6-symbol": "^3.1.1"
-            },
-            "dependencies": {
-                "d": {
-                    "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
-                    "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
-                    "dev": true,
-                    "requires": {
-                        "es5-ext": "^0.10.50",
-                        "type": "^1.0.1"
-                    }
-                }
-            }
-        },
         "es6-promise": {
             "version": "3.2.1",
             "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz",
@@ -6621,20 +5893,7 @@
             "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
             "dev": true,
             "requires": {
-                "d": "^1.0.1",
                 "ext": "^1.1.2"
-            },
-            "dependencies": {
-                "d": {
-                    "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
-                    "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
-                    "dev": true,
-                    "requires": {
-                        "es5-ext": "^0.10.50",
-                        "type": "^1.0.1"
-                    }
-                }
             }
         },
         "escalade": {
@@ -6653,9 +5912,9 @@
             "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
         },
         "escodegen": {
-            "version": "1.14.1",
-            "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz",
-            "integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==",
+            "version": "1.14.3",
+            "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz",
+            "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==",
             "dev": true,
             "requires": {
                 "esprima": "^4.0.1",
@@ -6772,6 +6031,11 @@
                         "which": "^1.2.9"
                     }
                 },
+                "get-stream": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+                    "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
+                },
                 "lru-cache": {
                     "version": "4.1.5",
                     "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
@@ -6868,11 +6132,6 @@
                         "is-extendable": "^0.1.0"
                     }
                 },
-                "is-extendable": {
-                    "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-                    "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
-                },
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -6922,6 +6181,23 @@
                 "vary": "~1.1.2"
             },
             "dependencies": {
+                "body-parser": {
+                    "version": "1.19.2",
+                    "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz",
+                    "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==",
+                    "requires": {
+                        "bytes": "3.1.2",
+                        "content-type": "~1.0.4",
+                        "debug": "2.6.9",
+                        "depd": "~1.1.2",
+                        "http-errors": "1.8.1",
+                        "iconv-lite": "0.4.24",
+                        "on-finished": "~2.3.0",
+                        "qs": "6.9.7",
+                        "raw-body": "2.4.3",
+                        "type-is": "~1.6.18"
+                    }
+                },
                 "cookie": {
                     "version": "0.4.2",
                     "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
@@ -6935,20 +6211,69 @@
                         "ms": "2.0.0"
                     }
                 },
+                "depd": {
+                    "version": "1.1.2",
+                    "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+                    "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+                },
+                "http-errors": {
+                    "version": "1.8.1",
+                    "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
+                    "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
+                    "requires": {
+                        "depd": "~1.1.2",
+                        "inherits": "2.0.4",
+                        "setprototypeof": "1.2.0",
+                        "statuses": ">= 1.5.0 < 2",
+                        "toidentifier": "1.0.1"
+                    }
+                },
+                "iconv-lite": {
+                    "version": "0.4.24",
+                    "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+                    "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+                    "requires": {
+                        "safer-buffer": ">= 2.1.2 < 3"
+                    }
+                },
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
                     "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
                 },
+                "on-finished": {
+                    "version": "2.3.0",
+                    "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+                    "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+                    "requires": {
+                        "ee-first": "1.1.1"
+                    }
+                },
                 "qs": {
                     "version": "6.9.7",
                     "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz",
                     "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw=="
                 },
+                "raw-body": {
+                    "version": "2.4.3",
+                    "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz",
+                    "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==",
+                    "requires": {
+                        "bytes": "3.1.2",
+                        "http-errors": "1.8.1",
+                        "iconv-lite": "0.4.24",
+                        "unpipe": "1.0.0"
+                    }
+                },
                 "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=="
+                },
+                "statuses": {
+                    "version": "1.5.0",
+                    "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+                    "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
                 }
             }
         },
@@ -6983,11 +6308,6 @@
                         "ms": "2.0.0"
                     }
                 },
-                "depd": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
-                    "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
-                },
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -7015,18 +6335,18 @@
             "integrity": "sha1-IgMoRpoY31rWFeK3oM6ZXxf7ru8="
         },
         "ext": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz",
-            "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==",
+            "version": "1.6.0",
+            "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz",
+            "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==",
             "dev": true,
             "requires": {
-                "type": "^2.0.0"
+                "type": "^2.5.0"
             },
             "dependencies": {
                 "type": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz",
-                    "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==",
+                    "version": "2.6.0",
+                    "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz",
+                    "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==",
                     "dev": true
                 }
             }
@@ -7043,6 +6363,16 @@
             "requires": {
                 "assign-symbols": "^1.0.0",
                 "is-extendable": "^1.0.1"
+            },
+            "dependencies": {
+                "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"
+                    }
+                }
             }
         },
         "extglob": {
@@ -7101,11 +6431,6 @@
                         "is-data-descriptor": "^1.0.0",
                         "kind-of": "^6.0.2"
                     }
-                },
-                "is-extendable": {
-                    "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-                    "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
                 }
             }
         },
@@ -7121,20 +6446,25 @@
             },
             "dependencies": {
                 "debug": {
-                    "version": "4.1.1",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+                    "version": "4.3.4",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+                    "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
                     "requires": {
-                        "ms": "^2.1.1"
+                        "ms": "2.1.2"
                     }
                 },
                 "get-stream": {
-                    "version": "5.1.0",
-                    "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
-                    "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
+                    "version": "5.2.0",
+                    "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+                    "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
                     "requires": {
                         "pump": "^3.0.0"
                     }
+                },
+                "ms": {
+                    "version": "2.1.2",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+                    "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
                 }
             }
         },
@@ -7144,9 +6474,14 @@
             "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
         },
         "fast-deep-equal": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
-            "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA=="
+            "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=="
+        },
+        "fast-equals": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-3.0.1.tgz",
+            "integrity": "sha512-J9FxqqC9E/ja0C+SYhoG3Jl6pQuhP92HNcVC75xDEhB+GUzPnjEp3vMfPIxPprYZFfXS5hpVvvPCWUMiDSMS8Q=="
         },
         "fast-json-stable-stringify": {
             "version": "2.1.0",
@@ -7160,9 +6495,9 @@
             "dev": true
         },
         "fast-text-encoding": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.2.tgz",
-            "integrity": "sha512-5rQdinSsycpzvAoHga2EDn+LRX1d5xLFsuNG0Kg61JrAT/tASXcLL0nf/33v+sAxlQcfYmWbTURa1mmAf55jGw=="
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz",
+            "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig=="
         },
         "fastest-levenshtein": {
             "version": "1.0.12",
@@ -7179,9 +6514,9 @@
             }
         },
         "fbjs": {
-            "version": "0.8.17",
-            "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz",
-            "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=",
+            "version": "0.8.18",
+            "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.18.tgz",
+            "integrity": "sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA==",
             "requires": {
                 "core-js": "^1.0.0",
                 "isomorphic-fetch": "^2.1.1",
@@ -7189,7 +6524,7 @@
                 "object-assign": "^4.1.0",
                 "promise": "^7.1.1",
                 "setimmediate": "^1.0.5",
-                "ua-parser-js": "^0.7.18"
+                "ua-parser-js": "^0.7.30"
             }
         },
         "fd-slicer": {
@@ -7208,19 +6543,6 @@
             "requires": {
                 "loader-utils": "^1.0.2",
                 "schema-utils": "^1.0.0"
-            },
-            "dependencies": {
-                "schema-utils": {
-                    "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
-                    "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
-                    "dev": true,
-                    "requires": {
-                        "ajv": "^6.1.0",
-                        "ajv-errors": "^1.0.0",
-                        "ajv-keywords": "^3.1.0"
-                    }
-                }
             }
         },
         "file-saver": {
@@ -7252,11 +6574,6 @@
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
-                },
-                "is-extendable": {
-                    "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-                    "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
                 }
             }
         },
@@ -7291,6 +6608,19 @@
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
                     "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                },
+                "on-finished": {
+                    "version": "2.3.0",
+                    "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+                    "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+                    "requires": {
+                        "ee-first": "1.1.1"
+                    }
+                },
+                "statuses": {
+                    "version": "1.5.0",
+                    "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+                    "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
                 }
             }
         },
@@ -7311,6 +6641,75 @@
                 "commondir": "^1.0.1",
                 "make-dir": "^1.0.0",
                 "pkg-dir": "^2.0.0"
+            },
+            "dependencies": {
+                "find-up": {
+                    "version": "2.1.0",
+                    "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+                    "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+                    "dev": true,
+                    "requires": {
+                        "locate-path": "^2.0.0"
+                    }
+                },
+                "locate-path": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+                    "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+                    "dev": true,
+                    "requires": {
+                        "p-locate": "^2.0.0",
+                        "path-exists": "^3.0.0"
+                    }
+                },
+                "make-dir": {
+                    "version": "1.3.0",
+                    "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+                    "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+                    "dev": true,
+                    "requires": {
+                        "pify": "^3.0.0"
+                    }
+                },
+                "p-limit": {
+                    "version": "1.3.0",
+                    "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+                    "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+                    "dev": true,
+                    "requires": {
+                        "p-try": "^1.0.0"
+                    }
+                },
+                "p-locate": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+                    "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+                    "dev": true,
+                    "requires": {
+                        "p-limit": "^1.1.0"
+                    }
+                },
+                "p-try": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+                    "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+                    "dev": true
+                },
+                "pify": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+                    "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+                    "dev": true
+                },
+                "pkg-dir": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+                    "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+                    "dev": true,
+                    "requires": {
+                        "find-up": "^2.1.0"
+                    }
+                }
             }
         },
         "find-in-files": {
@@ -7323,9 +6722,9 @@
             }
         },
         "find-parent-dir": {
-            "version": "0.3.0",
-            "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz",
-            "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ="
+            "version": "0.3.1",
+            "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.1.tgz",
+            "integrity": "sha512-o4UcykWV/XN9wm+jMEtWLPlV8RXCZnMhQI6F6OdHeSez7iiJWePw8ijOlskJZMsaQoGR/b7dH6lO02HhaTN7+A=="
         },
         "find-root": {
             "version": "1.1.0",
@@ -7346,9 +6745,9 @@
             "integrity": "sha512-Md3b3ReA/qJwwYvKXeHpOV1fhPqwhJ9/29zc9lfi8ijyg00J0S9C7+5XMZDFhlDAKbwOvVgBxVIG1EHoMSC3vw=="
         },
         "flat": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz",
-            "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==",
+            "version": "4.1.1",
+            "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz",
+            "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==",
             "requires": {
                 "is-buffer": "~2.0.3"
             }
@@ -7395,9 +6794,27 @@
             }
         },
         "follow-redirects": {
-            "version": "1.12.1",
-            "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.12.1.tgz",
-            "integrity": "sha512-tmRv0AVuR7ZyouUHLeNSiO6pqulF7dYa3s19c6t+wz9LD69/uSzdMxJ2S91nTI9U3rt/IldxpzMOFejp6f0hjg=="
+            "version": "1.5.10",
+            "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
+            "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
+            "requires": {
+                "debug": "=3.1.0"
+            },
+            "dependencies": {
+                "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"
+                    }
+                },
+                "ms": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                }
+            }
         },
         "for-each-property": {
             "version": "0.0.4",
@@ -7444,13 +6861,20 @@
                 "semver": "^5.6.0",
                 "tapable": "^1.0.0",
                 "worker-rpc": "^0.1.0"
+            },
+            "dependencies": {
+                "tapable": {
+                    "version": "1.1.3",
+                    "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+                    "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
+                    "dev": true
+                }
             }
         },
         "form-data": {
-            "version": "2.5.1",
-            "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
-            "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
-            "dev": true,
+            "version": "2.3.3",
+            "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+            "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
             "requires": {
                 "asynckit": "^0.4.0",
                 "combined-stream": "^1.0.6",
@@ -7517,6 +6941,36 @@
             "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
             "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
         },
+        "fs-extra": {
+            "version": "0.26.7",
+            "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz",
+            "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=",
+            "requires": {
+                "graceful-fs": "^4.1.2",
+                "jsonfile": "^2.1.0",
+                "klaw": "^1.0.0",
+                "path-is-absolute": "^1.0.0",
+                "rimraf": "^2.2.8"
+            },
+            "dependencies": {
+                "rimraf": {
+                    "version": "2.7.1",
+                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+                    "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+                    "requires": {
+                        "glob": "^7.1.3"
+                    }
+                }
+            }
+        },
+        "fs-minipass": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+            "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+            "requires": {
+                "minipass": "^3.0.0"
+            }
+        },
         "fs-monkey": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz",
@@ -7557,11 +7011,14 @@
             "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
         },
         "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
+            "version": "1.2.13",
+            "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+            "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+            "optional": true,
+            "requires": {
+                "bindings": "^1.5.0",
+                "nan": "^2.12.1"
+            }
         },
         "fstream": {
             "version": "1.0.12",
@@ -7607,50 +7064,58 @@
                 "interval-arithmetic-eval": "^0.4.7"
             }
         },
+        "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=="
+        },
         "gauge": {
-            "version": "2.7.4",
-            "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
-            "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
+            "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
             "requires": {
-                "aproba": "^1.0.3",
+                "aproba": "^1.0.3 || ^2.0.0",
+                "color-support": "^1.1.2",
                 "console-control-strings": "^1.0.0",
-                "has-unicode": "^2.0.0",
-                "object-assign": "^4.1.0",
+                "has-unicode": "^2.0.1",
+                "object-assign": "^4.1.1",
                 "signal-exit": "^3.0.0",
-                "string-width": "^1.0.1",
-                "strip-ansi": "^3.0.1",
-                "wide-align": "^1.1.0"
+                "string-width": "^4.2.3",
+                "strip-ansi": "^6.0.1",
+                "wide-align": "^1.1.2"
             },
             "dependencies": {
                 "ansi-regex": {
-                    "version": "2.1.1",
-                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+                    "version": "5.0.1",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+                    "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+                },
+                "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=="
                 },
                 "is-fullwidth-code-point": {
-                    "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
-                    "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
-                    "requires": {
-                        "number-is-nan": "^1.0.0"
-                    }
+                    "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=="
                 },
                 "string-width": {
-                    "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
-                    "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+                    "version": "4.2.3",
+                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+                    "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
                     "requires": {
-                        "code-point-at": "^1.0.0",
-                        "is-fullwidth-code-point": "^1.0.0",
-                        "strip-ansi": "^3.0.0"
+                        "emoji-regex": "^8.0.0",
+                        "is-fullwidth-code-point": "^3.0.0",
+                        "strip-ansi": "^6.0.1"
                     }
                 },
                 "strip-ansi": {
-                    "version": "3.0.1",
-                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-                    "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+                    "version": "6.0.1",
+                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+                    "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
                     "requires": {
-                        "ansi-regex": "^2.0.0"
+                        "ansi-regex": "^5.0.1"
                     }
                 }
             }
@@ -7668,14 +7133,17 @@
             },
             "dependencies": {
                 "is-stream": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
-                    "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw=="
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+                    "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="
                 },
                 "node-fetch": {
-                    "version": "2.6.0",
-                    "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
-                    "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
+                    "version": "2.6.7",
+                    "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+                    "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+                    "requires": {
+                        "whatwg-url": "^5.0.0"
+                    }
                 }
             }
         },
@@ -7732,9 +7200,9 @@
             "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="
         },
         "get-stream": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
-            "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+            "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="
         },
         "get-symbol-description": {
             "version": "1.0.0",
@@ -7764,9 +7232,9 @@
             "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4="
         },
         "glob": {
-            "version": "7.1.6",
-            "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
-            "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+            "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
             "requires": {
                 "fs.realpath": "^1.0.0",
                 "inflight": "^1.0.4",
@@ -7837,13 +7305,36 @@
             }
         },
         "globule": {
-            "version": "1.3.1",
-            "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.1.tgz",
-            "integrity": "sha512-OVyWOHgw29yosRHCHo7NncwR1hW5ew0W/UrvtwvjefVJeQ26q4/8r8FmPsSF1hJ93IgWkyv16pCTz6WblMzm/g==",
+            "version": "1.3.3",
+            "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.3.tgz",
+            "integrity": "sha512-mb1aYtDbIjTu4ShMB85m3UzjX9BVKe9WCzsnfMSZk+K5GpIbBOexgg4PPCt5eHDEG5/ZQAUX2Kct02zfiPLsKg==",
             "requires": {
                 "glob": "~7.1.1",
-                "lodash": "~4.17.12",
+                "lodash": "~4.17.10",
                 "minimatch": "~3.0.2"
+            },
+            "dependencies": {
+                "glob": {
+                    "version": "7.1.7",
+                    "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+                    "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+                    "requires": {
+                        "fs.realpath": "^1.0.0",
+                        "inflight": "^1.0.4",
+                        "inherits": "2",
+                        "minimatch": "^3.0.4",
+                        "once": "^1.3.0",
+                        "path-is-absolute": "^1.0.0"
+                    }
+                },
+                "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"
+                    }
+                }
             }
         },
         "golden-layout": {
@@ -7867,6 +7358,21 @@
                 "gtoken": "^3.0.0",
                 "jws": "^3.1.5",
                 "lru-cache": "^5.0.0"
+            },
+            "dependencies": {
+                "lru-cache": {
+                    "version": "5.1.1",
+                    "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+                    "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+                    "requires": {
+                        "yallist": "^3.0.2"
+                    }
+                },
+                "yallist": {
+                    "version": "3.1.1",
+                    "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+                    "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+                }
             }
         },
         "google-maps-react": {
@@ -7875,11 +7381,11 @@
             "integrity": "sha512-M8Eo9WndfQEfxcmm6yRq03qdJgw1x6rQmJ9DN+a+xPQ3K7yNDGkVDbinrf4/8vcox7nELbeopbm4bpefKewWfQ=="
         },
         "google-p12-pem": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.4.tgz",
-            "integrity": "sha512-S4blHBQWZRnEW44OcR7TL9WR+QCqByRvhNDZ/uuQfpxywfupikf/miba8js1jZi6ZOGv5slgSuoshCWh6EMDzg==",
+            "version": "2.0.5",
+            "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.5.tgz",
+            "integrity": "sha512-7RLkxwSsMsYh9wQ5Vb2zRtkAHvqPvfoMGag+nugl1noYO7gf0844Yr9TIFA5NEBMAeVt2Z+Imu7CQMp3oNatzQ==",
             "requires": {
-                "node-forge": "^0.9.0"
+                "node-forge": "^0.10.0"
             }
         },
         "googleapis": {
@@ -7905,9 +7411,12 @@
             },
             "dependencies": {
                 "qs": {
-                    "version": "6.9.3",
-                    "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz",
-                    "integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw=="
+                    "version": "6.10.3",
+                    "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
+                    "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
+                    "requires": {
+                        "side-channel": "^1.0.4"
+                    }
                 }
             }
         },
@@ -7922,11 +7431,11 @@
             }
         },
         "got": {
-            "version": "12.0.1",
-            "resolved": "https://registry.npmjs.org/got/-/got-12.0.1.tgz",
-            "integrity": "sha512-1Zhoh+lDej3t7Ks1BP/Jufn+rNqdiHQgUOcTxHzg2Dao1LQfp5S4Iq0T3iBxN4Zdo7QqCJL+WJUNzDX6rCP2Ew==",
+            "version": "12.0.3",
+            "resolved": "https://registry.npmjs.org/got/-/got-12.0.3.tgz",
+            "integrity": "sha512-hmdcXi/S0gcAtDg4P8j/rM7+j3o1Aq6bXhjxkDhRY2ipe7PHpvx/14DgTY2czHOLaGeU8VRvRecidwfu9qdFug==",
             "requires": {
-                "@sindresorhus/is": "^4.2.0",
+                "@sindresorhus/is": "^4.6.0",
                 "@szmarczak/http-timer": "^5.0.1",
                 "@types/cacheable-request": "^6.0.2",
                 "@types/responselike": "^1.0.0",
@@ -7935,7 +7444,7 @@
                 "decompress-response": "^6.0.0",
                 "form-data-encoder": "1.7.1",
                 "get-stream": "^6.0.1",
-                "http2-wrapper": "^2.1.9",
+                "http2-wrapper": "^2.1.10",
                 "lowercase-keys": "^3.0.0",
                 "p-cancelable": "^3.0.0",
                 "responselike": "^2.0.0"
@@ -7949,11 +7458,6 @@
                         "mimic-response": "^3.1.0"
                     }
                 },
-                "get-stream": {
-                    "version": "6.0.1",
-                    "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
-                    "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="
-                },
                 "mimic-response": {
                     "version": "3.1.0",
                     "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
@@ -7962,9 +7466,9 @@
             }
         },
         "graceful-fs": {
-            "version": "4.2.4",
-            "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
-            "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
+            "version": "4.2.10",
+            "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+            "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
         },
         "growl": {
             "version": "1.10.5",
@@ -7983,9 +7487,9 @@
             },
             "dependencies": {
                 "mime": {
-                    "version": "2.4.4",
-                    "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
-                    "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
+                    "version": "2.6.0",
+                    "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+                    "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg=="
                 }
             }
         },
@@ -8012,19 +7516,6 @@
             "requires": {
                 "ajv": "^6.12.3",
                 "har-schema": "^2.0.0"
-            },
-            "dependencies": {
-                "ajv": {
-                    "version": "6.12.6",
-                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
-                    "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
-                    "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"
-                    }
-                }
             }
         },
         "has": {
@@ -8051,9 +7542,9 @@
             }
         },
         "has-bigints": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
-            "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA=="
+            "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-binary2": {
             "version": "1.0.3",
@@ -8080,10 +7571,18 @@
             "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
             "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
         },
+        "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.1",
-            "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
-            "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
+            "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",
@@ -8091,13 +7590,6 @@
             "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
             "requires": {
                 "has-symbols": "^1.0.2"
-            },
-            "dependencies": {
-                "has-symbols": {
-                    "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
-                    "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
-                }
             }
         },
         "has-unicode": {
@@ -8153,9 +7645,9 @@
             }
         },
         "hosted-git-info": {
-            "version": "2.8.8",
-            "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
-            "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg=="
+            "version": "2.8.9",
+            "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+            "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="
         },
         "howler": {
             "version": "2.2.3",
@@ -8226,26 +7718,6 @@
                 "param-case": "^3.0.4",
                 "relateurl": "^0.2.7",
                 "terser": "^5.10.0"
-            },
-            "dependencies": {
-                "clean-css": {
-                    "version": "5.2.4",
-                    "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz",
-                    "integrity": "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==",
-                    "requires": {
-                        "source-map": "~0.6.0"
-                    }
-                },
-                "commander": {
-                    "version": "8.3.0",
-                    "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
-                    "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="
-                },
-                "source-map": {
-                    "version": "0.6.1",
-                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-                    "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
-                }
             }
         },
         "html-to-image": {
@@ -8274,13 +7746,6 @@
                 "lodash": "^4.17.21",
                 "pretty-error": "^4.0.0",
                 "tapable": "^2.0.0"
-            },
-            "dependencies": {
-                "tapable": {
-                    "version": "2.2.1",
-                    "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
-                    "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="
-                }
             }
         },
         "htmlparser2": {
@@ -8317,21 +7782,21 @@
             "dev": true
         },
         "http-errors": {
-            "version": "1.8.1",
-            "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
-            "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+            "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
             "requires": {
-                "depd": "~1.1.2",
+                "depd": "2.0.0",
                 "inherits": "2.0.4",
                 "setprototypeof": "1.2.0",
-                "statuses": ">= 1.5.0 < 2",
+                "statuses": "2.0.1",
                 "toidentifier": "1.0.1"
             }
         },
         "http-parser-js": {
-            "version": "0.5.5",
-            "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz",
-            "integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==",
+            "version": "0.5.6",
+            "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz",
+            "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==",
             "dev": true
         },
         "http-proxy": {
@@ -8387,21 +7852,26 @@
             "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
         },
         "https-proxy-agent": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
-            "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+            "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
             "requires": {
                 "agent-base": "6",
                 "debug": "4"
             },
             "dependencies": {
                 "debug": {
-                    "version": "4.1.1",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+                    "version": "4.3.4",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+                    "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
                     "requires": {
-                        "ms": "^2.1.1"
+                        "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=="
                 }
             }
         },
@@ -8416,9 +7886,9 @@
             "integrity": "sha512-xjxyDLbVDdLgjPnl4NM+Iu6il3UPmk6PNCBXruQKeuKDc/HtaZx1hk1AtMgw3vsn9YnLZRfoBpPxYMXcoT5KAA=="
         },
         "hyphenate-style-name": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz",
-            "integrity": "sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ=="
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
+            "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
         },
         "i": {
             "version": "0.3.7",
@@ -8426,11 +7896,11 @@
             "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q=="
         },
         "iconv-lite": {
-            "version": "0.4.24",
-            "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
-            "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+            "version": "0.6.3",
+            "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+            "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
             "requires": {
-                "safer-buffer": ">= 2.1.2 < 3"
+                "safer-buffer": ">= 2.1.2 < 3.0.0"
             }
         },
         "icss-replace-symbols": {
@@ -8449,9 +7919,9 @@
             }
         },
         "ieee754": {
-            "version": "1.1.13",
-            "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
-            "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
+            "version": "1.2.1",
+            "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+            "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
         },
         "iferr": {
             "version": "0.1.5",
@@ -8467,48 +7937,18 @@
         },
         "ignore-by-default": {
             "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
-            "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk="
-        },
-        "image-data-uri": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/image-data-uri/-/image-data-uri-2.0.1.tgz",
-            "integrity": "sha512-BZh721F2Q5TwBdwpiqrBrHEdj8daj8KuMZK/DOCyqQlz1CqFhhuZWbK5ZCUnAvFJr8LaKHTaWl9ja3/a3DC2Ew==",
-            "requires": {
-                "fs-extra": "^0.26.7",
-                "magicli": "0.0.8",
-                "mime-types": "^2.1.18",
-                "request": "^2.88.0"
-            },
-            "dependencies": {
-                "fs-extra": {
-                    "version": "0.26.7",
-                    "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz",
-                    "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=",
-                    "requires": {
-                        "graceful-fs": "^4.1.2",
-                        "jsonfile": "^2.1.0",
-                        "klaw": "^1.0.0",
-                        "path-is-absolute": "^1.0.0",
-                        "rimraf": "^2.2.8"
-                    }
-                },
-                "jsonfile": {
-                    "version": "2.4.0",
-                    "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
-                    "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
-                    "requires": {
-                        "graceful-fs": "^4.1.6"
-                    }
-                },
-                "rimraf": {
-                    "version": "2.7.1",
-                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-                    "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-                    "requires": {
-                        "glob": "^7.1.3"
-                    }
-                }
+            "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
+            "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk="
+        },
+        "image-data-uri": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/image-data-uri/-/image-data-uri-2.0.1.tgz",
+            "integrity": "sha512-BZh721F2Q5TwBdwpiqrBrHEdj8daj8KuMZK/DOCyqQlz1CqFhhuZWbK5ZCUnAvFJr8LaKHTaWl9ja3/a3DC2Ew==",
+            "requires": {
+                "fs-extra": "^0.26.7",
+                "magicli": "0.0.8",
+                "mime-types": "^2.1.18",
+                "request": "^2.88.0"
             }
         },
         "image-size": {
@@ -8521,14 +7961,13 @@
             "resolved": "https://registry.npmjs.org/image-size-stream/-/image-size-stream-1.1.0.tgz",
             "integrity": "sha1-Ivou2mbG31AQh0bacUkmSy0l+Gs=",
             "requires": {
-                "image-size": "github:netroy/image-size#da2c863807a3e9602617bdd357b0de3ab4a064c1",
                 "readable-stream": "^1.0.33",
                 "tryit": "^1.0.1"
             },
             "dependencies": {
                 "image-size": {
-                    "version": "github:netroy/image-size#da2c863807a3e9602617bdd357b0de3ab4a064c1",
-                    "from": "github:netroy/image-size#da2c863807a3e9602617bdd357b0de3ab4a064c1"
+                    "version": "git+https://github.com/netroy/image-size.git#da2c863807a3e9602617bdd357b0de3ab4a064c1",
+                    "from": "git+https://github.com/netroy/image-size.git#da2c863807a3e9602617bdd357b0de3ab4a064c1"
                 },
                 "isarray": {
                     "version": "0.0.1",
@@ -8573,24 +8012,12 @@
             "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM="
         },
         "import-local": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
-            "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
-            "dev": true,
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+            "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
             "requires": {
-                "pkg-dir": "^3.0.0",
-                "resolve-cwd": "^2.0.0"
-            },
-            "dependencies": {
-                "pkg-dir": {
-                    "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
-                    "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
-                    "dev": true,
-                    "requires": {
-                        "find-up": "^3.0.0"
-                    }
-                }
+                "pkg-dir": "^4.2.0",
+                "resolve-cwd": "^3.0.0"
             }
         },
         "imurmurhash": {
@@ -8611,12 +8038,6 @@
                 "repeating": "^2.0.0"
             }
         },
-        "indexes-of": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz",
-            "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=",
-            "dev": true
-        },
         "indexof": {
             "version": "0.0.1",
             "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
@@ -8652,9 +8073,9 @@
             "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
         },
         "ini": {
-            "version": "1.3.5",
-            "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
-            "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
+            "version": "1.3.8",
+            "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+            "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
         },
         "inline-style-prefixer": {
             "version": "3.0.8",
@@ -8692,6 +8113,11 @@
                 "unpack-string": "0.0.2"
             },
             "dependencies": {
+                "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=="
+                },
                 "magicli": {
                     "version": "0.0.5",
                     "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
@@ -8715,6 +8141,11 @@
                 "inspect-function": "^0.3.1"
             },
             "dependencies": {
+                "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=="
+                },
                 "inspect-function": {
                     "version": "0.3.4",
                     "resolved": "https://registry.npmjs.org/inspect-function/-/inspect-function-0.3.4.tgz",
@@ -8923,14 +8354,14 @@
             }
         },
         "is-buffer": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
-            "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A=="
+            "version": "2.0.5",
+            "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
+            "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ=="
         },
         "is-callable": {
-            "version": "1.1.5",
-            "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
-            "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q=="
+            "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-ci": {
             "version": "1.2.1",
@@ -8940,6 +8371,14 @@
                 "ci-info": "^1.5.0"
             }
         },
+        "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-data-descriptor": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
@@ -8964,9 +8403,12 @@
             }
         },
         "is-date-object": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
-            "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g=="
+            "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-descriptor": {
             "version": "0.1.6",
@@ -9007,12 +8449,9 @@
             }
         },
         "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"
-            }
+            "version": "0.1.1",
+            "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+            "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
         },
         "is-extglob": {
             "version": "2.1.1",
@@ -9038,9 +8477,9 @@
             }
         },
         "is-glob": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
-            "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+            "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"
             }
@@ -9093,9 +8532,9 @@
             }
         },
         "is-number-object": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz",
-            "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==",
+            "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"
             }
@@ -9158,11 +8597,12 @@
             "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ="
         },
         "is-regex": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
-            "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+            "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
             "requires": {
-                "has": "^1.0.3"
+                "call-bind": "^1.0.2",
+                "has-tostringtag": "^1.0.0"
             }
         },
         "is-retry-allowed": {
@@ -9179,9 +8619,12 @@
             }
         },
         "is-shared-array-buffer": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz",
-            "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA=="
+            "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-stream": {
             "version": "1.1.0",
@@ -9197,11 +8640,11 @@
             }
         },
         "is-symbol": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
-            "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
+            "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.1"
+                "has-symbols": "^1.0.2"
             }
         },
         "is-typed-array": {
@@ -9214,88 +8657,6 @@
                 "es-abstract": "^1.18.5",
                 "foreach": "^2.0.5",
                 "has-tostringtag": "^1.0.0"
-            },
-            "dependencies": {
-                "es-abstract": {
-                    "version": "1.19.1",
-                    "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz",
-                    "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==",
-                    "requires": {
-                        "call-bind": "^1.0.2",
-                        "es-to-primitive": "^1.2.1",
-                        "function-bind": "^1.1.1",
-                        "get-intrinsic": "^1.1.1",
-                        "get-symbol-description": "^1.0.0",
-                        "has": "^1.0.3",
-                        "has-symbols": "^1.0.2",
-                        "internal-slot": "^1.0.3",
-                        "is-callable": "^1.2.4",
-                        "is-negative-zero": "^2.0.1",
-                        "is-regex": "^1.1.4",
-                        "is-shared-array-buffer": "^1.0.1",
-                        "is-string": "^1.0.7",
-                        "is-weakref": "^1.0.1",
-                        "object-inspect": "^1.11.0",
-                        "object-keys": "^1.1.1",
-                        "object.assign": "^4.1.2",
-                        "string.prototype.trimend": "^1.0.4",
-                        "string.prototype.trimstart": "^1.0.4",
-                        "unbox-primitive": "^1.0.1"
-                    }
-                },
-                "has-symbols": {
-                    "version": "1.0.3",
-                    "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
-                    "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
-                },
-                "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-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"
-                    }
-                },
-                "object-inspect": {
-                    "version": "1.12.0",
-                    "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
-                    "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g=="
-                },
-                "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"
-                    }
-                },
-                "string.prototype.trimend": {
-                    "version": "1.0.4",
-                    "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
-                    "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
-                    "requires": {
-                        "call-bind": "^1.0.2",
-                        "define-properties": "^1.1.3"
-                    }
-                },
-                "string.prototype.trimstart": {
-                    "version": "1.0.4",
-                    "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
-                    "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
-                    "requires": {
-                        "call-bind": "^1.0.2",
-                        "define-properties": "^1.1.3"
-                    }
-                }
             }
         },
         "is-typedarray": {
@@ -9317,9 +8678,9 @@
             }
         },
         "is-what": {
-            "version": "3.10.0",
-            "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.10.0.tgz",
-            "integrity": "sha512-U4RYCXNOmATQHlOPlOCHCfXyKEFIPqvyaKDqYRuLbD6EYKcTTfc3YXkAYjzOVxO3zt34L+Wh2feIyWrYiZ7kng=="
+            "version": "3.14.1",
+            "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz",
+            "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA=="
         },
         "is-windows": {
             "version": "1.0.2",
@@ -9399,14 +8760,14 @@
             }
         },
         "jquery": {
-            "version": "3.5.1",
-            "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz",
-            "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg=="
+            "version": "3.6.0",
+            "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
+            "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
         },
         "js-base64": {
-            "version": "2.5.2",
-            "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.2.tgz",
-            "integrity": "sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ=="
+            "version": "2.6.4",
+            "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz",
+            "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ=="
         },
         "js-datepicker": {
             "version": "4.6.6",
@@ -9472,9 +8833,9 @@
             },
             "dependencies": {
                 "acorn": {
-                    "version": "7.1.1",
-                    "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz",
-                    "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==",
+                    "version": "7.4.1",
+                    "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+                    "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
                     "dev": true
                 },
                 "acorn-globals": {
@@ -9488,19 +8849,13 @@
                     },
                     "dependencies": {
                         "acorn": {
-                            "version": "6.4.1",
-                            "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
-                            "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
+                            "version": "6.4.2",
+                            "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
+                            "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==",
                             "dev": true
                         }
                     }
                 },
-                "parse5": {
-                    "version": "5.1.0",
-                    "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz",
-                    "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
-                    "dev": true
-                },
                 "tough-cookie": {
                     "version": "3.0.1",
                     "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz",
@@ -9511,6 +8866,32 @@
                         "psl": "^1.1.28",
                         "punycode": "^2.1.1"
                     }
+                },
+                "tr46": {
+                    "version": "1.0.1",
+                    "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
+                    "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
+                    "dev": true,
+                    "requires": {
+                        "punycode": "^2.1.0"
+                    }
+                },
+                "webidl-conversions": {
+                    "version": "4.0.2",
+                    "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
+                    "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
+                    "dev": true
+                },
+                "whatwg-url": {
+                    "version": "7.1.0",
+                    "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
+                    "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
+                    "dev": true,
+                    "requires": {
+                        "lodash.sortby": "^4.7.0",
+                        "tr46": "^1.0.1",
+                        "webidl-conversions": "^4.0.2"
+                    }
                 }
             }
         },
@@ -9520,11 +8901,11 @@
             "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="
         },
         "json-bigint": {
-            "version": "0.3.0",
-            "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.0.tgz",
-            "integrity": "sha1-DM2RLEuCcNBfBW+9E4FLU9OCWx4=",
+            "version": "0.3.1",
+            "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.1.tgz",
+            "integrity": "sha512-DGWnSzmusIreWlEupsUelHrhwmPPE+FiQvg+drKfk2p+bdEYa5mp4PJ8JsCWqae0M2jQNb0HPvnwvf1qOTThzQ==",
             "requires": {
-                "bignumber.js": "^7.0.0"
+                "bignumber.js": "^9.0.0"
             }
         },
         "json-buffer": {
@@ -9557,6 +8938,14 @@
             "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
             "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
         },
+        "json5": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+            "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+            "requires": {
+                "minimist": "^1.2.0"
+            }
+        },
         "jsondiffpatch": {
             "version": "0.4.1",
             "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.4.1.tgz",
@@ -9566,6 +8955,14 @@
                 "diff-match-patch": "^1.0.0"
             }
         },
+        "jsonfile": {
+            "version": "2.4.0",
+            "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+            "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
+            "requires": {
+                "graceful-fs": "^4.1.6"
+            }
+        },
         "jsonschema": {
             "version": "1.4.0",
             "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.0.tgz",
@@ -9594,9 +8991,9 @@
             },
             "dependencies": {
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
+                    "version": "3.0.11",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
+                    "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
                 }
             }
         },
@@ -9677,9 +9074,9 @@
             }
         },
         "jszip": {
-            "version": "3.7.1",
-            "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz",
-            "integrity": "sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==",
+            "version": "3.9.1",
+            "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.9.1.tgz",
+            "integrity": "sha512-H9A60xPqJ1CuC4Ka6qxzXZeU8aNmgOeP5IFqwJbQQwtu2EUYxota3LdsiZWplF7Wgd9tkAd0mdu36nceSaPuYw==",
             "requires": {
                 "lie": "~3.3.0",
                 "pako": "~1.0.2",
@@ -9733,9 +9130,9 @@
             "integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew=="
         },
         "keycode": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz",
-            "integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ="
+            "version": "2.2.1",
+            "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.1.tgz",
+            "integrity": "sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg=="
         },
         "keygrip": {
             "version": "1.1.0",
@@ -9746,10 +9143,11 @@
             }
         },
         "keyv": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.1.1.tgz",
-            "integrity": "sha512-tGv1yP6snQVDSM4X6yxrv2zzq/EvpW+oYiUz6aueW1u9CtS8RzUQYxxmFwgZlO2jSgCxQbchhxaqXXp2hnKGpQ==",
+            "version": "4.2.2",
+            "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.2.2.tgz",
+            "integrity": "sha512-uYS0vKTlBIjNCAUqrjlxmruxOEiZxZIHXyp32sdcGmP+ukFrmWUnE//RcPXJH3Vxrni1H2gsQbjHE0bH7MtMQQ==",
             "requires": {
+                "compress-brotli": "^1.3.6",
                 "json-buffer": "3.0.1"
             }
         },
@@ -9786,9 +9184,9 @@
             "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4="
         },
         "lazystream": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
-            "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=",
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz",
+            "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
             "requires": {
                 "readable-stream": "^2.0.5"
             },
@@ -9851,18 +9249,13 @@
                     "requires": {
                         "error-ex": "^1.2.0"
                     }
-                },
-                "pify": {
-                    "version": "2.3.0",
-                    "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-                    "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
                 }
             }
         },
         "loader-runner": {
-            "version": "4.2.0",
-            "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz",
-            "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==",
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
+            "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
             "dev": true
         },
         "loader-utils": {
@@ -9873,16 +9266,6 @@
                 "big.js": "^5.2.2",
                 "emojis-list": "^3.0.0",
                 "json5": "^1.0.1"
-            },
-            "dependencies": {
-                "json5": {
-                    "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
-                    "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
-                    "requires": {
-                        "minimist": "^1.2.0"
-                    }
-                }
             }
         },
         "locate-path": {
@@ -10002,9 +9385,9 @@
             }
         },
         "loglevel": {
-            "version": "1.6.8",
-            "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz",
-            "integrity": "sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA==",
+            "version": "1.8.0",
+            "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz",
+            "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==",
             "dev": true
         },
         "loglevelnext": {
@@ -10053,13 +9436,6 @@
             "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
             "requires": {
                 "tslib": "^2.0.3"
-            },
-            "dependencies": {
-                "tslib": {
-                    "version": "2.3.1",
-                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
-                    "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
-                }
             }
         },
         "lowercase-keys": {
@@ -10068,11 +9444,11 @@
             "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ=="
         },
         "lru-cache": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
-            "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+            "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
             "requires": {
-                "yallist": "^3.0.2"
+                "yallist": "^4.0.0"
             }
         },
         "magicli": {
@@ -10127,17 +9503,17 @@
             }
         },
         "make-dir": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
-            "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+            "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
             "requires": {
-                "pify": "^3.0.0"
+                "semver": "^6.0.0"
             },
             "dependencies": {
-                "pify": {
-                    "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-                    "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
+                "semver": {
+                    "version": "6.3.0",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+                    "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
                 }
             }
         },
@@ -10245,9 +9621,9 @@
             }
         },
         "memoize-one": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz",
-            "integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA=="
+            "version": "5.2.1",
+            "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
+            "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
         },
         "memory-fs": {
             "version": "0.5.0",
@@ -10359,16 +9735,16 @@
             "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
         },
         "mime-db": {
-            "version": "1.44.0",
-            "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
-            "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
+            "version": "1.52.0",
+            "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+            "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
         },
         "mime-types": {
-            "version": "2.1.27",
-            "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
-            "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
+            "version": "2.1.35",
+            "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+            "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
             "requires": {
-                "mime-db": "1.44.0"
+                "mime-db": "1.52.0"
             }
         },
         "mimic-fn": {
@@ -10388,17 +9764,34 @@
             "dev": true
         },
         "minimatch": {
-            "version": "3.0.4",
-            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-            "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+            "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.5",
-            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
-            "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+            "version": "1.2.6",
+            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+            "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
+        },
+        "minipass": {
+            "version": "3.1.6",
+            "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
+            "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
+            "requires": {
+                "yallist": "^4.0.0"
+            }
+        },
+        "minizlib": {
+            "version": "2.1.2",
+            "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+            "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+            "requires": {
+                "minipass": "^3.0.0",
+                "yallist": "^4.0.0"
+            }
         },
         "mississippi": {
             "version": "2.0.0",
@@ -10437,6 +9830,16 @@
             "requires": {
                 "for-in": "^1.0.2",
                 "is-extendable": "^1.0.1"
+            },
+            "dependencies": {
+                "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"
+                    }
+                }
             }
         },
         "mkdirp": {
@@ -10448,9 +9851,9 @@
             }
         },
         "mkdirp-classic": {
-            "version": "0.5.2",
-            "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.2.tgz",
-            "integrity": "sha512-ejdnDQcR75gwknmMw/tx02AuRs8jCtqFoFqDZMjiNxsu85sRIJVXDKHuLYvUUPRBUtV2FpSZa9bL1BUa3BdR2g=="
+            "version": "0.5.3",
+            "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+            "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
         },
         "mobile-detect": {
             "version": "1.4.5",
@@ -10535,6 +9938,15 @@
                     "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
                     "dev": true
                 },
+                "minimatch": {
+                    "version": "3.0.4",
+                    "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+                    "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+                    "dev": true,
+                    "requires": {
+                        "brace-expansion": "^1.1.7"
+                    }
+                },
                 "minimist": {
                     "version": "0.0.8",
                     "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
@@ -10594,14 +10006,6 @@
                     "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
                     "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg=="
                 },
-                "optional-require": {
-                    "version": "1.1.8",
-                    "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz",
-                    "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==",
-                    "requires": {
-                        "require-at": "^1.0.6"
-                    }
-                },
                 "readable-stream": {
                     "version": "2.3.7",
                     "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -10655,14 +10059,6 @@
                 "sliced": "1.0.1"
             },
             "dependencies": {
-                "@types/bson": {
-                    "version": "4.0.5",
-                    "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.5.tgz",
-                    "integrity": "sha512-vVLwMUqhYJSQ/WKcE60eFqcyuWse5fGH+NMAXHuKrUAPoryq3ATxk5o4bgYNtg5aOM4APVg7Hnb3ASqUYG0PKg==",
-                    "requires": {
-                        "@types/node": "*"
-                    }
-                },
                 "bson": {
                     "version": "1.1.6",
                     "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
@@ -10673,6 +10069,11 @@
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
                     "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
                 },
+                "optional-require": {
+                    "version": "1.0.3",
+                    "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz",
+                    "integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA=="
+                },
                 "safe-buffer": {
                     "version": "5.2.1",
                     "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -10699,6 +10100,12 @@
                 "run-queue": "^1.0.3"
             },
             "dependencies": {
+                "aproba": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                    "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+                    "dev": true
+                },
                 "rimraf": {
                     "version": "2.7.1",
                     "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
@@ -10774,9 +10181,9 @@
             "dev": true
         },
         "nan": {
-            "version": "2.14.1",
-            "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
-            "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw=="
+            "version": "2.15.0",
+            "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
+            "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
         },
         "nanoid": {
             "version": "2.1.11",
@@ -10817,9 +10224,9 @@
             "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
         },
         "neo-async": {
-            "version": "2.6.1",
-            "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
-            "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
+            "version": "2.6.2",
+            "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+            "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
             "dev": true
         },
         "next-tick": {
@@ -10848,19 +10255,12 @@
             "requires": {
                 "lower-case": "^2.0.2",
                 "tslib": "^2.0.3"
-            },
-            "dependencies": {
-                "tslib": {
-                    "version": "2.3.1",
-                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
-                    "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
-                }
             }
         },
         "node-abi": {
-            "version": "2.16.0",
-            "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.16.0.tgz",
-            "integrity": "sha512-+sa0XNlWDA6T+bDLmkCUYn6W5k5W6BPRL6mqzSCs6H/xUgtl4D5x2fORKDzopKiU6wsyn/+wXlRXwXeSp+mtoA==",
+            "version": "2.30.1",
+            "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz",
+            "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==",
             "requires": {
                 "semver": "^5.4.1"
             }
@@ -10889,9 +10289,9 @@
             }
         },
         "node-forge": {
-            "version": "0.9.1",
-            "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.1.tgz",
-            "integrity": "sha512-G6RlQt5Sb4GMBzXvhfkeFmbqR6MzhtnT7VTHuLadjkii3rdYHNdw0m8zA4BTxVIh68FicCQ2NSUANpsqkr9jvQ=="
+            "version": "0.10.0",
+            "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
+            "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA=="
         },
         "node-gyp": {
             "version": "3.8.0",
@@ -10912,6 +10312,48 @@
                 "which": "1"
             },
             "dependencies": {
+                "ansi-regex": {
+                    "version": "2.1.1",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+                },
+                "aproba": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                    "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+                },
+                "are-we-there-yet": {
+                    "version": "1.1.7",
+                    "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
+                    "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
+                    "requires": {
+                        "delegates": "^1.0.0",
+                        "readable-stream": "^2.0.6"
+                    }
+                },
+                "gauge": {
+                    "version": "2.7.4",
+                    "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+                    "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+                    "requires": {
+                        "aproba": "^1.0.3",
+                        "console-control-strings": "^1.0.0",
+                        "has-unicode": "^2.0.0",
+                        "object-assign": "^4.1.0",
+                        "signal-exit": "^3.0.0",
+                        "string-width": "^1.0.1",
+                        "strip-ansi": "^3.0.1",
+                        "wide-align": "^1.1.0"
+                    }
+                },
+                "is-fullwidth-code-point": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+                    "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+                    "requires": {
+                        "number-is-nan": "^1.0.0"
+                    }
+                },
                 "nopt": {
                     "version": "3.0.6",
                     "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
@@ -10920,6 +10362,31 @@
                         "abbrev": "1"
                     }
                 },
+                "npmlog": {
+                    "version": "4.1.2",
+                    "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+                    "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+                    "requires": {
+                        "are-we-there-yet": "~1.1.2",
+                        "console-control-strings": "~1.1.0",
+                        "gauge": "~2.7.3",
+                        "set-blocking": "~2.0.0"
+                    }
+                },
+                "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"
+                    }
+                },
                 "rimraf": {
                     "version": "2.7.1",
                     "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
@@ -10933,6 +10400,24 @@
                     "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
                     "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
                 },
+                "string-width": {
+                    "version": "1.0.2",
+                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+                    "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+                    "requires": {
+                        "code-point-at": "^1.0.0",
+                        "is-fullwidth-code-point": "^1.0.0",
+                        "strip-ansi": "^3.0.0"
+                    }
+                },
+                "strip-ansi": {
+                    "version": "3.0.1",
+                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+                    "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+                    "requires": {
+                        "ansi-regex": "^2.0.0"
+                    }
+                },
                 "tar": {
                     "version": "2.2.2",
                     "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
@@ -10946,9 +10431,9 @@
             }
         },
         "node-releases": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz",
-            "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg=="
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.3.tgz",
+            "integrity": "sha512-maHFz6OLqYxz+VQyCAtA3PTX4UP/53pa05fyDNc9CwjvJ0yEh6+xBwKsgCxMNhS8taUKBFYxfuiaD9U/55iFaw=="
         },
         "node-sass": {
             "version": "4.14.1",
@@ -10984,6 +10469,20 @@
                     "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
                     "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
                 },
+                "aproba": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                    "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+                },
+                "are-we-there-yet": {
+                    "version": "1.1.7",
+                    "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
+                    "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
+                    "requires": {
+                        "delegates": "^1.0.0",
+                        "readable-stream": "^2.0.6"
+                    }
+                },
                 "chalk": {
                     "version": "1.1.3",
                     "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
@@ -10996,11 +10495,69 @@
                         "supports-color": "^2.0.0"
                     }
                 },
+                "gauge": {
+                    "version": "2.7.4",
+                    "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+                    "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+                    "requires": {
+                        "aproba": "^1.0.3",
+                        "console-control-strings": "^1.0.0",
+                        "has-unicode": "^2.0.0",
+                        "object-assign": "^4.1.0",
+                        "signal-exit": "^3.0.0",
+                        "string-width": "^1.0.1",
+                        "strip-ansi": "^3.0.1",
+                        "wide-align": "^1.1.0"
+                    }
+                },
                 "get-stdin": {
                     "version": "4.0.1",
                     "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
                     "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4="
                 },
+                "is-fullwidth-code-point": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+                    "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+                    "requires": {
+                        "number-is-nan": "^1.0.0"
+                    }
+                },
+                "npmlog": {
+                    "version": "4.1.2",
+                    "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+                    "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+                    "requires": {
+                        "are-we-there-yet": "~1.1.2",
+                        "console-control-strings": "~1.1.0",
+                        "gauge": "~2.7.3",
+                        "set-blocking": "~2.0.0"
+                    }
+                },
+                "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"
+                    }
+                },
+                "string-width": {
+                    "version": "1.0.2",
+                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+                    "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+                    "requires": {
+                        "code-point-at": "^1.0.0",
+                        "is-fullwidth-code-point": "^1.0.0",
+                        "strip-ansi": "^3.0.0"
+                    }
+                },
                 "strip-ansi": {
                     "version": "3.0.1",
                     "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
@@ -11056,6 +10613,14 @@
             "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
             "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI="
         },
+        "nopt": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
+            "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
+            "requires": {
+                "abbrev": "1"
+            }
+        },
         "normalize-package-data": {
             "version": "2.5.0",
             "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
@@ -14193,14 +13758,14 @@
             }
         },
         "npmlog": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
-            "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
+            "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
             "requires": {
-                "are-we-there-yet": "~1.1.2",
-                "console-control-strings": "~1.1.0",
-                "gauge": "~2.7.3",
-                "set-blocking": "~2.0.0"
+                "are-we-there-yet": "^2.0.0",
+                "console-control-strings": "^1.1.0",
+                "gauge": "^3.0.0",
+                "set-blocking": "^2.0.0"
             }
         },
         "nth-check": {
@@ -14271,9 +13836,9 @@
             }
         },
         "object-inspect": {
-            "version": "1.7.0",
-            "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
-            "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw=="
+            "version": "1.12.0",
+            "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
+            "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g=="
         },
         "object-is": {
             "version": "1.1.5",
@@ -14301,6 +13866,11 @@
                 "unpack-string": "0.0.2"
             },
             "dependencies": {
+                "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=="
+                },
                 "inspect-parameters-declaration": {
                     "version": "0.0.10",
                     "resolved": "https://registry.npmjs.org/inspect-parameters-declaration/-/inspect-parameters-declaration-0.0.10.tgz",
@@ -14345,12 +13915,13 @@
             }
         },
         "object.getownpropertydescriptors": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz",
-            "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==",
+            "version": "2.1.3",
+            "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz",
+            "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==",
             "requires": {
+                "call-bind": "^1.0.2",
                 "define-properties": "^1.1.3",
-                "es-abstract": "^1.17.0-next.1"
+                "es-abstract": "^1.19.1"
             }
         },
         "object.pick": {
@@ -14368,9 +13939,9 @@
             "dev": true
         },
         "on-finished": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
-            "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+            "version": "2.4.1",
+            "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+            "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
             "requires": {
                 "ee-first": "1.1.1"
             }
@@ -14415,9 +13986,12 @@
             }
         },
         "optional-require": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz",
-            "integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA=="
+            "version": "1.1.8",
+            "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz",
+            "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==",
+            "requires": {
+                "require-at": "^1.0.6"
+            }
         },
         "optionator": {
             "version": "0.8.3",
@@ -14528,6 +14102,11 @@
                 "semver": "^5.1.0"
             },
             "dependencies": {
+                "get-stream": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+                    "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
+                },
                 "got": {
                     "version": "6.7.1",
                     "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
@@ -14593,13 +14172,6 @@
             "requires": {
                 "dot-case": "^3.0.4",
                 "tslib": "^2.0.3"
-            },
-            "dependencies": {
-                "tslib": {
-                    "version": "2.3.1",
-                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
-                    "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
-                }
             }
         },
         "parent-module": {
@@ -14621,6 +14193,12 @@
                 "lines-and-columns": "^1.1.6"
             }
         },
+        "parse5": {
+            "version": "5.1.0",
+            "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz",
+            "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
+            "dev": true
+        },
         "parseqs": {
             "version": "0.0.6",
             "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz",
@@ -14643,13 +14221,6 @@
             "requires": {
                 "no-case": "^3.0.4",
                 "tslib": "^2.0.3"
-            },
-            "dependencies": {
-                "tslib": {
-                    "version": "2.3.1",
-                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
-                    "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
-                }
             }
         },
         "pascalcase": {
@@ -14683,9 +14254,9 @@
             }
         },
         "passport-oauth2": {
-            "version": "1.5.0",
-            "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.5.0.tgz",
-            "integrity": "sha512-kqBt6vR/5VlCK8iCx1/KpY42kQ+NEHZwsSyt4Y6STiNjU+wWICG1i8ucc1FapXDGO15C5O5VZz7+7vRzrDPXXQ==",
+            "version": "1.6.1",
+            "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.6.1.tgz",
+            "integrity": "sha512-ZbV43Hq9d/SBSYQ22GOiglFsjsD1YY/qdiptA+8ej+9C1dL1TVB+mBE5kDH/D4AJo50+2i8f4bx0vg4/yDDZCQ==",
             "requires": {
                 "base64url": "3.x.x",
                 "oauth": "0.9.x",
@@ -14730,9 +14301,9 @@
             "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
         },
         "path-parse": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
-            "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
+            "version": "1.0.7",
+            "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+            "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
         },
         "path-to-regexp": {
             "version": "0.1.7",
@@ -14814,14 +14385,12 @@
         "picomatch": {
             "version": "2.3.1",
             "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
-            "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-            "dev": true
+            "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
         },
         "pify": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
-            "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
-            "dev": true
+            "version": "2.3.0",
+            "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+            "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
         },
         "pinkie": {
             "version": "2.0.4",
@@ -14842,56 +14411,42 @@
             "integrity": "sha512-6Rtbp7criZRwedlvWbUYxqlqJoAlMvYHo2UcRWq79xZ54vZcaNHpVBOcWkX3ErT2aUA69tv+uiv4zKJbhD/Wgg=="
         },
         "pkg-dir": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
-            "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
-            "dev": true,
+            "version": "4.2.0",
+            "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+            "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
             "requires": {
-                "find-up": "^2.1.0"
+                "find-up": "^4.0.0"
             },
             "dependencies": {
                 "find-up": {
-                    "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
-                    "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
-                    "dev": true,
+                    "version": "4.1.0",
+                    "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+                    "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
                     "requires": {
-                        "locate-path": "^2.0.0"
+                        "locate-path": "^5.0.0",
+                        "path-exists": "^4.0.0"
                     }
                 },
                 "locate-path": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
-                    "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
-                    "dev": true,
-                    "requires": {
-                        "p-locate": "^2.0.0",
-                        "path-exists": "^3.0.0"
-                    }
-                },
-                "p-limit": {
-                    "version": "1.3.0",
-                    "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
-                    "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
-                    "dev": true,
+                    "version": "5.0.0",
+                    "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+                    "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
                     "requires": {
-                        "p-try": "^1.0.0"
+                        "p-locate": "^4.1.0"
                     }
                 },
                 "p-locate": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
-                    "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
-                    "dev": true,
+                    "version": "4.1.0",
+                    "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+                    "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
                     "requires": {
-                        "p-limit": "^1.1.0"
+                        "p-limit": "^2.2.0"
                     }
                 },
-                "p-try": {
-                    "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
-                    "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
-                    "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=="
                 }
             }
         },
@@ -14944,12 +14499,12 @@
             },
             "dependencies": {
                 "mkdirp": {
-                    "version": "0.5.5",
-                    "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
-                    "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+                    "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.5"
+                        "minimist": "^1.2.6"
                     }
                 }
             }
@@ -14960,30 +14515,26 @@
             "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
         },
         "postcss": {
-            "version": "7.0.27",
-            "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz",
-            "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==",
+            "version": "7.0.39",
+            "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+            "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
             "dev": true,
             "requires": {
-                "chalk": "^2.4.2",
-                "source-map": "^0.6.1",
-                "supports-color": "^6.1.0"
+                "picocolors": "^0.2.1",
+                "source-map": "^0.6.1"
             },
             "dependencies": {
+                "picocolors": {
+                    "version": "0.2.1",
+                    "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+                    "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+                    "dev": true
+                },
                 "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
-                },
-                "supports-color": {
-                    "version": "6.1.0",
-                    "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
-                    "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
-                    "dev": true,
-                    "requires": {
-                        "has-flag": "^3.0.0"
-                    }
                 }
             }
         },
@@ -15028,14 +14579,13 @@
             }
         },
         "postcss-selector-parser": {
-            "version": "6.0.2",
-            "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz",
-            "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==",
+            "version": "6.0.10",
+            "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
+            "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
             "dev": true,
             "requires": {
                 "cssesc": "^3.0.0",
-                "indexes-of": "^1.0.1",
-                "uniq": "^1.0.1"
+                "util-deprecate": "^1.0.2"
             }
         },
         "postcss-value-parser": {
@@ -15044,15 +14594,15 @@
             "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="
         },
         "prebuild-install": {
-            "version": "5.3.3",
-            "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.3.tgz",
-            "integrity": "sha512-GV+nsUXuPW2p8Zy7SarF/2W/oiK8bFQgJcncoJ0d7kRpekEA0ftChjfEaF9/Y+QJEc/wFR7RAEa8lYByuUIe2g==",
+            "version": "5.3.6",
+            "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz",
+            "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==",
             "requires": {
                 "detect-libc": "^1.0.3",
                 "expand-template": "^2.0.3",
                 "github-from-package": "0.0.0",
-                "minimist": "^1.2.0",
-                "mkdirp": "^0.5.1",
+                "minimist": "^1.2.3",
+                "mkdirp-classic": "^0.5.3",
                 "napi-build-utils": "^1.0.1",
                 "node-abi": "^2.7.0",
                 "noop-logger": "^0.1.1",
@@ -15063,6 +14613,98 @@
                 "tar-fs": "^2.0.0",
                 "tunnel-agent": "^0.6.0",
                 "which-pm-runs": "^1.0.0"
+            },
+            "dependencies": {
+                "ansi-regex": {
+                    "version": "2.1.1",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+                },
+                "aproba": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                    "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+                },
+                "are-we-there-yet": {
+                    "version": "1.1.7",
+                    "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
+                    "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
+                    "requires": {
+                        "delegates": "^1.0.0",
+                        "readable-stream": "^2.0.6"
+                    }
+                },
+                "detect-libc": {
+                    "version": "1.0.3",
+                    "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+                    "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
+                },
+                "gauge": {
+                    "version": "2.7.4",
+                    "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+                    "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+                    "requires": {
+                        "aproba": "^1.0.3",
+                        "console-control-strings": "^1.0.0",
+                        "has-unicode": "^2.0.0",
+                        "object-assign": "^4.1.0",
+                        "signal-exit": "^3.0.0",
+                        "string-width": "^1.0.1",
+                        "strip-ansi": "^3.0.1",
+                        "wide-align": "^1.1.0"
+                    }
+                },
+                "is-fullwidth-code-point": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+                    "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+                    "requires": {
+                        "number-is-nan": "^1.0.0"
+                    }
+                },
+                "npmlog": {
+                    "version": "4.1.2",
+                    "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+                    "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+                    "requires": {
+                        "are-we-there-yet": "~1.1.2",
+                        "console-control-strings": "~1.1.0",
+                        "gauge": "~2.7.3",
+                        "set-blocking": "~2.0.0"
+                    }
+                },
+                "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"
+                    }
+                },
+                "string-width": {
+                    "version": "1.0.2",
+                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+                    "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+                    "requires": {
+                        "code-point-at": "^1.0.0",
+                        "is-fullwidth-code-point": "^1.0.0",
+                        "strip-ansi": "^3.0.0"
+                    }
+                },
+                "strip-ansi": {
+                    "version": "3.0.1",
+                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+                    "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+                    "requires": {
+                        "ansi-regex": "^2.0.0"
+                    }
+                }
             }
         },
         "prelude-ls": {
@@ -15135,19 +14777,19 @@
             "dev": true
         },
         "prop-types": {
-            "version": "15.7.2",
-            "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
-            "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
+            "version": "15.8.1",
+            "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+            "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
             "requires": {
                 "loose-envify": "^1.4.0",
                 "object-assign": "^4.1.1",
-                "react-is": "^16.8.1"
+                "react-is": "^16.13.1"
             }
         },
         "prosemirror-commands": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.2.1.tgz",
-            "integrity": "sha512-S/IkpXfpuLFsRynC2HQ5iYROUPiZskKS1+ClcWycGJvj4HMb/mVfeEkQrixYxgTl96EAh+RZQNWPC06GZXk5tQ==",
+            "version": "1.2.2",
+            "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.2.2.tgz",
+            "integrity": "sha512-TX+KpWudMon06frryfpO/u7hsQv2hu8L4VSVbCpi3/7wXHBgl+35mV85qfa3RpT8xD2f3MdeoTqH0vy5JdbXPg==",
             "requires": {
                 "prosemirror-model": "^1.0.0",
                 "prosemirror-state": "^1.0.0",
@@ -15234,17 +14876,17 @@
             }
         },
         "prosemirror-transform": {
-            "version": "1.3.4",
-            "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.3.4.tgz",
-            "integrity": "sha512-gTsg3UIeaFuEY6+YmNPMgTpEkCKPedkFIUnsPpOMbclU701fEVI/e4VOXACXh3BO5rZJaBbEBwrnzB0mLp6eBA==",
+            "version": "1.4.2",
+            "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.4.2.tgz",
+            "integrity": "sha512-bcIsf3uRZhfab0xRfyyxOEh6eqSszq/hJbDbmUumFnbHBoWhB/uXbpz6vvUxfk0XiEvrZDJ+5pXRrNDc1Hu3vQ==",
             "requires": {
                 "prosemirror-model": "^1.0.0"
             }
         },
         "prosemirror-view": {
-            "version": "1.23.7",
-            "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.23.7.tgz",
-            "integrity": "sha512-ugY+g/4UI2Ree1zzdvbyQWF2KpbFa7kxKMLHaEJcxiPaErnZiD5wZFqIgFinc7fY2v/QM3DLnJ++2I45ULRdrg==",
+            "version": "1.23.12",
+            "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.23.12.tgz",
+            "integrity": "sha512-uvw9ZVz5dNDD9w1bzHkU2r4NWFlpFz85v9rCD8NAhQBau6LYhwM/crjry+C4JgeR8gy6pMXS5eJ1zhNLcK4ctQ==",
             "requires": {
                 "prosemirror-model": "^1.16.0",
                 "prosemirror-state": "^1.0.0",
@@ -15282,9 +14924,9 @@
             "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
         },
         "pstree.remy": {
-            "version": "1.1.7",
-            "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.7.tgz",
-            "integrity": "sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A=="
+            "version": "1.1.8",
+            "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
+            "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w=="
         },
         "pug": {
             "version": "2.0.4",
@@ -15312,9 +14954,9 @@
             }
         },
         "pug-code-gen": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.2.tgz",
-            "integrity": "sha512-kROFWv/AHx/9CRgoGJeRSm+4mLWchbgpRzTEn8XCiwwOy6Vh0gAClS8Vh5TEJ9DBjaP8wCjS3J6HKsEsYdvaCw==",
+            "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",
@@ -15343,6 +14985,21 @@
                 "pug-walk": "^1.1.8",
                 "resolve": "^1.1.6",
                 "uglify-js": "^2.6.1"
+            },
+            "dependencies": {
+                "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"
+                    }
+                },
+                "source-map": {
+                    "version": "0.6.1",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+                    "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+                }
             }
         },
         "pug-lexer": {
@@ -15460,11 +15117,11 @@
                     "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g=="
                 },
                 "debug": {
-                    "version": "4.1.1",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+                    "version": "4.3.4",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+                    "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
                     "requires": {
-                        "ms": "^2.1.1"
+                        "ms": "2.1.2"
                     }
                 },
                 "https-proxy-agent": {
@@ -15477,9 +15134,14 @@
                     }
                 },
                 "mime": {
-                    "version": "2.4.6",
-                    "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz",
-                    "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA=="
+                    "version": "2.6.0",
+                    "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+                    "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg=="
+                },
+                "ms": {
+                    "version": "2.1.2",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+                    "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
                 }
             }
         },
@@ -15551,14 +15213,24 @@
             "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
         },
         "raw-body": {
-            "version": "2.4.3",
-            "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz",
-            "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==",
+            "version": "2.5.1",
+            "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
+            "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
             "requires": {
                 "bytes": "3.1.2",
-                "http-errors": "1.8.1",
+                "http-errors": "2.0.0",
                 "iconv-lite": "0.4.24",
                 "unpipe": "1.0.0"
+            },
+            "dependencies": {
+                "iconv-lite": {
+                    "version": "0.4.24",
+                    "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+                    "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+                    "requires": {
+                        "safer-buffer": ">= 2.1.2 < 3"
+                    }
+                }
             }
         },
         "raw-loader": {
@@ -15568,18 +15240,6 @@
             "requires": {
                 "loader-utils": "^1.1.0",
                 "schema-utils": "^1.0.0"
-            },
-            "dependencies": {
-                "schema-utils": {
-                    "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
-                    "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
-                    "requires": {
-                        "ajv": "^6.1.0",
-                        "ajv-errors": "^1.0.0",
-                        "ajv-keywords": "^3.1.0"
-                    }
-                }
             }
         },
         "rc": {
@@ -15686,6 +15346,13 @@
                 "d3-array": "^1.2.4",
                 "prop-types": "^15.7.2",
                 "warning": "^3.0.0"
+            },
+            "dependencies": {
+                "d3-array": {
+                    "version": "1.2.4",
+                    "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
+                    "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
+                }
             }
         },
         "react-datepicker": {
@@ -15732,11 +15399,11 @@
             }
         },
         "react-draggable": {
-            "version": "4.4.3",
-            "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.3.tgz",
-            "integrity": "sha512-jV4TE59MBuWm7gb6Ns3Q1mxX8Azffb7oTtDtBgFkxRvhDp38YAARmRplrj0+XGkhOJB5XziArX+4HUUABtyZ0w==",
+            "version": "4.4.4",
+            "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.4.tgz",
+            "integrity": "sha512-6e0WdcNLwpBx/YIDpoyd2Xb04PB0elrDrulKUgdrIlwuYvxh5Ok9M+F8cljm8kPXXs43PmMzek9RrB1b7mLMqA==",
             "requires": {
-                "classnames": "^2.2.5",
+                "clsx": "^1.1.1",
                 "prop-types": "^15.6.0"
             }
         },
@@ -15825,9 +15492,9 @@
             },
             "dependencies": {
                 "@types/react": {
-                    "version": "17.0.39",
-                    "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz",
-                    "integrity": "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==",
+                    "version": "17.0.44",
+                    "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.44.tgz",
+                    "integrity": "sha512-Ye0nlw09GeMp2Suh8qoOv0odfgCoowfM/9MG6WeRD60Gq9wS90bdkdRtYbRkNhXOpG4H+YXGvj4wOWhAC0LJ1g==",
                     "optional": true,
                     "requires": {
                         "@types/prop-types": "*",
@@ -15836,28 +15503,23 @@
                     }
                 },
                 "@types/react-dom": {
-                    "version": "17.0.11",
-                    "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz",
-                    "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==",
+                    "version": "17.0.15",
+                    "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.15.tgz",
+                    "integrity": "sha512-Tr9VU9DvNoHDWlmecmcsE5ZZiUkYx+nKBzum4Oxe1K0yJVyBlfbq7H3eXjxXqJczBKqPGq3EgfTru4MgKb9+Yw==",
                     "optional": true,
                     "requires": {
-                        "@types/react": "*"
+                        "@types/react": "^17"
                     }
                 },
-                "acorn": {
-                    "version": "8.7.0",
-                    "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
-                    "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ=="
-                },
                 "core-js": {
-                    "version": "3.21.1",
-                    "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz",
-                    "integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig=="
+                    "version": "3.22.1",
+                    "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.1.tgz",
+                    "integrity": "sha512-l6CwCLq7XgITOQGhv1dIUmwCFoqFjyQ6zQHUCQlS0xKmb9d6OHIg8jDiEoswhaettT21BSF5qKr6kbvE+aKwxw=="
                 },
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==",
+                    "version": "3.0.11",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
+                    "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==",
                     "optional": true
                 }
             }
@@ -15889,12 +15551,12 @@
             "integrity": "sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ=="
         },
         "react-modal": {
-            "version": "3.11.2",
-            "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.11.2.tgz",
-            "integrity": "sha512-o8gvvCOFaG1T7W6JUvsYjRjMVToLZgLIsi5kdhFIQCtHxDkA47LznX62j+l6YQkpXDbvQegsDyxe/+JJsFQN7w==",
+            "version": "3.14.4",
+            "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.14.4.tgz",
+            "integrity": "sha512-8surmulejafYCH9wfUmFyj4UfbSJwjcgbS9gf3oOItu4Hwd6ivJyVBETI0yHRhpJKCLZMUtnhzk76wXTsNL6Qg==",
             "requires": {
                 "exenv": "^1.2.0",
-                "prop-types": "^15.5.10",
+                "prop-types": "^15.7.2",
                 "react-lifecycles-compat": "^3.0.0",
                 "warning": "^4.0.3"
             },
@@ -15954,9 +15616,9 @@
             }
         },
         "react-redux": {
-            "version": "7.2.6",
-            "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.6.tgz",
-            "integrity": "sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ==",
+            "version": "7.2.8",
+            "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.8.tgz",
+            "integrity": "sha512-6+uDjhs3PSIclqoCk0kd6iX74gzrGc3W5zcAjbrFgEdIjRSQObdIwfx80unTkVUYvbQ95Y8Av3OvFHq1w5EOUw==",
             "requires": {
                 "@babel/runtime": "^7.15.4",
                 "@types/react-redux": "^7.1.20",
@@ -15966,14 +15628,6 @@
                 "react-is": "^17.0.2"
             },
             "dependencies": {
-                "@babel/runtime": {
-                    "version": "7.17.2",
-                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz",
-                    "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==",
-                    "requires": {
-                        "regenerator-runtime": "^0.13.4"
-                    }
-                },
                 "react-is": {
                     "version": "17.0.2",
                     "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -15982,9 +15636,9 @@
             }
         },
         "react-refresh-typescript": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/react-refresh-typescript/-/react-refresh-typescript-2.0.3.tgz",
-            "integrity": "sha512-CnR+UkpCFUIxW3u+KPxc6UhSO3M3aQxd9XCvgdry4a22LFwwITnjbANFUKtPGxA/Skw3PbZJrLiZ08UQnpXprQ=="
+            "version": "2.0.4",
+            "resolved": "https://registry.npmjs.org/react-refresh-typescript/-/react-refresh-typescript-2.0.4.tgz",
+            "integrity": "sha512-ySsBExEFik5Jjf7NoXtFbzUk2rYWM4gF5gg+wRTNmp9p7B2uMpAAa339FHWqmB8EAr0e6mzzskAXxc0Jd04fBw=="
         },
         "react-resizable": {
             "version": "1.11.1",
@@ -16034,9 +15688,9 @@
                     }
                 },
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
+                    "version": "3.0.11",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
+                    "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
                 },
                 "dom-helpers": {
                     "version": "5.2.1",
@@ -16136,11 +15790,6 @@
                         "pify": "^2.0.0",
                         "pinkie-promise": "^2.0.0"
                     }
-                },
-                "pify": {
-                    "version": "2.3.0",
-                    "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-                    "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
                 }
             }
         },
@@ -16254,17 +15903,17 @@
             "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc="
         },
         "redux": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz",
-            "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==",
+            "version": "4.2.0",
+            "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz",
+            "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==",
             "requires": {
                 "@babel/runtime": "^7.9.2"
             }
         },
         "regenerator-runtime": {
-            "version": "0.13.5",
-            "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
-            "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA=="
+            "version": "0.13.9",
+            "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
+            "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
         },
         "regex-not": {
             "version": "1.0.2",
@@ -16281,12 +15930,13 @@
             "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw=="
         },
         "regexp.prototype.flags": {
-            "version": "1.4.1",
-            "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz",
-            "integrity": "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==",
+            "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"
+                "define-properties": "^1.1.3",
+                "functions-have-names": "^1.2.2"
             }
         },
         "registry-auth-token": {
@@ -16334,9 +15984,9 @@
                     "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
                 },
                 "dom-serializer": {
-                    "version": "1.3.2",
-                    "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
-                    "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
+                    "version": "1.4.1",
+                    "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
+                    "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
                     "requires": {
                         "domelementtype": "^2.0.1",
                         "domhandler": "^4.2.0",
@@ -16344,14 +15994,14 @@
                     }
                 },
                 "domelementtype": {
-                    "version": "2.2.0",
-                    "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
-                    "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
+                    "version": "2.3.0",
+                    "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+                    "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
                 },
                 "domhandler": {
-                    "version": "4.3.0",
-                    "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
-                    "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
+                    "version": "4.3.1",
+                    "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
+                    "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
                     "requires": {
                         "domelementtype": "^2.2.0"
                     }
@@ -16393,9 +16043,9 @@
             }
         },
         "repeat-element": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
-            "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g=="
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz",
+            "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ=="
         },
         "repeat-string": {
             "version": "1.6.1",
@@ -16437,16 +16087,6 @@
                 "uuid": "^3.3.2"
             },
             "dependencies": {
-                "form-data": {
-                    "version": "2.3.3",
-                    "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
-                    "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
-                    "requires": {
-                        "asynckit": "^0.4.0",
-                        "combined-stream": "^1.0.6",
-                        "mime-types": "^2.1.12"
-                    }
-                },
                 "tough-cookie": {
                     "version": "2.5.0",
                     "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
@@ -16469,14 +16109,6 @@
                 "tough-cookie": "^2.3.3"
             },
             "dependencies": {
-                "request-promise-core": {
-                    "version": "1.1.4",
-                    "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
-                    "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
-                    "requires": {
-                        "lodash": "^4.17.19"
-                    }
-                },
                 "tough-cookie": {
                     "version": "2.5.0",
                     "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
@@ -16489,21 +16121,20 @@
             }
         },
         "request-promise-core": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz",
-            "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==",
-            "dev": true,
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
+            "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
             "requires": {
-                "lodash": "^4.17.15"
+                "lodash": "^4.17.19"
             }
         },
         "request-promise-native": {
-            "version": "1.0.8",
-            "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz",
-            "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==",
+            "version": "1.0.9",
+            "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz",
+            "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==",
             "dev": true,
             "requires": {
-                "request-promise-core": "1.1.3",
+                "request-promise-core": "1.1.4",
                 "stealthy-require": "^1.1.1",
                 "tough-cookie": "^2.3.3"
             },
@@ -16573,11 +16204,13 @@
             "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
         },
         "resolve": {
-            "version": "1.17.0",
-            "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
-            "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+            "version": "1.22.0",
+            "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
+            "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
             "requires": {
-                "path-parse": "^1.0.6"
+                "is-core-module": "^2.8.1",
+                "path-parse": "^1.0.7",
+                "supports-preserve-symlinks-flag": "^1.0.0"
             }
         },
         "resolve-alpn": {
@@ -16586,19 +16219,17 @@
             "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="
         },
         "resolve-cwd": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
-            "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
-            "dev": true,
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+            "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
             "requires": {
-                "resolve-from": "^3.0.0"
+                "resolve-from": "^5.0.0"
             },
             "dependencies": {
                 "resolve-from": {
-                    "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
-                    "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
-                    "dev": true
+                    "version": "5.0.0",
+                    "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+                    "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="
                 }
             }
         },
@@ -16639,9 +16270,9 @@
             "dev": true
         },
         "reveal.js": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/reveal.js/-/reveal.js-4.3.0.tgz",
-            "integrity": "sha512-KzZxJjj1gmxVNyplY6g9MiGwtDvZJiYkMvG1Qmaita7vWT/8eoTEK+RuIPLvxDeyxOtTz56u2wrOETVO79qL4A=="
+            "version": "4.3.1",
+            "resolved": "https://registry.npmjs.org/reveal.js/-/reveal.js-4.3.1.tgz",
+            "integrity": "sha512-1kyEnWeUkaCdBdX//XXq9dtBK95ppvIlSwlHelrP8/wrX6LcsYp4HT9WTFoFEOUBfVqkm8C2aHQ367o+UKfcxw=="
         },
         "right-align": {
             "version": "0.1.3",
@@ -16679,6 +16310,14 @@
             "dev": true,
             "requires": {
                 "aproba": "^1.1.1"
+            },
+            "dependencies": {
+                "aproba": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                    "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+                    "dev": true
+                }
             }
         },
         "safe-buffer": {
@@ -16732,6 +16371,12 @@
                 "semver": "^6.3.0"
             },
             "dependencies": {
+                "pify": {
+                    "version": "4.0.1",
+                    "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+                    "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+                    "dev": true
+                },
                 "semver": {
                     "version": "6.3.0",
                     "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -16762,7 +16407,6 @@
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
             "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
-            "dev": true,
             "requires": {
                 "ajv": "^6.1.0",
                 "ajv-errors": "^1.0.0",
@@ -16817,14 +16461,6 @@
             "dev": true,
             "requires": {
                 "node-forge": "^0.10.0"
-            },
-            "dependencies": {
-                "node-forge": {
-                    "version": "0.10.0",
-                    "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
-                    "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==",
-                    "dev": true
-                }
             }
         },
         "semver": {
@@ -16880,18 +16516,56 @@
                         }
                     }
                 },
+                "depd": {
+                    "version": "1.1.2",
+                    "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+                    "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+                },
+                "destroy": {
+                    "version": "1.0.4",
+                    "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+                    "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+                },
+                "http-errors": {
+                    "version": "1.8.1",
+                    "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
+                    "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
+                    "requires": {
+                        "depd": "~1.1.2",
+                        "inherits": "2.0.4",
+                        "setprototypeof": "1.2.0",
+                        "statuses": ">= 1.5.0 < 2",
+                        "toidentifier": "1.0.1"
+                    }
+                },
                 "ms": {
                     "version": "2.1.3",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
                     "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+                },
+                "on-finished": {
+                    "version": "2.3.0",
+                    "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+                    "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+                    "requires": {
+                        "ee-first": "1.1.1"
+                    }
+                },
+                "statuses": {
+                    "version": "1.5.0",
+                    "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+                    "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
                 }
             }
         },
         "serialize-javascript": {
-            "version": "1.9.1",
-            "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz",
-            "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==",
-            "dev": true
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+            "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+            "dev": true,
+            "requires": {
+                "randombytes": "^2.1.0"
+            }
         },
         "serializr": {
             "version": "1.5.4",
@@ -16922,6 +16596,12 @@
                         "ms": "2.0.0"
                     }
                 },
+                "depd": {
+                    "version": "1.1.2",
+                    "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+                    "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+                    "dev": true
+                },
                 "http-errors": {
                     "version": "1.6.3",
                     "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
@@ -16951,6 +16631,12 @@
                     "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
                     "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
                     "dev": true
+                },
+                "statuses": {
+                    "version": "1.5.0",
+                    "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+                    "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
+                    "dev": true
                 }
             }
         },
@@ -16993,11 +16679,6 @@
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
-                },
-                "is-extendable": {
-                    "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-                    "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
                 }
             }
         },
@@ -17040,29 +16721,89 @@
                 "tunnel-agent": "^0.6.0"
             },
             "dependencies": {
-                "fs-minipass": {
-                    "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
-                    "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+                "ansi-regex": {
+                    "version": "2.1.1",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+                },
+                "aproba": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                    "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+                },
+                "are-we-there-yet": {
+                    "version": "1.1.7",
+                    "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
+                    "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
                     "requires": {
-                        "minipass": "^3.0.0"
+                        "delegates": "^1.0.0",
+                        "readable-stream": "^2.0.6"
                     }
                 },
-                "minipass": {
-                    "version": "3.1.1",
-                    "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.1.tgz",
-                    "integrity": "sha512-UFqVihv6PQgwj8/yTGvl9kPz7xIAY+R5z6XYjRInD3Gk3qx6QGSD6zEcpeG4Dy/lQnv1J6zv8ejV90hyYIKf3w==",
+                "chownr": {
+                    "version": "1.1.4",
+                    "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+                    "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+                },
+                "detect-libc": {
+                    "version": "1.0.3",
+                    "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+                    "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
+                },
+                "gauge": {
+                    "version": "2.7.4",
+                    "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+                    "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+                    "requires": {
+                        "aproba": "^1.0.3",
+                        "console-control-strings": "^1.0.0",
+                        "has-unicode": "^2.0.0",
+                        "object-assign": "^4.1.0",
+                        "signal-exit": "^3.0.0",
+                        "string-width": "^1.0.1",
+                        "strip-ansi": "^3.0.1",
+                        "wide-align": "^1.1.0"
+                    }
+                },
+                "is-fullwidth-code-point": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+                    "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+                    "requires": {
+                        "number-is-nan": "^1.0.0"
+                    }
+                },
+                "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"
+                    }
+                },
+                "npmlog": {
+                    "version": "4.1.2",
+                    "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+                    "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
                     "requires": {
-                        "yallist": "^4.0.0"
+                        "are-we-there-yet": "~1.1.2",
+                        "console-control-strings": "~1.1.0",
+                        "gauge": "~2.7.3",
+                        "set-blocking": "~2.0.0"
                     }
                 },
-                "minizlib": {
-                    "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.0.tgz",
-                    "integrity": "sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA==",
+                "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": {
-                        "minipass": "^3.0.0",
-                        "yallist": "^4.0.0"
+                        "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"
                     }
                 },
                 "semver": {
@@ -17070,23 +16811,36 @@
                     "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
                     "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
                 },
+                "string-width": {
+                    "version": "1.0.2",
+                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+                    "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+                    "requires": {
+                        "code-point-at": "^1.0.0",
+                        "is-fullwidth-code-point": "^1.0.0",
+                        "strip-ansi": "^3.0.0"
+                    }
+                },
+                "strip-ansi": {
+                    "version": "3.0.1",
+                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+                    "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+                    "requires": {
+                        "ansi-regex": "^2.0.0"
+                    }
+                },
                 "tar": {
-                    "version": "5.0.5",
-                    "resolved": "https://registry.npmjs.org/tar/-/tar-5.0.5.tgz",
-                    "integrity": "sha512-MNIgJddrV2TkuwChwcSNds/5E9VijOiw7kAc1y5hTNJoLDSuIyid2QtLYiCYNnICebpuvjhPQZsXwUL0O3l7OQ==",
-                    "requires": {
-                        "chownr": "^1.1.3",
-                        "fs-minipass": "^2.0.0",
-                        "minipass": "^3.0.0",
-                        "minizlib": "^2.1.0",
-                        "mkdirp": "^0.5.0",
+                    "version": "5.0.11",
+                    "resolved": "https://registry.npmjs.org/tar/-/tar-5.0.11.tgz",
+                    "integrity": "sha512-E6q48d5y4XSCD+Xmwc0yc8lXuyDK38E0FB8N4S/drQRtXOMUhfhDxbB0xr2KKDhNfO51CFmoa6Oz00nAkWsjnA==",
+                    "requires": {
+                        "chownr": "^1.1.4",
+                        "fs-minipass": "^2.1.0",
+                        "minipass": "^3.1.3",
+                        "minizlib": "^2.1.2",
+                        "mkdirp": "^0.5.5",
                         "yallist": "^4.0.0"
                     }
-                },
-                "yallist": {
-                    "version": "4.0.0",
-                    "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-                    "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
                 }
             }
         },
@@ -17121,13 +16875,6 @@
                 "call-bind": "^1.0.0",
                 "get-intrinsic": "^1.0.2",
                 "object-inspect": "^1.9.0"
-            },
-            "dependencies": {
-                "object-inspect": {
-                    "version": "1.12.0",
-                    "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
-                    "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g=="
-                }
             }
         },
         "sift": {
@@ -17136,9 +16883,9 @@
             "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA=="
         },
         "signal-exit": {
-            "version": "3.0.3",
-            "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
-            "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
+            "version": "3.0.7",
+            "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+            "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
         },
         "simple-assign": {
             "version": "0.1.0",
@@ -17146,14 +16893,14 @@
             "integrity": "sha1-F/0wZqXz13OPUDIbsPFMooHMS6o="
         },
         "simple-concat": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz",
-            "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY="
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+            "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="
         },
         "simple-get": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz",
-            "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==",
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz",
+            "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
             "requires": {
                 "decompress-response": "^4.2.0",
                 "once": "^1.3.1",
@@ -17175,11 +16922,6 @@
                 }
             }
         },
-        "skmeans": {
-            "version": "0.9.7",
-            "resolved": "https://registry.npmjs.org/skmeans/-/skmeans-0.9.7.tgz",
-            "integrity": "sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg=="
-        },
         "slash": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
@@ -17230,11 +16972,6 @@
                         "is-extendable": "^0.1.0"
                     }
                 },
-                "is-extendable": {
-                    "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-                    "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
-                },
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -17324,11 +17061,6 @@
                 "socket.io-parser": "~3.4.0"
             },
             "dependencies": {
-                "component-emitter": {
-                    "version": "1.2.1",
-                    "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
-                    "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
-                },
                 "debug": {
                     "version": "4.1.1",
                     "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
@@ -17336,21 +17068,6 @@
                     "requires": {
                         "ms": "^2.1.1"
                     }
-                },
-                "isarray": {
-                    "version": "2.0.1",
-                    "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
-                    "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
-                },
-                "socket.io-parser": {
-                    "version": "3.4.1",
-                    "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz",
-                    "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==",
-                    "requires": {
-                        "component-emitter": "1.2.1",
-                        "debug": "~4.1.0",
-                        "isarray": "2.0.1"
-                    }
                 }
             }
         },
@@ -17408,29 +17125,32 @@
             }
         },
         "socket.io-parser": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.1.2.tgz",
-            "integrity": "sha512-j3kk71QLJuyQ/hh5F/L2t1goqzdTL0gvDzuhTuNSwihfuFUrcSji0qFZmJJPtG6Rmug153eOPsUizeirf1IIog==",
-            "dev": true,
+            "version": "3.4.1",
+            "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz",
+            "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==",
             "requires": {
-                "@socket.io/component-emitter": "~3.0.0",
-                "debug": "~4.3.1"
+                "component-emitter": "1.2.1",
+                "debug": "~4.1.0",
+                "isarray": "2.0.1"
             },
             "dependencies": {
+                "component-emitter": {
+                    "version": "1.2.1",
+                    "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+                    "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
+                },
                 "debug": {
-                    "version": "4.3.3",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
-                    "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
-                    "dev": true,
+                    "version": "4.1.1",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
                     "requires": {
-                        "ms": "2.1.2"
+                        "ms": "^2.1.1"
                     }
                 },
-                "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
+                "isarray": {
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+                    "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
                 }
             }
         },
@@ -17488,9 +17208,12 @@
             },
             "dependencies": {
                 "node-fetch": {
-                    "version": "2.6.0",
-                    "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
-                    "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
+                    "version": "2.6.7",
+                    "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+                    "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+                    "requires": {
+                        "whatwg-url": "^5.0.0"
+                    }
                 }
             }
         },
@@ -17512,10 +17235,9 @@
             }
         },
         "source-map-support": {
-            "version": "0.5.19",
-            "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
-            "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
-            "dev": true,
+            "version": "0.5.21",
+            "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+            "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
             "requires": {
                 "buffer-from": "^1.0.0",
                 "source-map": "^0.6.0"
@@ -17524,15 +17246,14 @@
                 "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
+                    "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
                 }
             }
         },
         "source-map-url": {
-            "version": "0.4.0",
-            "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
-            "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM="
+            "version": "0.4.1",
+            "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz",
+            "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw=="
         },
         "sparse-bitfield": {
             "version": "3.0.3",
@@ -17544,9 +17265,9 @@
             }
         },
         "spdx-correct": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
-            "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+            "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
             "requires": {
                 "spdx-expression-parse": "^3.0.0",
                 "spdx-license-ids": "^3.0.0"
@@ -17558,18 +17279,18 @@
             "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A=="
         },
         "spdx-expression-parse": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
-            "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+            "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
             "requires": {
                 "spdx-exceptions": "^2.1.0",
                 "spdx-license-ids": "^3.0.0"
             }
         },
         "spdx-license-ids": {
-            "version": "3.0.5",
-            "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
-            "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q=="
+            "version": "3.0.11",
+            "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz",
+            "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g=="
         },
         "spdy": {
             "version": "4.0.2",
@@ -17585,9 +17306,9 @@
             },
             "dependencies": {
                 "debug": {
-                    "version": "4.3.3",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
-                    "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+                    "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"
@@ -17616,9 +17337,9 @@
             },
             "dependencies": {
                 "debug": {
-                    "version": "4.3.3",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
-                    "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+                    "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"
@@ -17713,9 +17434,9 @@
             }
         },
         "statuses": {
-            "version": "1.5.0",
-            "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
-            "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+            "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
         },
         "stdout-stream": {
             "version": "1.4.1",
@@ -17814,41 +17535,21 @@
             "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg=="
         },
         "string.prototype.trimend": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
-            "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
-            "requires": {
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.17.5"
-            }
-        },
-        "string.prototype.trimleft": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz",
-            "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==",
-            "requires": {
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.17.5",
-                "string.prototype.trimstart": "^1.0.0"
-            }
-        },
-        "string.prototype.trimright": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz",
-            "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==",
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
+            "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
             "requires": {
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.17.5",
-                "string.prototype.trimend": "^1.0.0"
+                "call-bind": "^1.0.2",
+                "define-properties": "^1.1.3"
             }
         },
         "string.prototype.trimstart": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
-            "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
+            "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
             "requires": {
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.17.5"
+                "call-bind": "^1.0.2",
+                "define-properties": "^1.1.3"
             }
         },
         "string_decoder": {
@@ -17868,6 +17569,11 @@
                 "unpack-string": "0.0.2"
             },
             "dependencies": {
+                "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=="
+                },
                 "magicli": {
                     "version": "0.0.5",
                     "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
@@ -17935,19 +17641,6 @@
             "requires": {
                 "loader-utils": "^1.1.0",
                 "schema-utils": "^1.0.0"
-            },
-            "dependencies": {
-                "schema-utils": {
-                    "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
-                    "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
-                    "dev": true,
-                    "requires": {
-                        "ajv": "^6.1.0",
-                        "ajv-errors": "^1.0.0",
-                        "ajv-keywords": "^3.1.0"
-                    }
-                }
             }
         },
         "styled-components": {
@@ -17968,12 +17661,27 @@
                 "stylis": "^3.5.0",
                 "stylis-rule-sheet": "^0.0.10",
                 "supports-color": "^5.5.0"
+            },
+            "dependencies": {
+                "@emotion/is-prop-valid": {
+                    "version": "0.8.8",
+                    "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
+                    "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
+                    "requires": {
+                        "@emotion/memoize": "0.7.4"
+                    }
+                },
+                "stylis": {
+                    "version": "3.5.4",
+                    "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz",
+                    "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q=="
+                }
             }
         },
         "stylis": {
-            "version": "3.5.4",
-            "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz",
-            "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q=="
+            "version": "4.0.13",
+            "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz",
+            "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
         },
         "stylis-rule-sheet": {
             "version": "0.0.10",
@@ -17981,9 +17689,9 @@
             "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw=="
         },
         "supercluster": {
-            "version": "7.1.4",
-            "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-7.1.4.tgz",
-            "integrity": "sha512-GhKkRM1jMR6WUwGPw05fs66pOFWhf59lXq+Q3J3SxPvhNcmgOtLRV6aVQPMRsmXdpaeFJGivt+t7QXUPL3ff4g==",
+            "version": "7.1.5",
+            "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-7.1.5.tgz",
+            "integrity": "sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg==",
             "requires": {
                 "kdbush": "^3.0.0"
             }
@@ -17996,6 +17704,11 @@
                 "has-flag": "^3.0.0"
             }
         },
+        "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=="
+        },
         "symbol-observable": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
@@ -18020,28 +17733,54 @@
             }
         },
         "tapable": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
-            "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
-            "dev": true
+            "version": "2.2.1",
+            "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+            "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="
+        },
+        "tar": {
+            "version": "6.1.11",
+            "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
+            "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
+            "requires": {
+                "chownr": "^2.0.0",
+                "fs-minipass": "^2.0.0",
+                "minipass": "^3.0.0",
+                "minizlib": "^2.1.1",
+                "mkdirp": "^1.0.3",
+                "yallist": "^4.0.0"
+            },
+            "dependencies": {
+                "mkdirp": {
+                    "version": "1.0.4",
+                    "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+                    "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
+                }
+            }
         },
         "tar-fs": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.1.tgz",
-            "integrity": "sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA==",
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
+            "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
             "requires": {
                 "chownr": "^1.1.1",
                 "mkdirp-classic": "^0.5.2",
                 "pump": "^3.0.0",
-                "tar-stream": "^2.0.0"
+                "tar-stream": "^2.1.4"
+            },
+            "dependencies": {
+                "chownr": {
+                    "version": "1.1.4",
+                    "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+                    "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+                }
             }
         },
         "tar-stream": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.2.tgz",
-            "integrity": "sha512-UaF6FoJ32WqALZGOIAApXx+OdxhekNMChu6axLJR85zMMjXKWFGjbIRe+J6P4UnRGg9rAwWvbTT0oI7hD/Un7Q==",
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+            "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
             "requires": {
-                "bl": "^4.0.1",
+                "bl": "^4.0.3",
                 "end-of-stream": "^1.4.1",
                 "fs-constants": "^1.0.0",
                 "inherits": "^2.0.3",
@@ -18071,9 +17810,9 @@
             }
         },
         "terser": {
-            "version": "5.12.0",
-            "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.0.tgz",
-            "integrity": "sha512-R3AUhNBGWiFc77HXag+1fXpAxTAFRQTJemlJKjAgD9r8xXTpjNKqIXwHM/o7Rh+O0kUJtS3WQVdBeMKFk5sw9A==",
+            "version": "5.12.1",
+            "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz",
+            "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==",
             "requires": {
                 "acorn": "^8.5.0",
                 "commander": "^2.20.0",
@@ -18081,31 +17820,15 @@
                 "source-map-support": "~0.5.20"
             },
             "dependencies": {
-                "acorn": {
-                    "version": "8.7.0",
-                    "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
-                    "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ=="
+                "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=="
                 },
                 "source-map": {
                     "version": "0.7.3",
                     "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
                     "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ=="
-                },
-                "source-map-support": {
-                    "version": "0.5.21",
-                    "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
-                    "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
-                    "requires": {
-                        "buffer-from": "^1.0.0",
-                        "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=="
-                        }
-                    }
                 }
             }
         },
@@ -18122,24 +17845,6 @@
                 "terser": "^5.7.2"
             },
             "dependencies": {
-                "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"
-                    }
-                },
-                "ajv-keywords": {
-                    "version": "3.5.2",
-                    "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
-                    "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
-                    "dev": true
-                },
                 "schema-utils": {
                     "version": "3.1.1",
                     "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
@@ -18151,15 +17856,6 @@
                         "ajv-keywords": "^3.5.2"
                     }
                 },
-                "serialize-javascript": {
-                    "version": "6.0.0",
-                    "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
-                    "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
-                    "dev": true,
-                    "requires": {
-                        "randombytes": "^2.1.0"
-                    }
-                },
                 "source-map": {
                     "version": "0.6.1",
                     "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -18333,13 +18029,9 @@
             }
         },
         "tr46": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
-            "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
-            "dev": true,
-            "requires": {
-                "punycode": "^2.1.0"
-            }
+            "version": "0.0.3",
+            "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+            "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
         },
         "translate-google-api": {
             "version": "1.0.4",
@@ -18356,6 +18048,11 @@
                     "requires": {
                         "follow-redirects": "^1.10.0"
                     }
+                },
+                "follow-redirects": {
+                    "version": "1.14.9",
+                    "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
+                    "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w=="
                 }
             }
         },
@@ -18399,6 +18096,25 @@
                 "loader-utils": "^1.0.2",
                 "micromatch": "^3.1.4",
                 "semver": "^5.0.1"
+            },
+            "dependencies": {
+                "enhanced-resolve": {
+                    "version": "4.5.0",
+                    "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz",
+                    "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==",
+                    "dev": true,
+                    "requires": {
+                        "graceful-fs": "^4.1.2",
+                        "memory-fs": "^0.5.0",
+                        "tapable": "^1.0.0"
+                    }
+                },
+                "tapable": {
+                    "version": "1.1.3",
+                    "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+                    "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
+                    "dev": true
+                }
             }
         },
         "ts-node": {
@@ -18499,6 +18215,13 @@
                         "to-regex-range": "^5.0.1"
                     }
                 },
+                "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
+                },
                 "glob-parent": {
                     "version": "5.1.2",
                     "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
@@ -18599,10 +18322,9 @@
             }
         },
         "tslib": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
-            "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==",
-            "dev": true
+            "version": "2.3.1",
+            "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
+            "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
         },
         "tslint": {
             "version": "5.20.1",
@@ -18625,11 +18347,29 @@
                 "tsutils": "^2.29.0"
             },
             "dependencies": {
+                "builtin-modules": {
+                    "version": "1.1.1",
+                    "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+                    "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+                    "dev": true
+                },
+                "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
+                },
                 "diff": {
                     "version": "4.0.2",
                     "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
                     "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
                     "dev": true
+                },
+                "tslib": {
+                    "version": "1.14.1",
+                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+                    "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+                    "dev": true
                 }
             }
         },
@@ -18669,6 +18409,14 @@
             "dev": true,
             "requires": {
                 "tslib": "^1.8.1"
+            },
+            "dependencies": {
+                "tslib": {
+                    "version": "1.14.1",
+                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+                    "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+                    "dev": true
+                }
             }
         },
         "tunnel-agent": {
@@ -18684,12 +18432,6 @@
             "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
             "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
         },
-        "type": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
-            "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
-            "dev": true
-        },
         "type-check": {
             "version": "0.3.2",
             "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
@@ -18724,9 +18466,9 @@
             "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
         },
         "typescript": {
-            "version": "4.6.2",
-            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz",
-            "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==",
+            "version": "4.6.3",
+            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
+            "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
             "dev": true
         },
         "typescript-collections": {
@@ -18748,6 +18490,11 @@
                 "vscode-uri": "^1.0.5"
             },
             "dependencies": {
+                "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=="
+                },
                 "fs-extra": {
                     "version": "7.0.1",
                     "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
@@ -18774,9 +18521,9 @@
             "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0="
         },
         "ua-parser-js": {
-            "version": "0.7.21",
-            "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz",
-            "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ=="
+            "version": "0.7.31",
+            "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz",
+            "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ=="
         },
         "uglify-js": {
             "version": "2.8.29",
@@ -18831,9 +18578,9 @@
             }
         },
         "uid2": {
-            "version": "0.0.3",
-            "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz",
-            "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I="
+            "version": "0.0.4",
+            "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz",
+            "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA=="
         },
         "unbox-primitive": {
             "version": "1.0.1",
@@ -18844,13 +18591,6 @@
                 "has-bigints": "^1.0.1",
                 "has-symbols": "^1.0.2",
                 "which-boxed-primitive": "^1.0.2"
-            },
-            "dependencies": {
-                "has-symbols": {
-                    "version": "1.0.3",
-                    "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
-                    "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
-                }
             }
         },
         "unbzip2-stream": {
@@ -18863,32 +18603,14 @@
             }
         },
         "undefsafe": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz",
-            "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==",
-            "requires": {
-                "debug": "^2.2.0"
-            },
-            "dependencies": {
-                "debug": {
-                    "version": "2.6.9",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-                    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-                    "requires": {
-                        "ms": "2.0.0"
-                    }
-                },
-                "ms": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
-                }
-            }
+            "version": "2.0.5",
+            "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
+            "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA=="
         },
         "underscore": {
-            "version": "1.10.2",
-            "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz",
-            "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg=="
+            "version": "1.13.2",
+            "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.2.tgz",
+            "integrity": "sha512-ekY1NhRzq0B08g4bGuX4wd2jZx5GnKz6mKSqFL4nqBlfyMGiG10gDFhDTMEfYmDL6Jy0FUIZp7wiRB+0BP7J2g=="
         },
         "unicode-trie": {
             "version": "0.3.1",
@@ -18915,21 +18637,8 @@
                 "get-value": "^2.0.6",
                 "is-extendable": "^0.1.1",
                 "set-value": "^2.0.1"
-            },
-            "dependencies": {
-                "is-extendable": {
-                    "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-                    "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
-                }
             }
         },
-        "uniq": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz",
-            "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=",
-            "dev": true
-        },
         "unique-filename": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
@@ -19055,9 +18764,9 @@
             }
         },
         "uri-js": {
-            "version": "4.2.2",
-            "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
-            "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+            "version": "4.4.1",
+            "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+            "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
             "requires": {
                 "punycode": "^2.1.0"
             }
@@ -19096,19 +18805,9 @@
             },
             "dependencies": {
                 "mime": {
-                    "version": "2.4.4",
-                    "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
-                    "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
-                },
-                "schema-utils": {
-                    "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
-                    "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
-                    "requires": {
-                        "ajv": "^6.1.0",
-                        "ajv-errors": "^1.0.0",
-                        "ajv-keywords": "^3.1.0"
-                    }
+                    "version": "2.6.0",
+                    "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+                    "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg=="
                 }
             }
         },
@@ -19146,13 +18845,6 @@
             "integrity": "sha512-7/hqDrWa0iMnCoET9W1T07EmD4Eg/Wmoj/X8TGBc++ECRK4m5yTsjP4O6s0yagbxfqIOuUkIxe2/sA+VR2GxZA==",
             "requires": {
                 "fast-deep-equal": "^3.1.3"
-            },
-            "dependencies": {
-                "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=="
-                }
             }
         },
         "use-memo-one": {
@@ -19230,6 +18922,13 @@
                 "assert-plus": "^1.0.0",
                 "core-util-is": "1.0.2",
                 "extsprintf": "^1.2.0"
+            },
+            "dependencies": {
+                "core-util-is": {
+                    "version": "1.0.2",
+                    "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+                    "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+                }
             }
         },
         "void-elements": {
@@ -19238,9 +18937,9 @@
             "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w="
         },
         "vscode-jsonrpc": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz",
-            "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A=="
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz",
+            "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg=="
         },
         "vscode-languageserver": {
             "version": "5.3.0-next.10",
@@ -19252,18 +18951,18 @@
             }
         },
         "vscode-languageserver-protocol": {
-            "version": "3.15.3",
-            "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz",
-            "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==",
+            "version": "3.16.0",
+            "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz",
+            "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==",
             "requires": {
-                "vscode-jsonrpc": "^5.0.1",
-                "vscode-languageserver-types": "3.15.1"
+                "vscode-jsonrpc": "6.0.0",
+                "vscode-languageserver-types": "3.16.0"
             }
         },
         "vscode-languageserver-types": {
-            "version": "3.15.1",
-            "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz",
-            "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ=="
+            "version": "3.16.0",
+            "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz",
+            "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA=="
         },
         "vscode-textbuffer": {
             "version": "1.0.0",
@@ -19276,9 +18975,9 @@
             "integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ=="
         },
         "vue-template-compiler": {
-            "version": "2.6.11",
-            "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz",
-            "integrity": "sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA==",
+            "version": "2.6.14",
+            "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz",
+            "integrity": "sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g==",
             "requires": {
                 "de-indent": "^1.0.2",
                 "he": "^1.1.0"
@@ -19307,6 +19006,14 @@
                 "domexception": "^1.0.1",
                 "webidl-conversions": "^4.0.2",
                 "xml-name-validator": "^3.0.0"
+            },
+            "dependencies": {
+                "webidl-conversions": {
+                    "version": "4.0.2",
+                    "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
+                    "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
+                    "dev": true
+                }
             }
         },
         "walkdir": {
@@ -19350,20 +19057,19 @@
             }
         },
         "web-streams-polyfill": {
-            "version": "3.2.0",
-            "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz",
-            "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA=="
+            "version": "3.2.1",
+            "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
+            "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q=="
         },
         "webidl-conversions": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
-            "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
-            "dev": true
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+            "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
         },
         "webpack": {
-            "version": "5.69.1",
-            "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.69.1.tgz",
-            "integrity": "sha512-+VyvOSJXZMT2V5vLzOnDuMz5GxEqLk7hKWQ56YxPW/PQRUuKimPqmEIJOx8jHYeyo65pKbapbW464mvsKbaj4A==",
+            "version": "5.72.0",
+            "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.0.tgz",
+            "integrity": "sha512-qmSmbspI0Qo5ld49htys8GY9XhS9CGqFoHTsOVAnjBdg0Zn79y135R+k4IR4rKK6+eKaabMhJwiVB7xw0SJu5w==",
             "dev": true,
             "requires": {
                 "@types/eslint-scope": "^3.7.3",
@@ -19375,7 +19081,7 @@
                 "acorn-import-assertions": "^1.7.6",
                 "browserslist": "^4.14.5",
                 "chrome-trace-event": "^1.0.2",
-                "enhanced-resolve": "^5.8.3",
+                "enhanced-resolve": "^5.9.2",
                 "es-module-lexer": "^0.9.0",
                 "eslint-scope": "5.1.1",
                 "events": "^3.2.0",
@@ -19392,52 +19098,6 @@
                 "webpack-sources": "^3.2.3"
             },
             "dependencies": {
-                "acorn": {
-                    "version": "8.7.0",
-                    "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
-                    "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
-                    "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"
-                    }
-                },
-                "ajv-keywords": {
-                    "version": "3.5.2",
-                    "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
-                    "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
-                    "dev": true
-                },
-                "enhanced-resolve": {
-                    "version": "5.9.1",
-                    "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.1.tgz",
-                    "integrity": "sha512-jdyZMwCQ5Oj4c5+BTnkxPgDZO/BJzh/ADDmKebayyzNwjVX1AFCeGkOfxNx0mHi2+8BKC5VxUYiw3TIvoT7vhw==",
-                    "dev": true,
-                    "requires": {
-                        "graceful-fs": "^4.2.4",
-                        "tapable": "^2.2.0"
-                    }
-                },
-                "graceful-fs": {
-                    "version": "4.2.9",
-                    "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-                    "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-                    "dev": true
-                },
-                "neo-async": {
-                    "version": "2.6.2",
-                    "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
-                    "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
-                    "dev": true
-                },
                 "schema-utils": {
                     "version": "3.1.1",
                     "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
@@ -19448,12 +19108,6 @@
                         "ajv": "^6.12.5",
                         "ajv-keywords": "^3.5.2"
                     }
-                },
-                "tapable": {
-                    "version": "2.2.1",
-                    "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
-                    "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
-                    "dev": true
                 }
             }
         },
@@ -19507,29 +19161,6 @@
                         "strip-final-newline": "^2.0.0"
                     }
                 },
-                "find-up": {
-                    "version": "4.1.0",
-                    "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
-                    "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
-                    "requires": {
-                        "locate-path": "^5.0.0",
-                        "path-exists": "^4.0.0"
-                    }
-                },
-                "get-stream": {
-                    "version": "6.0.1",
-                    "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
-                    "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="
-                },
-                "import-local": {
-                    "version": "3.1.0",
-                    "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
-                    "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
-                    "requires": {
-                        "pkg-dir": "^4.2.0",
-                        "resolve-cwd": "^3.0.0"
-                    }
-                },
                 "interpret": {
                     "version": "2.2.0",
                     "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz",
@@ -19540,14 +19171,6 @@
                     "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
                     "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="
                 },
-                "locate-path": {
-                    "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
-                    "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
-                    "requires": {
-                        "p-locate": "^4.1.0"
-                    }
-                },
                 "npm-run-path": {
                     "version": "4.0.1",
                     "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
@@ -19556,32 +19179,11 @@
                         "path-key": "^3.0.0"
                     }
                 },
-                "p-locate": {
-                    "version": "4.1.0",
-                    "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
-                    "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
-                    "requires": {
-                        "p-limit": "^2.2.0"
-                    }
-                },
-                "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=="
-                },
                 "path-key": {
                     "version": "3.1.1",
                     "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
                     "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
                 },
-                "pkg-dir": {
-                    "version": "4.2.0",
-                    "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
-                    "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
-                    "requires": {
-                        "find-up": "^4.0.0"
-                    }
-                },
                 "rechoir": {
                     "version": "0.7.1",
                     "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
@@ -19590,19 +19192,6 @@
                         "resolve": "^1.9.0"
                     }
                 },
-                "resolve-cwd": {
-                    "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
-                    "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
-                    "requires": {
-                        "resolve-from": "^5.0.0"
-                    }
-                },
-                "resolve-from": {
-                    "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
-                    "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="
-                },
                 "shebang-command": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -19639,9 +19228,9 @@
             },
             "dependencies": {
                 "ajv": {
-                    "version": "8.10.0",
-                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz",
-                    "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==",
+                    "version": "8.11.0",
+                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
+                    "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
                     "requires": {
                         "fast-deep-equal": "^3.1.1",
                         "json-schema-traverse": "^1.0.0",
@@ -19655,13 +19244,6 @@
                     "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
                     "requires": {
                         "fast-deep-equal": "^3.1.3"
-                    },
-                    "dependencies": {
-                        "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=="
-                        }
                     }
                 },
                 "json-schema-traverse": {
@@ -19669,19 +19251,6 @@
                     "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
                     "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
                 },
-                "mime-db": {
-                    "version": "1.51.0",
-                    "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
-                    "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
-                },
-                "mime-types": {
-                    "version": "2.1.34",
-                    "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
-                    "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
-                    "requires": {
-                        "mime-db": "1.51.0"
-                    }
-                },
                 "schema-utils": {
                     "version": "4.0.0",
                     "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz",
@@ -19743,14 +19312,24 @@
                     "dev": true
                 },
                 "debug": {
-                    "version": "4.3.3",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
-                    "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+                    "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"
                     }
                 },
+                "import-local": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
+                    "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
+                    "dev": true,
+                    "requires": {
+                        "pkg-dir": "^3.0.0",
+                        "resolve-cwd": "^2.0.0"
+                    }
+                },
                 "memory-fs": {
                     "version": "0.4.1",
                     "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
@@ -19773,6 +19352,15 @@
                     "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
                     "dev": true
                 },
+                "pkg-dir": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+                    "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+                    "dev": true,
+                    "requires": {
+                        "find-up": "^3.0.0"
+                    }
+                },
                 "readable-stream": {
                     "version": "2.3.7",
                     "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -19788,6 +19376,21 @@
                         "util-deprecate": "~1.0.1"
                     }
                 },
+                "resolve-cwd": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
+                    "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+                    "dev": true,
+                    "requires": {
+                        "resolve-from": "^3.0.0"
+                    }
+                },
+                "resolve-from": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+                    "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+                    "dev": true
+                },
                 "semver": {
                     "version": "6.3.0",
                     "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -19865,9 +19468,9 @@
                     "dev": true
                 },
                 "html-entities": {
-                    "version": "2.3.2",
-                    "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz",
-                    "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==",
+                    "version": "2.3.3",
+                    "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz",
+                    "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==",
                     "dev": true
                 },
                 "strip-ansi": {
@@ -19941,12 +19544,23 @@
             "dev": true,
             "requires": {
                 "iconv-lite": "0.4.24"
+            },
+            "dependencies": {
+                "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"
+                    }
+                }
             }
         },
         "whatwg-fetch": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz",
-            "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q=="
+            "version": "3.6.2",
+            "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz",
+            "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA=="
         },
         "whatwg-mimetype": {
             "version": "2.3.0",
@@ -19955,14 +19569,12 @@
             "dev": true
         },
         "whatwg-url": {
-            "version": "7.1.0",
-            "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
-            "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
-            "dev": true,
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+            "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
             "requires": {
-                "lodash.sortby": "^4.7.0",
-                "tr46": "^1.0.1",
-                "webidl-conversions": "^4.0.2"
+                "tr46": "~0.0.3",
+                "webidl-conversions": "^3.0.0"
             }
         },
         "which": {
@@ -19991,9 +19603,9 @@
             "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
         },
         "which-pm-runs": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
-            "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs="
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz",
+            "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA=="
         },
         "which-typed-array": {
             "version": "1.1.7",
@@ -20006,88 +19618,6 @@
                 "foreach": "^2.0.5",
                 "has-tostringtag": "^1.0.0",
                 "is-typed-array": "^1.1.7"
-            },
-            "dependencies": {
-                "es-abstract": {
-                    "version": "1.19.1",
-                    "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz",
-                    "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==",
-                    "requires": {
-                        "call-bind": "^1.0.2",
-                        "es-to-primitive": "^1.2.1",
-                        "function-bind": "^1.1.1",
-                        "get-intrinsic": "^1.1.1",
-                        "get-symbol-description": "^1.0.0",
-                        "has": "^1.0.3",
-                        "has-symbols": "^1.0.2",
-                        "internal-slot": "^1.0.3",
-                        "is-callable": "^1.2.4",
-                        "is-negative-zero": "^2.0.1",
-                        "is-regex": "^1.1.4",
-                        "is-shared-array-buffer": "^1.0.1",
-                        "is-string": "^1.0.7",
-                        "is-weakref": "^1.0.1",
-                        "object-inspect": "^1.11.0",
-                        "object-keys": "^1.1.1",
-                        "object.assign": "^4.1.2",
-                        "string.prototype.trimend": "^1.0.4",
-                        "string.prototype.trimstart": "^1.0.4",
-                        "unbox-primitive": "^1.0.1"
-                    }
-                },
-                "has-symbols": {
-                    "version": "1.0.3",
-                    "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
-                    "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
-                },
-                "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-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"
-                    }
-                },
-                "object-inspect": {
-                    "version": "1.12.0",
-                    "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
-                    "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g=="
-                },
-                "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"
-                    }
-                },
-                "string.prototype.trimend": {
-                    "version": "1.0.4",
-                    "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
-                    "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
-                    "requires": {
-                        "call-bind": "^1.0.2",
-                        "define-properties": "^1.1.3"
-                    }
-                },
-                "string.prototype.trimstart": {
-                    "version": "1.0.4",
-                    "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
-                    "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
-                    "requires": {
-                        "call-bind": "^1.0.2",
-                        "define-properties": "^1.1.3"
-                    }
-                }
             }
         },
         "wide-align": {
@@ -20133,6 +19663,13 @@
             "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": "sha1-ReN/s56No/JbruP/U2niu18iAXo="
+                }
             }
         },
         "word-wrap": {
@@ -20185,9 +19722,9 @@
             },
             "dependencies": {
                 "ansi-regex": {
-                    "version": "4.1.0",
-                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-                    "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+                    "version": "4.1.1",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+                    "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="
                 },
                 "string-width": {
                     "version": "3.1.0",
@@ -20225,9 +19762,9 @@
             }
         },
         "ws": {
-            "version": "7.2.5",
-            "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz",
-            "integrity": "sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA=="
+            "version": "7.5.7",
+            "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz",
+            "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A=="
         },
         "xdg-basedir": {
             "version": "3.0.0",
@@ -20291,14 +19828,14 @@
             "dev": true
         },
         "y18n": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
-            "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
+            "version": "4.0.3",
+            "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+            "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
         },
         "yallist": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
-            "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+            "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
         },
         "yaml": {
             "version": "1.10.2",
@@ -20323,9 +19860,9 @@
             },
             "dependencies": {
                 "ansi-regex": {
-                    "version": "4.1.0",
-                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-                    "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+                    "version": "4.1.1",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+                    "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="
                 },
                 "string-width": {
                     "version": "3.1.0",
@@ -20397,9 +19934,9 @@
             }
         },
         "zustand": {
-            "version": "3.7.1",
-            "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.1.tgz",
-            "integrity": "sha512-wHBCZlKj+bg03/hP+Tzv24YhnqqP8MCeN9ECPDXoF01062SIbnfl3j9O0znkDw1lNTY0a8WN3F///a0UhhaEqg=="
+            "version": "3.7.2",
+            "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz",
+            "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA=="
         }
     }
 }
diff --git a/src/client/views/nodes/RecordingBox/ProgressBar.tsx b/src/client/views/nodes/RecordingBox/ProgressBar.tsx
index da5fa2b00..82d5e1f04 100644
--- a/src/client/views/nodes/RecordingBox/ProgressBar.tsx
+++ b/src/client/views/nodes/RecordingBox/ProgressBar.tsx
@@ -5,42 +5,41 @@ import "./ProgressBar.scss"
 interface ProgressBarProps {
       progress: number,
       marks: number[],
-      playSegment: (idx: number) => void
 }
 
 export function ProgressBar(props: ProgressBarProps) {
 
-      const handleClick = (e: React.MouseEvent) => {
-            let progressbar = document.getElementById('progressbar')!
-            let bounds = progressbar!.getBoundingClientRect();
-            let x = e.clientX - bounds.left;
-            let percent = x / progressbar.clientWidth * 100
-            
-            for (let i = 0; i < props.marks.length; i++) {
-                  let start = i == 0 ? 0 : props.marks[i-1];
-                  if (percent > start && percent < props.marks[i]) {
-                        props.playSegment(i)
-                        // console.log(i)
-                        // console.log(percent)
-                        // console.log(props.marks[i])
-                        break
-                  }
-            }
-      }
+      // const handleClick = (e: React.MouseEvent) => {
+      //       let progressbar = document.getElementById('progressbar')!
+      //       let bounds = progressbar!.getBoundingClientRect();
+      //       let x = e.clientX - bounds.left;
+      //       let percent = x / progressbar.clientWidth * 100
 
-      return(
+      //       for (let i = 0; i < props.marks.length; i++) {
+      //             let start = i == 0 ? 0 : props.marks[i-1];
+      //             if (percent > start && percent < props.marks[i]) {
+      //                   props.playSegment(i)
+      //                   // console.log(i)
+      //                   // console.log(percent)
+      //                   // console.log(props.marks[i])
+      //                   break
+      //             }
+      //       }
+      // }
+
+      return (
             <div className="progressbar" id="progressbar">
-                  <div 
+                  <div
                         className="progressbar done"
                         style={{ width: `${props.progress}%` }}
-                        onClick={handleClick}
+                  // onClick={handleClick}
                   ></div>
                   {props.marks.map((mark) => {
-                        return <div 
-                                    className="progressbar mark"
-                                    style={{ width: `${mark}%` }}
-                              ></div>
+                        return <div
+                              className="progressbar mark"
+                              style={{ width: `${mark}%` }}
+                        ></div>
                   })}
-          </div>
+            </div>
       )
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.scss b/src/client/views/nodes/RecordingBox/RecordingView.scss
index 2eaf5468d..e4d971d51 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.scss
+++ b/src/client/views/nodes/RecordingBox/RecordingView.scss
@@ -1,207 +1,188 @@
 video {
-  flex: 100%;
-  width: 100%;
-  min-height: 400px;
-  height: auto;
-  display: block;
-  background-color: black;  
+      flex: 100%;
+      width: 100%;
+      min-height: 400px;
+      height: auto;
+      display: block;
+      background-color: black;
 }
 
-button { margin: 0 .5rem }
+button {
+      margin: 0 .5rem
+}
 
 .recording-container {
-  height: 100%;
-  width: 100%;
-  display: flex;
+      height: 100%;
+      width: 100%;
+      display: flex;
 }
 
 .video-wrapper {
-  max-width: 600px;
-  max-width: 700px;
-  position: relative;
-  display: flex;
-  justify-content: center;
-  overflow: hidden;
-  border-radius: 10px;
+      max-width: 600px;
+      max-width: 700px;
+      position: relative;
+      display: flex;
+      justify-content: center;
+      overflow: hidden;
+      border-radius: 10px;
 }
 
 .video-wrapper:hover .controls {
-  bottom: 30px;
-  transform: translateY(0%);
-  opacity: 100%;
+      bottom: 30px;
+      transform: translateY(0%);
+      opacity: 100%;
 }
 
 .controls {
-  display: flex;
-  align-items: center;
-  justify-content: space-evenly;
-  position: absolute;
-  padding: 14px;
-  width: 100%;
-  max-width: 500px;
-  flex-wrap: wrap;
-  background: rgba(255, 255, 255, 0.25);
-  box-shadow: 0 8px 32px 0 rgba(255, 255, 255, 0.1);
-  backdrop-filter: blur(4px);
-  border-radius: 10px;
-  border: 1px solid rgba(255, 255, 255, 0.18);
-  // transform: translateY(150%);
-  transition: all 0.3s ease-in-out;
-  // opacity: 0%;
-  bottom: 30px;
-  // bottom: -150px;
+      display: flex;
+      align-items: center;
+      justify-content: space-evenly;
+      position: absolute;
+      padding: 14px;
+      width: 100%;
+      max-width: 500px;
+      max-height: 20%;
+      flex-wrap: wrap;
+      background: rgba(255, 255, 255, 0.25);
+      box-shadow: 0 8px 32px 0 rgba(255, 255, 255, 0.1);
+      backdrop-filter: blur(4px);
+      border-radius: 10px;
+      border: 1px solid rgba(255, 255, 255, 0.18);
+      // transform: translateY(150%);
+      transition: all 0.3s ease-in-out;
+      // opacity: 0%;
+      bottom: 30px;
+      // bottom: -150px;
 }
 
 .actions button {
-  background: none;
-  border: none;
-  outline: none;
-  cursor: pointer;
+      background: none;
+      border: none;
+      outline: none;
+      cursor: pointer;
 }
 
 .actions button i {
-  background-color: none;
-  color: white;
-  font-size: 30px;
+      background-color: none;
+      color: white;
+      font-size: 30px;
 }
 
-// input[type="range"] {
-//   -webkit-appearance: none !important;
-//   background: rgba(255, 255, 255, 0.2);
-//   border-radius: 20px;
-//   height: 4px;
-//   width: 350px;
-// }
-
-// input[type="range"]::-webkit-slider-thumb {
-//   -webkit-appearance: none !important;
-//   cursor: pointer;
-//   height: 6px;
-// }
-
-// input[type="range"]::-moz-range-progress {
-//   background: white;
-// }
 
 .velocity {
-  appearance: none;
-  background: none;
-  color: white;
-  outline: none;
-  border: none;
-  text-align: center;
-  font-size: 16px;
+      appearance: none;
+      background: none;
+      color: white;
+      outline: none;
+      border: none;
+      text-align: center;
+      font-size: 16px;
 }
 
 .mute-btn {
-  background: none;
-  border: none;
-  outline: none;
-  cursor: pointer;
+      background: none;
+      border: none;
+      outline: none;
+      cursor: pointer;
 }
 
 .mute-btn i {
-  background-color: none;
-  color: white;
-  font-size: 20px;
+      background-color: none;
+      color: white;
+      font-size: 20px;
 }
 
 .recording-sign {
-  height: 20px;
-  width: auto;
-  display: flex;
-  flex-direction: row;
-  position: absolute;
-  top: 10px; 
-  right: 15px; 
-  align-items: center;
-  justify-content: center;
-
-  .timer {
-    font-size: 15px;
-    color: white;
-    margin: 0;
-  }
-
-  .dot {
-    height: 15px;
-    width: 15px;
-    margin: 5px;
-    background-color: red;
-    border-radius: 50%;
-    display: inline-block;
-  }
+      height: 20px;
+      width: auto;
+      display: flex;
+      flex-direction: row;
+      position: absolute;
+      top: 10px;
+      right: 15px;
+      align-items: center;
+      justify-content: center;
+
+      .timer {
+            font-size: 15px;
+            color: white;
+            margin: 0;
+      }
+
+      .dot {
+            height: 15px;
+            width: 15px;
+            margin: 5px;
+            background-color: red;
+            border-radius: 50%;
+            display: inline-block;
+      }
 }
 
 .controls-inner-container {
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  width: 100%;
+      display: flex;
+      flex-direction: row;
+      justify-content: center;
+      width: 100%;
 
 }
 
 .record-button-wrapper {
-  width: 35px;
-	height: 35px;
-	font-size: 0;
-	background-color: grey;
-	border: 0px;
-	border-radius: 35px;
-	margin: 10px;
-
-  .record-button {
-    position: relative;
-    background-color: red;
-    border: 0px;
-    border-radius: 50%;
-    height: 28px;
-    width: 28px;
-    top: 50%;
-    left: 50%;
-    margin: -14px 0px 0px -14px;
-  
-    &:hover {
-      width: 30px;
-      height: 30px;
-      margin: -15px 0px 0px -15px;
-    }
-  }
-
-  .stop-button{
-    position: relative;
-    background-color: red;
-    border: 0px;
-    border-radius: 10%;
-    height: 18px;
-    width: 18px;
-    top: 50%;
-    left: 50%;
-    margin: -9px 0px 0px -9px;
-  
-    // &:hover {
-    //   width: 40px;
-    //   height: 40px
-    // }
-  }
+      width: 35px;
+      height: 35px;
+      font-size: 0;
+      background-color: grey;
+      border: 0px;
+      border-radius: 35px;
+      margin: 10px;
+      display: flex;
+      justify-content: center;
+
+      .record-button {
+            background-color: red;
+            border: 0px;
+            border-radius: 50%;
+            height: 80%;
+            width: 80%;
+            align-self: center;
+            margin: 0;
+
+            &:hover {
+                  height: 85%;
+                  width: 85%;
+            }
+      }
+
+      .stop-button {
+            background-color: red;
+            border: 0px;
+            border-radius: 10%;
+            height: 80%;
+            width: 80%;
+            align-self: center;
+            margin: 0;
+
+
+            // &:hover {
+            //   width: 40px;
+            //   height: 40px
+            // }
+      }
 
 }
 
 .video-edit-wrapper {
-  height: 100%;
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-  position: absolute;
-  top: 0;
-  bottom: 0;
-  right: 50% - 15;
-
-  .video-edit-buttons {
-    margin: 0 5px;
-  }
-
-}
-
-
-
+      height: 100%;
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      position: absolute;
+      top: 0;
+      bottom: 0;
+      right: 50% - 15;
+
+      .video-edit-buttons {
+            margin: 0 5px;
+      }
+
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 15f8c8626..905f87a1a 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -38,7 +38,7 @@ export function RecordingView() {
 
       const [finished, setFinished] = useState<Boolean>(false)
 
-      
+
 
       const DEFAULT_MEDIA_CONSTRAINTS = {
             video: {
@@ -55,7 +55,7 @@ export function RecordingView() {
       useEffect(() => {
 
             if (finished) {
-                  let allVideoChunks : any = []
+                  let allVideoChunks: any = []
                   console.log(videos)
                   videos.forEach((vid) => {
                         console.log(vid.chunks)
@@ -65,15 +65,24 @@ export function RecordingView() {
                   console.log(allVideoChunks)
 
                   const blob = new Blob(allVideoChunks, {
-                              type: 'video/webm'
+                        type: 'video/webm'
                   })
                   const blobUrl = URL.createObjectURL(blob)
 
                   videoElementRef.current!.srcObject = null
                   videoElementRef.current!.src = blobUrl
                   videoElementRef.current!.muted = false
+
+                  // upload data
+                  //       const [{ result }] = await Networking.UploadFilesToServer(e.data);
+                  // console.log("Data result", result);
+                  // if (!(result instanceof Error)) {
+                  //     this.props.Document[this.fieldKey] = new AudioField(result.accessPaths.agnostic.client);
+                  // }
+
+                  // change to one recording box
             }
-            
+
 
       }, [finished])
 
@@ -156,7 +165,7 @@ export function RecordingView() {
                   // if we have a last portion
                   if (chunks.length > 1) {
                         // append the current portion to the video pieces
-                        setVideos(videos => [...videos, {chunks: chunks, endTime: recordingTimerRef.current}]) 
+                        setVideos(videos => [...videos, { chunks: chunks, endTime: recordingTimerRef.current }])
                   }
 
                   // reset the temporary chunks
@@ -169,7 +178,7 @@ export function RecordingView() {
             recorder.current.onpause = (event: any) => {
                   // append the current portion to the video pieces
                   console.log(chunks)
-                  setVideos(videos => [...videos, {chunks: chunks, endTime: recordingTimerRef.current}])
+                  setVideos(videos => [...videos, { chunks: chunks, endTime: recordingTimerRef.current }])
 
                   // reset the temporary chunks
                   chunks = []
@@ -204,7 +213,7 @@ export function RecordingView() {
       }
 
       const startOrResume = () => {
-          console.log('[RecordingView.tsx] startOrResume')
+            console.log('[RecordingView.tsx] startOrResume')
             if (!recorder.current || recorder.current.state === "inactive") {
                   record();
             } else if (recorder.current.state === "paused") {
@@ -212,21 +221,21 @@ export function RecordingView() {
             }
       }
 
-      const playSegment = (idx: number) => {
-            console.log(idx)
-            let currentChunks = videos[idx].chunks
-            console.log(currentChunks)
+      // const playSegment = (idx: number) => {
+      //       console.log(idx)
+      //       let currentChunks = videos[idx].chunks
+      //       console.log(currentChunks)
 
-            const blob = new Blob(currentChunks, {
-                  type: 'video/webm'
-            })
-            const blobUrl = URL.createObjectURL(blob)
-            console.log(blobUrl)
+      //       const blob = new Blob(currentChunks, {
+      //             type: 'video/webm'
+      //       })
+      //       const blobUrl = URL.createObjectURL(blob)
+      //       console.log(blobUrl)
 
-            videoElementRef.current!.srcObject = null
-            videoElementRef.current!.src = blobUrl
-            videoElementRef.current!.muted = false
-      }
+      //       videoElementRef.current!.srcObject = null
+      //       videoElementRef.current!.src = blobUrl
+      //       videoElementRef.current!.muted = false
+      // }
 
       const clearPrevious = () => {
             const numVideos = videos.length
@@ -257,12 +266,12 @@ export function RecordingView() {
             const toTwoDigit = (digit: number) => {
                   return String(digit).length == 1 ? "0" + digit : digit
             }
-            const minutes = Math.floor(( milliseconds % (1000 * 60 * 60)) / (1000 * 60));
+            const minutes = Math.floor((milliseconds % (1000 * 60 * 60)) / (1000 * 60));
             const seconds = Math.floor((milliseconds % (1000 * 60)) / 1000);
             return toTwoDigit(minutes) + " : " + toTwoDigit(seconds);
       }
 
-      
+
 
 
       useEffect(() => {
@@ -279,37 +288,37 @@ export function RecordingView() {
                               onTimeUpdate={handleOnTimeUpdate}
                         />
                         <div className="recording-sign">
-                              <span className="dot"/>
+                              <span className="dot" />
                               <p className="timer">{millisecondToMinuteSecond(recordingTimer * 10)}</p>
                         </div>
                         <div className="controls">
-                              
+
                               <div className="controls-inner-container">
                                     <div className="record-button-wrapper">
-                                          {recording ? 
-                                          <button className="stop-button" onClick={pause}/> :
-                                          <button className="record-button" onClick={startOrResume}/>
+                                          {recording ?
+                                                <button className="stop-button" onClick={pause} /> :
+                                                <button className="record-button" onClick={startOrResume} />
                                           }
                                     </div>
-                                    {!recording && videos.length > 0 ? 
-
-                                    <div className="video-edit-wrapper">
-                                          <IconContext.Provider value={{ color: "grey", className: "video-edit-buttons" }}>
-                                                <MdBackspace onClick={clearPrevious}/>
-                                          </IconContext.Provider>
-                                          <IconContext.Provider value={{ color: "#cc1c08", className: "video-edit-buttons" }}>
-                                                <FaCheckCircle onClick={stop}/>
-                                          </IconContext.Provider>
-                                    </div>
-                                    
-                                     : <></>}
-                                    
+                                    {!recording && videos.length > 0 ?
+
+                                          <div className="video-edit-wrapper">
+                                                <IconContext.Provider value={{ color: "grey", className: "video-edit-buttons" }}>
+                                                      <MdBackspace onClick={clearPrevious} />
+                                                </IconContext.Provider>
+                                                <IconContext.Provider value={{ color: "#cc1c08", className: "video-edit-buttons" }}>
+                                                      <FaCheckCircle onClick={stop} />
+                                                </IconContext.Provider>
+                                          </div>
+
+                                          : <></>}
+
                               </div>
-                              
-                              <ProgressBar 
-                                    progress={progress} 
+
+                              <ProgressBar
+                                    progress={progress}
                                     marks={videos.map((elt) => elt.endTime / MAXTIME * 100)}
-                                    playSegment={playSegment}
+                              // playSegment={playSegment}
                               />
 
                               {/* <button className="mute-btn" onClick={() => setMuted(!muted)}>
-- 
cgit v1.2.3-70-g09d2


From fd43ece4b97073b81553b5e8a8394d4404011005 Mon Sep 17 00:00:00 2001
From: Michael Foiani <sotech117@michaels-mbp-3.devices.brown.edu>
Date: Thu, 21 Apr 2022 12:01:04 -0400
Subject: Adapting code

---
 src/client/apis/recording/recordingApi.tsx            |  2 ++
 src/client/views/nodes/RecordingBox/RecordingView.tsx | 13 ++++++++++---
 2 files changed, 12 insertions(+), 3 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/client/apis/recording/recordingApi.tsx b/src/client/apis/recording/recordingApi.tsx
index 55714f03b..97d4e2e7e 100644
--- a/src/client/apis/recording/recordingApi.tsx
+++ b/src/client/apis/recording/recordingApi.tsx
@@ -148,4 +148,6 @@ export function RecordingApi() {
         })
     }
 
+    return (<></>)
+
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 15f8c8626..9be972d53 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -6,6 +6,8 @@ import { MdBackspace } from 'react-icons/md';
 import { FaCheckCircle } from 'react-icons/fa';
 import { IconContext } from "react-icons";
 
+import { RecordingApi } from '../../../apis/recording/recordingApi';
+
 
 enum RecordingStatus {
       Recording,
@@ -36,7 +38,9 @@ export function RecordingView() {
       const recorder = useRef<MediaRecorder | null>(null);
       const videoElementRef = useRef<HTMLVideoElement | null>(null);
 
-      const [finished, setFinished] = useState<Boolean>(false)
+    const [finished, setFinished] = useState<Boolean>(false)
+    
+    const recordingApiRef = useRef<any | null>(null);
 
       
 
@@ -206,7 +210,8 @@ export function RecordingView() {
       const startOrResume = () => {
           console.log('[RecordingView.tsx] startOrResume')
             if (!recorder.current || recorder.current.state === "inactive") {
-                  record();
+                record();
+                recordingApiRef.current.startAndInit()
             } else if (recorder.current.state === "paused") {
                   recorder.current.resume();
             }
@@ -319,7 +324,9 @@ export function RecordingView() {
                                                 <i className="bx bxs-volume-mute"></i>
                                           )}
                                     </button>  */}
-                        </div>
+                  </div>
+                  
+                  <RecordingApi ref={recordingApiRef}></RecordingApi>
 
                   </div>
             </div>)
-- 
cgit v1.2.3-70-g09d2


From 0af393318adafa885d66c0fc43ffbf23f91e3c73 Mon Sep 17 00:00:00 2001
From: Michael Foiani <sotech117@michaels-mbp-3.devices.brown.edu>
Date: Thu, 21 Apr 2022 16:48:51 -0400
Subject: Integrate with jenny's videobox api

---
 src/client/apis/recording/RecordingApi.ts          | 153 +++++++++++++++++++++
 src/client/apis/recording/recordingApi.tsx         | 153 ---------------------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  27 +---
 .../views/nodes/RecordingBox/RecordingView.tsx     |  18 +--
 4 files changed, 167 insertions(+), 184 deletions(-)
 create mode 100644 src/client/apis/recording/RecordingApi.ts
 delete mode 100644 src/client/apis/recording/recordingApi.tsx

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/client/apis/recording/RecordingApi.ts b/src/client/apis/recording/RecordingApi.ts
new file mode 100644
index 000000000..64243e443
--- /dev/null
+++ b/src/client/apis/recording/RecordingApi.ts
@@ -0,0 +1,153 @@
+import { CollectionFreeFormView } from "../../views/collections/collectionFreeForm";
+import React, { useState } from "react";
+
+export namespace RecordingApi {
+
+    type Movement = {
+        time: number,
+        panX: number,
+        panY: number,
+    }
+
+    export type Presentation = {
+        movements: Array<Movement>
+        meta: Object,
+        startDate: Date | null,
+    }
+
+    const NULL_PRESENTATION = {
+        movements: [],
+        meta: {},
+        startDate: null,
+    }
+
+    const [currentPresentation, setCurrentPresenation] = useState<Presentation>(NULL_PRESENTATION)
+    const [isRecording, setIsRecording] = useState(false)
+    const [absoluteStart, setAbsoluteStart] = useState<number>(-1)
+
+    export const initAndStart = (meta?: Object): Error | undefined => {
+        // check if already init a presentation
+        if (currentPresentation.startDate !== null) {
+            console.error('[recordingApi.ts] start() failed: current presentation data exists. please call clear() first.')
+            return new Error('[recordingApi.ts] start()')
+        }
+
+        // (1a) get start date for presenation
+        const startDate = new Date()
+        // (1b) set start timestamp to absolute timestamp
+        setAbsoluteStart(startDate.getTime())
+
+        // TODO: (2) assign meta content
+
+        // (3) assign init values to currentPresenation
+        setCurrentPresenation({ ...currentPresentation, startDate })
+
+        // (4) set isRecording true to allow trackMovements
+        setIsRecording(true)
+    }
+
+    export const clear = (): Error | undefined => {
+        // TODO: maybe archive the data?
+        if (isRecording) {
+            console.error('[recordingApi.ts] clear() failed: currently recording presentation. call pause() or finish() first')
+            return new Error('[recordingApi.ts] clear()')
+        }
+        // clear presenation data
+        setCurrentPresenation(NULL_PRESENTATION)
+
+        // set isRecording false
+        setIsRecording(false)
+
+        // default absoluteStart
+        setAbsoluteStart(-1)
+    }
+
+    export const pause = (): Error | undefined => {
+        if (currentPresentation.startDate === null) {
+            console.error('[recordingApi.ts] pause() failed: no presentation started. try calling init() first')
+            return new Error('[recordingApi.ts] pause()')
+        }
+        // don't allow track movments
+        setIsRecording(false)
+
+        // set relativeStart to the pausedTimestamp
+        const timestamp = new Date().getTime()
+        setAbsoluteStart(timestamp)
+    }
+
+    export const resume = () => {
+        if (currentPresentation.startDate === null) {
+            console.error('[recordingApi.ts] resume() failed: no presentation started. try calling init() first')
+            return new Error('[recordingApi.ts] resume()')
+        }
+
+        const timestamp = new Date().getTime()
+        const startTimestamp = currentPresentation.startDate?.getTime()
+        if (!startTimestamp) {
+            console.error('[recordingApi.ts] resume() failed: no presentation data. try calling init() first')
+            return new Error('[recordingApi.ts] pause()')
+        }
+
+        setAbsoluteStart(prevTime => { 
+            // const relativeUnpause = timestamp - absoluteStart
+            // const timePaused = relativeUnpause - prevTime
+            // return timePaused + absoluteStart
+            const absoluteTimePaused = timestamp - prevTime
+            return absoluteTimePaused
+        })
+    }
+
+    export const finish = (): Error | Presentation => {
+        if (currentPresentation.movements === null) {
+            console.error('[recordingApi.ts] finish() failed: no presentation data. try calling init() first')
+            return new Error('[recordingApi.ts] finish()')
+        }
+
+        // make copy and clear this class's data
+        // const returnCopy = { ...currentPresentation }
+        // clear()
+
+        // // return the copy
+        // return returnCopy
+
+        return currentPresentation
+    }
+
+    export const trackMovements = (panX: number, panY: number): Error | undefined => {
+        // ensure we are recording
+        if (!isRecording) {
+            console.error('[recordingApi.ts] pause() failed: recording is paused()')
+            return new Error('[recordingApi.ts] pause()')
+        }
+
+        // get the relative time
+        const timestamp = new Date().getTime()
+        const relativeTime = timestamp - absoluteStart
+
+        // make new movement struct
+        const movement: Movement = { time: relativeTime, panX, panY }
+        
+        // add that movement struct to the current presentation data
+        setCurrentPresenation(prevPres => {
+            const movements = [...prevPres.movements, movement]
+            return {...prevPres, movements}
+        })
+    }
+
+    // TOOD: need to pause all intervals if possible lol
+    // TODO: extract this into different class with pause and resume recording
+    export const followMovements = (presentation: Presentation, docView: CollectionFreeFormView): void => {
+        const document = docView.Document
+
+        const { movements } = presentation
+        movements.forEach(movement => {
+            const { panX, panY, time } = movement
+            // set the pan to what was stored
+            setTimeout(() => {
+                document._panX = panX;
+                document._panY = panY;
+            }, time)
+        })
+    }
+
+}
\ No newline at end of file
diff --git a/src/client/apis/recording/recordingApi.tsx b/src/client/apis/recording/recordingApi.tsx
deleted file mode 100644
index 97d4e2e7e..000000000
--- a/src/client/apis/recording/recordingApi.tsx
+++ /dev/null
@@ -1,153 +0,0 @@
-import { CollectionFreeFormView } from "../../views/collections/collectionFreeForm";
-import React, { useState } from "react";
-
-export function RecordingApi() {
-
-    type Movement = {
-        time: number,
-        panX: number,
-        panY: number,
-    }
-
-    type Presentation = {
-        movements: Array<Movement>
-        meta: Object,
-        startDate: Date | null,
-    }
-
-    const NULL_PRESENTATION = {
-        movements: [],
-        meta: {},
-        startDate: null,
-    }
-
-    const [currentPresentation, setCurrentPresenation] = useState<Presentation>(NULL_PRESENTATION)
-    const [isRecording, setIsRecording] = useState(false)
-    const [absoluteStart, setAbsoluteStart] = useState<number>(-1)
-
-    const initAndStart = (view: CollectionFreeFormView, meta?: Object): Error | undefined => {
-        // check if already init a presentation
-        if (currentPresentation.startDate !== null) {
-            console.error('[recordingApi.ts] start() failed: current presentation data exists. please call clear() first.')
-            return new Error('[recordingApi.ts] start()')
-        }
-
-        // (1a) get start date for presenation
-        const startDate = new Date()
-        // (1b) set start timestamp to absolute timestamp
-        setAbsoluteStart(startDate.getTime())
-
-        // TODO: (2) assign meta content
-
-        // (3) assign init values to currentPresenation
-        setCurrentPresenation({ ...currentPresentation, startDate })
-
-        // (4) set isRecording true to allow trackMovements
-        setIsRecording(true)
-    }
-
-    const clear = (): Error | undefined => {
-        // TODO: maybe archive the data?
-        if (isRecording) {
-            console.error('[recordingApi.ts] clear() failed: currently recording presentation. call pause() or finish() first')
-            return new Error('[recordingApi.ts] clear()')
-        }
-        // clear presenation data
-        setCurrentPresenation(NULL_PRESENTATION)
-
-        // clear isRecording
-        setIsRecording(false)
-
-        // clear absoluteStart
-        setAbsoluteStart(-1)
-    }
-
-    const pause = (): Error | undefined => {
-        if (currentPresentation.startDate === null) {
-            console.error('[recordingApi.ts] pause() failed: no presentation started. try calling init() first')
-            return new Error('[recordingApi.ts] pause(): no presenation')
-        }
-        // don't allow track movments
-        setIsRecording(false)
-
-        // set relativeStart to the pausedTimestamp
-        const timestamp = new Date().getTime()
-        setAbsoluteStart(timestamp)
-    }
-
-    const resume = () => {
-        if (currentPresentation.startDate === null) {
-            console.error('[recordingApi.ts] resume() failed: no presentation started. try calling init() first')
-            return new Error('[recordingApi.ts] resume()')
-        }
-
-        const timestamp = new Date().getTime()
-        const startTimestamp = currentPresentation.startDate?.getTime()
-        if (!startTimestamp) {
-            console.error('[recordingApi.ts] resume() failed: no presentation data. try calling init() first')
-            return new Error('[recordingApi.ts] pause()')
-        }
-
-        setAbsoluteStart(prevTime => { 
-            // const relativeUnpause = timestamp - absoluteStart
-            // const timePaused = relativeUnpause - prevTime
-            // return timePaused + absoluteStart
-            const absoluteTimePaused = timestamp - prevTime
-            return absoluteTimePaused
-        })
-    }
-
-    const finish = (): Error | Presentation => {
-        if (currentPresentation.movements === null) {
-            console.error('[recordingApi.ts] finish() failed: no presentation data. try calling init() first')
-            return new Error('[recordingApi.ts] finish()')
-        }
-
-        // make copy and clear this class's data
-        const returnCopy = { ...currentPresentation }
-        clear()
-
-        // return the copy
-        return returnCopy
-    }
-
-    const trackMovements = (panX: number, panY: number): Error | undefined => {
-        // ensure we are recording
-        if (!isRecording) {
-             console.error('[recordingApi.ts] pause() failed: recording is paused()')
-            return new Error('[recordingApi.ts] pause()')
-        }
-
-        // get the relative time
-        const timestamp = new Date().getTime()
-        const relativeTime = timestamp - absoluteStart
-
-        // make new movement struct
-        const movement: Movement = { time: relativeTime, panX, panY }
-        
-        // add that movement struct to the current presentation data
-        setCurrentPresenation(prevPres => {
-            const movements = [...prevPres.movements, movement]
-            return {...prevPres, movements}
-        })
-    }
-
-    // TOOD: need to pause all intervals if possible lol
-    // TODO: extract this into different class with pause and resume recording
-    const followMovements = (presentation: Presentation, docView: CollectionFreeFormView): void => {
-        const document = docView.Document
-
-        const { movements } = presentation
-        movements.forEach(movement => {
-            const { panX, panY, time } = movement
-            // set the pan to what was stored
-            setTimeout(() => {
-                document._panX = panX;
-                document._panY = panY;
-            }, time)
-        })
-    }
-
-    return (<></>)
-
-}
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 6db2269c4..239aacd4f 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -51,6 +51,7 @@ import "./CollectionFreeFormView.scss";
 import { MarqueeView } from "./MarqueeView";
 import React = require("react");
 import e = require("connect-flash");
+import { RecordingApi } from "../../../apis/recording/RecordingApi";
 
 export const panZoomSchema = createSchema({
     _panX: "number",
@@ -959,36 +960,18 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         }
     }
 
-
-    followMovements = (): void => {
-        // need the first for subtraction
-        let first = null;
-
-        this.storedMovements.forEach(movement => {
-            if (first === null) first = movement.time;
-
-            // set the pan to what was stored
-            setTimeout(() => {
-                this.Document._panX = movement.panX;
-                this.Document._panY = movement.panY;
-            }, movement.time - first)
-        })
-
-        // for now, clear the movements
-        this.storedMovements = []
-    }
-
     @action
     setPan(panX: number, panY: number, panTime: number = 0, clamp: boolean = false) {
         // if not presenting, just retrace the movements
         if (Doc.UserDoc()?.presentationMode === 'watching') {
-            this.followMovements()
-            return;
+            // RecordingApi.followMovements(presentation, this)
+            return
         }
 
         if (Doc.UserDoc()?.presentationMode === 'recording') {
             // store as many movments as possible
-            this.storedMovements.push({time: new Date().getTime(), panX, panY})
+            // this.storedMovements.push({time: new Date().getTime(), panX, panY})
+            const err = RecordingApi.trackMovements(panX, panY)
         }
 
         if (!this.isAnnotationOverlay && clamp) {
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 9be972d53..8c1ab9e2b 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -6,7 +6,7 @@ import { MdBackspace } from 'react-icons/md';
 import { FaCheckCircle } from 'react-icons/fa';
 import { IconContext } from "react-icons";
 
-import { RecordingApi } from '../../../apis/recording/recordingApi';
+import { RecordingApi } from '../../../apis/recording/RecordingApi';
 
 
 enum RecordingStatus {
@@ -39,8 +39,6 @@ export function RecordingView() {
       const videoElementRef = useRef<HTMLVideoElement | null>(null);
 
     const [finished, setFinished] = useState<Boolean>(false)
-    
-    const recordingApiRef = useRef<any | null>(null);
 
       
 
@@ -75,7 +73,11 @@ export function RecordingView() {
 
                   videoElementRef.current!.srcObject = null
                   videoElementRef.current!.src = blobUrl
-                  videoElementRef.current!.muted = false
+                videoElementRef.current!.muted = false
+                
+                // clear the recording api
+                const presentation = RecordingApi.finish()
+                RecordingApi.clear()
             }
             
 
@@ -202,7 +204,8 @@ export function RecordingView() {
       const pause = () => {
             if (recorder.current) {
                   if (recorder.current.state === "recording") {
-                        recorder.current.pause();
+                      recorder.current.pause();
+                      const err = RecordingApi.pause()
                   }
             }
       }
@@ -211,7 +214,7 @@ export function RecordingView() {
           console.log('[RecordingView.tsx] startOrResume')
             if (!recorder.current || recorder.current.state === "inactive") {
                 record();
-                recordingApiRef.current.startAndInit()
+                const err = RecordingApi.initAndStart()
             } else if (recorder.current.state === "paused") {
                   recorder.current.resume();
             }
@@ -325,9 +328,6 @@ export function RecordingView() {
                                           )}
                                     </button>  */}
                   </div>
-                  
-                  <RecordingApi ref={recordingApiRef}></RecordingApi>
-
                   </div>
             </div>)
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From a5da5e6246a6fd7500fed8b206fc3540be509eab Mon Sep 17 00:00:00 2001
From: Jenny Yu <jennyyu212@outlook.com>
Date: Fri, 22 Apr 2022 19:53:44 -0400
Subject: uploading not working (cannot find ffmpeg)

---
 package-lock.json                                  |  18 +-
 package.json                                       |   1 +
 src/client/Network.ts                              |  77 +--
 src/client/views/OverlayView.scss                  |  70 +--
 src/client/views/OverlayView.tsx                   | 387 ++++++------
 .../views/nodes/RecordingBox/RecordingBox.tsx      |  37 +-
 .../views/nodes/RecordingBox/RecordingView.scss    |   5 +-
 .../views/nodes/RecordingBox/RecordingView.tsx     |  28 +-
 src/client/views/nodes/trails/PresElementBox.tsx   | 699 +++++++++++----------
 src/server/ApiManagers/UploadManager.ts            | 534 ++++++++--------
 10 files changed, 957 insertions(+), 899 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/package-lock.json b/package-lock.json
index 01763e9b6..0f045c546 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6535,6 +6535,14 @@
                 "pend": "~1.2.0"
             }
         },
+        "ffmpeg": {
+            "version": "0.0.4",
+            "resolved": "https://registry.npmjs.org/ffmpeg/-/ffmpeg-0.0.4.tgz",
+            "integrity": "sha1-HEYN+OfaUSf2LO70v6BsWciWMMs=",
+            "requires": {
+                "when": ">= 0.0.1"
+            }
+        },
         "file-loader": {
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz",
@@ -7961,13 +7969,14 @@
             "resolved": "https://registry.npmjs.org/image-size-stream/-/image-size-stream-1.1.0.tgz",
             "integrity": "sha1-Ivou2mbG31AQh0bacUkmSy0l+Gs=",
             "requires": {
+                "image-size": "github:netroy/image-size#da2c863807a3e9602617bdd357b0de3ab4a064c1",
                 "readable-stream": "^1.0.33",
                 "tryit": "^1.0.1"
             },
             "dependencies": {
                 "image-size": {
-                    "version": "git+https://github.com/netroy/image-size.git#da2c863807a3e9602617bdd357b0de3ab4a064c1",
-                    "from": "git+https://github.com/netroy/image-size.git#da2c863807a3e9602617bdd357b0de3ab4a064c1"
+                    "version": "github:netroy/image-size#da2c863807a3e9602617bdd357b0de3ab4a064c1",
+                    "from": "github:netroy/image-size#da2c863807a3e9602617bdd357b0de3ab4a064c1"
                 },
                 "isarray": {
                     "version": "0.0.1",
@@ -19577,6 +19586,11 @@
                 "webidl-conversions": "^3.0.0"
             }
         },
+        "when": {
+            "version": "3.7.8",
+            "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz",
+            "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I="
+        },
         "which": {
             "version": "1.3.1",
             "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
diff --git a/package.json b/package.json
index 35aa2ef92..6185bc0d7 100644
--- a/package.json
+++ b/package.json
@@ -175,6 +175,7 @@
         "express-session": "^1.17.2",
         "express-validator": "^5.3.1",
         "expressjs": "^1.0.1",
+        "ffmpeg": "0.0.4",
         "file-saver": "^2.0.5",
         "find-in-files": "^0.5.0",
         "fit-curve": "^0.1.7",
diff --git a/src/client/Network.ts b/src/client/Network.ts
index bf2918734..58f356c90 100644
--- a/src/client/Network.ts
+++ b/src/client/Network.ts
@@ -4,46 +4,49 @@ import { Upload } from "../server/SharedMediaTypes";
 
 export namespace Networking {
 
-    export async function FetchFromServer(relativeRoute: string) {
-        return (await fetch(relativeRoute)).text();
-    }
+      export async function FetchFromServer(relativeRoute: string) {
+            return (await fetch(relativeRoute)).text();
+      }
 
-    export async function PostToServer(relativeRoute: string, body?: any) {
-        const options = {
-            uri: Utils.prepend(relativeRoute),
-            method: "POST",
-            body,
-            json: true
-        };
-        return requestPromise.post(options);
-    }
+      export async function PostToServer(relativeRoute: string, body?: any) {
+            const options = {
+                  uri: Utils.prepend(relativeRoute),
+                  method: "POST",
+                  body,
+                  json: true
+            };
+            return requestPromise.post(options);
+      }
 
-    export async function UploadFilesToServer<T extends Upload.FileInformation = Upload.FileInformation>(files: File | File[]): Promise<Upload.FileResponse<T>[]> {
-        const formData = new FormData();
-        if (Array.isArray(files)) {
-            if (!files.length) {
-                return [];
+      export async function UploadFilesToServer<T extends Upload.FileInformation = Upload.FileInformation>(files: File | File[]): Promise<Upload.FileResponse<T>[]> {
+            console.log(files)
+            const formData = new FormData();
+            if (Array.isArray(files)) {
+                  if (!files.length) {
+                        return [];
+                  }
+                  files.forEach(file => formData.append(Utils.GenerateGuid(), file));
+            } else {
+                  formData.append(Utils.GenerateGuid(), files);
             }
-            files.forEach(file => formData.append(Utils.GenerateGuid(), file));
-        } else {
-            formData.append(Utils.GenerateGuid(), files);
-        }
-        const parameters = {
-            method: 'POST',
-            body: formData
-        };
-        const response = await fetch("/uploadFormData", parameters);
-        return response.json();
-    }
+            const parameters = {
+                  method: 'POST',
+                  body: formData
+            };
+            const response = await fetch("/uploadFormData", parameters);
+            console.log(response)
+            // console.log(response.json())
+            return response.json();
+      }
 
-    export async function UploadYoutubeToServer<T extends Upload.FileInformation = Upload.FileInformation>(videoId: string): Promise<Upload.FileResponse<T>[]> {
-        const parameters = {
-            method: 'POST',
-            body: JSON.stringify({ videoId }),
-            json: true
-        };
-        const response = await fetch("/uploadYoutubeVideo", parameters);
-        return response.json();
-    }
+      export async function UploadYoutubeToServer<T extends Upload.FileInformation = Upload.FileInformation>(videoId: string): Promise<Upload.FileResponse<T>[]> {
+            const parameters = {
+                  method: 'POST',
+                  body: JSON.stringify({ videoId }),
+                  json: true
+            };
+            const response = await fetch("/uploadYoutubeVideo", parameters);
+            return response.json();
+      }
 
 }
\ No newline at end of file
diff --git a/src/client/views/OverlayView.scss b/src/client/views/OverlayView.scss
index 02ea5e53b..d6a6e4301 100644
--- a/src/client/views/OverlayView.scss
+++ b/src/client/views/OverlayView.scss
@@ -1,59 +1,59 @@
 .overlayView {
-    position: absolute;
-    pointer-events: none;
-    top: 0;
-    width: 100vw;
-    height: 100vh;
-    /* background-color: pink; */
-    z-index: 100000;
+      position: absolute;
+      pointer-events: none;
+      top: 0;
+      width: 100vw;
+      height: 100vh;
+      /* background-color: pink; */
+      z-index: 100000;
 }
 
 .overlayWindow-outerDiv {
-    border-radius: 5px;
-    overflow: hidden;
-    display: flex;
-    flex-direction: column;
-    top: 0;
-    left: 0;
+      border-radius: 5px;
+      overflow: hidden;
+      display: flex;
+      flex-direction: column;
+      top: 0;
+      left: 0;
 }
 
 .overlayWindow-outerDiv,
 .overlayView-wrapperDiv {
-    position: absolute;
-    z-index: 1;
+      position: absolute;
+      z-index: 1;
 }
 
 .overlayWindow-titleBar {
-    flex: 0 1 30px;
-    background: darkslategray;
-    color: whitesmoke;
-    text-align: center;
-    cursor: move;
+      flex: 0 1 30px;
+      background: darkslategray;
+      color: whitesmoke;
+      text-align: center;
+      cursor: move;
 }
 
 .overlayWindow-content {
-    flex: 1 1 auto;
-    display: flex;
-    flex-direction: column;
+      flex: 1 1 auto;
+      display: flex;
+      flex-direction: column;
 }
 
 .overlayWindow-closeButton {
-    float: right;
-    height: 30px;
-    width: 30px;
+      float: right;
+      height: 30px;
+      width: 30px;
 }
 
 .overlayWindow-resizeDragger {
-    background-color: rgb(0, 0, 0);
-    position: absolute;
-    right: 0px;
-    bottom: 0px;
-    width: 10px;
-    height: 10px;
-    cursor: nwse-resize;
+      background-color: rgb(0, 0, 0);
+      position: absolute;
+      right: 0px;
+      bottom: 0px;
+      width: 10px;
+      height: 10px;
+      cursor: nwse-resize;
 }
 
 .overlayView-doc {
-    z-index: 9002; //so that it appears above chroma 
-    position: absolute;
+      z-index: 9002; //so that it appears above chroma 
+      position: absolute;
 }
\ No newline at end of file
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 0f51cf9b2..806abb990 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -20,212 +20,213 @@ import { DefaultStyleProvider } from "./StyleProvider";
 export type OverlayDisposer = () => void;
 
 export type OverlayElementOptions = {
-    x: number;
-    y: number;
-    width?: number;
-    height?: number;
-    title?: string;
+      x: number;
+      y: number;
+      width?: number;
+      height?: number;
+      title?: string;
 };
 
 export interface OverlayWindowProps {
-    children: JSX.Element;
-    overlayOptions: OverlayElementOptions;
-    onClick: () => void;
+      children: JSX.Element;
+      overlayOptions: OverlayElementOptions;
+      onClick: () => void;
 }
 
 @observer
 export class OverlayWindow extends React.Component<OverlayWindowProps> {
-    @observable x: number;
-    @observable y: number;
-    @observable width: number;
-    @observable height: number;
-    constructor(props: OverlayWindowProps) {
-        super(props);
-
-        const opts = props.overlayOptions;
-        this.x = opts.x;
-        this.y = opts.y;
-        this.width = opts.width || 200;
-        this.height = opts.height || 200;
-    }
-
-    onPointerDown = (_: React.PointerEvent) => {
-        document.removeEventListener("pointermove", this.onPointerMove);
-        document.removeEventListener("pointerup", this.onPointerUp);
-        document.addEventListener("pointermove", this.onPointerMove);
-        document.addEventListener("pointerup", this.onPointerUp);
-    }
-
-    onResizerPointerDown = (_: React.PointerEvent) => {
-        document.removeEventListener("pointermove", this.onResizerPointerMove);
-        document.removeEventListener("pointerup", this.onResizerPointerUp);
-        document.addEventListener("pointermove", this.onResizerPointerMove);
-        document.addEventListener("pointerup", this.onResizerPointerUp);
-    }
-
-    @action
-    onPointerMove = (e: PointerEvent) => {
-        this.x += e.movementX;
-        this.x = Math.max(Math.min(this.x, window.innerWidth - this.width), 0);
-        this.y += e.movementY;
-        this.y = Math.max(Math.min(this.y, window.innerHeight - this.height), 0);
-    }
-
-    @action
-    onResizerPointerMove = (e: PointerEvent) => {
-        this.width += e.movementX;
-        this.width = Math.max(this.width, 30);
-        this.height += e.movementY;
-        this.height = Math.max(this.height, 30);
-    }
-
-    onPointerUp = (e: PointerEvent) => {
-        document.removeEventListener("pointermove", this.onPointerMove);
-        document.removeEventListener("pointerup", this.onPointerUp);
-    }
-
-    onResizerPointerUp = (e: PointerEvent) => {
-        document.removeEventListener("pointermove", this.onResizerPointerMove);
-        document.removeEventListener("pointerup", this.onResizerPointerUp);
-    }
-
-    render() {
-        return (
-            <div className="overlayWindow-outerDiv" style={{ transform: `translate(${this.x}px, ${this.y}px)`, width: this.width, height: this.height }}>
-                <div className="overlayWindow-titleBar" onPointerDown={this.onPointerDown} >
-                    {this.props.overlayOptions.title || "Untitled"}
-                    <button onClick={this.props.onClick} className="overlayWindow-closeButton">X</button>
-                </div>
-                <div className="overlayWindow-content">
-                    {this.props.children}
-                </div>
-                <div className="overlayWindow-resizeDragger" onPointerDown={this.onResizerPointerDown}></div>
-            </div>
-        );
-    }
+      @observable x: number;
+      @observable y: number;
+      @observable width: number;
+      @observable height: number;
+      constructor(props: OverlayWindowProps) {
+            super(props);
+
+            const opts = props.overlayOptions;
+            this.x = opts.x;
+            this.y = opts.y;
+            this.width = opts.width || 200;
+            this.height = opts.height || 200;
+      }
+
+      onPointerDown = (_: React.PointerEvent) => {
+            document.removeEventListener("pointermove", this.onPointerMove);
+            document.removeEventListener("pointerup", this.onPointerUp);
+            document.addEventListener("pointermove", this.onPointerMove);
+            document.addEventListener("pointerup", this.onPointerUp);
+      }
+
+      onResizerPointerDown = (_: React.PointerEvent) => {
+            document.removeEventListener("pointermove", this.onResizerPointerMove);
+            document.removeEventListener("pointerup", this.onResizerPointerUp);
+            document.addEventListener("pointermove", this.onResizerPointerMove);
+            document.addEventListener("pointerup", this.onResizerPointerUp);
+      }
+
+      @action
+      onPointerMove = (e: PointerEvent) => {
+            this.x += e.movementX;
+            this.x = Math.max(Math.min(this.x, window.innerWidth - this.width), 0);
+            this.y += e.movementY;
+            this.y = Math.max(Math.min(this.y, window.innerHeight - this.height), 0);
+      }
+
+      @action
+      onResizerPointerMove = (e: PointerEvent) => {
+            this.width += e.movementX;
+            this.width = Math.max(this.width, 30);
+            this.height += e.movementY;
+            this.height = Math.max(this.height, 30);
+      }
+
+      onPointerUp = (e: PointerEvent) => {
+            document.removeEventListener("pointermove", this.onPointerMove);
+            document.removeEventListener("pointerup", this.onPointerUp);
+      }
+
+      onResizerPointerUp = (e: PointerEvent) => {
+            document.removeEventListener("pointermove", this.onResizerPointerMove);
+            document.removeEventListener("pointerup", this.onResizerPointerUp);
+      }
+
+      render() {
+            return (
+                  <div className="overlayWindow-outerDiv" style={{ transform: `translate(${this.x}px, ${this.y}px)`, width: this.width, height: this.height }}>
+                        <div className="overlayWindow-titleBar" onPointerDown={this.onPointerDown} >
+                              {this.props.overlayOptions.title || "Untitled"}
+                              <button onClick={this.props.onClick} className="overlayWindow-closeButton">X</button>
+                        </div>
+                        <div className="overlayWindow-content">
+                              {this.props.children}
+                        </div>
+                        <div className="overlayWindow-resizeDragger" onPointerDown={this.onResizerPointerDown}></div>
+                  </div>
+            );
+      }
 }
 
 @observer
 export class OverlayView extends React.Component {
-    public static Instance: OverlayView;
-    @observable.shallow
-    private _elements: JSX.Element[] = [];
-
-    constructor(props: any) {
-        super(props);
-        if (!OverlayView.Instance) {
-            OverlayView.Instance = this;
-        }
-    }
-
-    @action
-    addElement(ele: JSX.Element, options: OverlayElementOptions): OverlayDisposer {
-        const remove = action(() => {
-            const index = this._elements.indexOf(ele);
-            if (index !== -1) this._elements.splice(index, 1);
-        });
-        ele = <div key={Utils.GenerateGuid()} className="overlayView-wrapperDiv" style={{
-            transform: `translate(${options.x}px, ${options.y}px)`,
-            width: options.width,
-            height: options.height,
-            top: 0,
-            left: 0
-        }}>{ele}</div>;
-        this._elements.push(ele);
-        return remove;
-    }
-
-    @action
-    addWindow(contents: JSX.Element, options: OverlayElementOptions): OverlayDisposer {
-        const remove = action(() => {
-            const index = this._elements.indexOf(contents);
-            if (index !== -1) this._elements.splice(index, 1);
-        });
-        contents = <OverlayWindow onClick={remove} key={Utils.GenerateGuid()} overlayOptions={options}>{contents}</OverlayWindow>;
-        this._elements.push(contents);
-        return remove;
-    }
-
-
-    @computed get overlayDocs() {
-        return CurrentUserUtils.OverlayDocs?.map(d => {
-            let offsetx = 0, offsety = 0;
-            const dref = React.createRef<HTMLDivElement>();
-            const onPointerMove = action((e: PointerEvent, down: number[]) => {
-                if (e.buttons === 1) {
-                    d.x = e.clientX + offsetx;
-                    d.y = e.clientY + offsety;
-                }
-                if (e.metaKey) {
-                    const dragData = new DragManager.DocumentDragData([d]);
-                    dragData.offset = [-offsetx, -offsety];
-                    dragData.dropAction = "move";
-                    dragData.removeDocument = (doc: Doc | Doc[]) => {
-                        const docs = (doc instanceof Doc) ? [doc] : doc;
-                        docs.forEach(d => Doc.RemoveDocFromList(Cast(Doc.UserDoc().myOverlayDocs, Doc, null), "data", d));
-                        return true;
-                    };
-                    dragData.moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => {
-                        return dragData.removeDocument!(doc) ? addDocument(doc) : false;
-                    };
-                    DragManager.StartDocumentDrag([dref.current!], dragData, down[0], down[1]);
-                    return true;
-                }
-                return false;
+      public static Instance: OverlayView;
+      @observable.shallow
+      private _elements: JSX.Element[] = [];
+
+      constructor(props: any) {
+            super(props);
+            if (!OverlayView.Instance) {
+                  OverlayView.Instance = this;
+            }
+      }
+
+      @action
+      addElement(ele: JSX.Element, options: OverlayElementOptions): OverlayDisposer {
+            const remove = action(() => {
+                  const index = this._elements.indexOf(ele);
+                  if (index !== -1) this._elements.splice(index, 1);
             });
-
-            const onPointerDown = (e: React.PointerEvent) => {
-                setupMoveUpEvents(this, e, onPointerMove, emptyFunction, emptyFunction);
-                offsetx = NumCast(d.x) - e.clientX;
-                offsety = NumCast(d.y) - e.clientY;
-            };
-            return <div className="overlayView-doc" ref={dref} key={d[Id]} onPointerDown={onPointerDown} style={{ top: d.type === 'presentation' ? 0 : undefined, width: NumCast(d._width), height: NumCast(d._height), transform: `translate(${d.x}px, ${d.y}px)` }}>
-                <DocumentView
-                    Document={d}
-                    rootSelected={returnTrue}
-                    bringToFront={emptyFunction}
-                    addDocument={undefined}
-                    removeDocument={undefined}
-                    PanelWidth={returnOne}
-                    PanelHeight={returnOne}
-                    ScreenToLocalTransform={Transform.Identity}
-                    renderDepth={1}
-                    isDocumentActive={returnTrue}
-                    isContentActive={emptyFunction}
-                    whenChildContentsActiveChanged={emptyFunction}
-                    focus={DocUtils.DefaultFocus}
-                    styleProvider={DefaultStyleProvider}
-                    layerProvider={undefined}
-                    docViewPath={returnEmptyDoclist}
-                    addDocTab={returnFalse}
-                    pinToPres={emptyFunction}
-                    docFilters={returnEmptyFilter}
-                    docRangeFilters={returnEmptyFilter}
-                    searchFilterDocs={returnEmptyDoclist}
-                    ContainingCollectionView={undefined}
-                    ContainingCollectionDoc={undefined} />
-            </div>;
-        });
-    }
-
-    public static ShowSpinner() {
-        return OverlayView.Instance.addElement(<ReactLoading type="spinningBubbles" color="green" height={250} width={250} />, { x: 300, y: 200 });
-    }
-
-
-    render() {
-        return (
-            <div className="overlayView" id="overlayView">
-                <div>
-                    {this._elements}
-                </div>
-                <CollectionFreeFormLinksView key="freeformLinks" />
-                {this.overlayDocs}
-            </div>
-        );
-    }
+            ele = <div key={Utils.GenerateGuid()} className="overlayView-wrapperDiv" style={{
+                  transform: `translate(${options.x}px, ${options.y}px)`,
+                  width: options.width,
+                  height: options.height,
+                  top: 0,
+                  left: 0
+            }}>{ele}</div>;
+            this._elements.push(ele);
+            return remove;
+      }
+
+      @action
+      addWindow(contents: JSX.Element, options: OverlayElementOptions): OverlayDisposer {
+            const remove = action(() => {
+                  const index = this._elements.indexOf(contents);
+                  if (index !== -1) this._elements.splice(index, 1);
+            });
+            contents = <OverlayWindow onClick={remove} key={Utils.GenerateGuid()} overlayOptions={options}>{contents}</OverlayWindow>;
+            this._elements.push(contents);
+            return remove;
+      }
+
+
+      @computed get overlayDocs() {
+            return CurrentUserUtils.OverlayDocs?.map(d => {
+                  let offsetx = 0, offsety = 0;
+                  const dref = React.createRef<HTMLDivElement>();
+                  const onPointerMove = action((e: PointerEvent, down: number[]) => {
+                        if (e.buttons === 1) {
+                              d.x = e.clientX + offsetx;
+                              d.y = e.clientY + offsety;
+                        }
+                        if (e.metaKey) {
+                              const dragData = new DragManager.DocumentDragData([d]);
+                              dragData.offset = [-offsetx, -offsety];
+                              dragData.dropAction = "move";
+                              dragData.removeDocument = (doc: Doc | Doc[]) => {
+                                    const docs = (doc instanceof Doc) ? [doc] : doc;
+                                    docs.forEach(d => Doc.RemoveDocFromList(Cast(Doc.UserDoc().myOverlayDocs, Doc, null), "data", d));
+                                    return true;
+                              };
+                              dragData.moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => {
+                                    return dragData.removeDocument!(doc) ? addDocument(doc) : false;
+                              };
+                              DragManager.StartDocumentDrag([dref.current!], dragData, down[0], down[1]);
+                              return true;
+                        }
+                        return false;
+                  });
+
+                  const onPointerDown = (e: React.PointerEvent) => {
+                        setupMoveUpEvents(this, e, onPointerMove, emptyFunction, emptyFunction);
+                        offsetx = NumCast(d.x) - e.clientX;
+                        offsety = NumCast(d.y) - e.clientY;
+                  };
+
+                  return <div className="overlayView-doc" ref={dref} key={d[Id]} onPointerDown={onPointerDown} style={{ top: d.type === 'presentation' ? 0 : undefined, width: NumCast(d._width), height: NumCast(d._height), transform: `translate(${d.x}px, ${d.y}px)` }}>
+                        <DocumentView
+                              Document={d}
+                              rootSelected={returnTrue}
+                              bringToFront={emptyFunction}
+                              addDocument={undefined}
+                              removeDocument={undefined}
+                              PanelWidth={returnOne}
+                              PanelHeight={returnOne}
+                              ScreenToLocalTransform={Transform.Identity}
+                              renderDepth={1}
+                              isDocumentActive={returnTrue}
+                              isContentActive={emptyFunction}
+                              whenChildContentsActiveChanged={emptyFunction}
+                              focus={DocUtils.DefaultFocus}
+                              styleProvider={DefaultStyleProvider}
+                              layerProvider={undefined}
+                              docViewPath={returnEmptyDoclist}
+                              addDocTab={returnFalse}
+                              pinToPres={emptyFunction}
+                              docFilters={returnEmptyFilter}
+                              docRangeFilters={returnEmptyFilter}
+                              searchFilterDocs={returnEmptyDoclist}
+                              ContainingCollectionView={undefined}
+                              ContainingCollectionDoc={undefined} />
+                  </div>;
+            });
+      }
+
+      public static ShowSpinner() {
+            return OverlayView.Instance.addElement(<ReactLoading type="spinningBubbles" color="green" height={250} width={250} />, { x: 300, y: 200 });
+      }
+
+
+      render() {
+            return (
+                  <div className="overlayView" id="overlayView">
+                        <div>
+                              {this._elements}
+                        </div>
+                        <CollectionFreeFormLinksView key="freeformLinks" />
+                        {this.overlayDocs}
+                  </div>
+            );
+      }
 }
 // bcz: ugh ... want to be able to pass ScriptingRepl as tag argument, but that doesn't seem to work.. runtime error
 ScriptingGlobals.add(function addOverlayWindow(type: string, options: OverlayElementOptions) {
-    OverlayView.Instance.addWindow(<ScriptingRepl />, options);
+      OverlayView.Instance.addWindow(<ScriptingRepl />, options);
 });
\ No newline at end of file
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 6d444d324..1e17e2ddd 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -1,24 +1,39 @@
+import { action, observable } from "mobx";
 import { observer } from "mobx-react";
 import * as React from "react";
+import { AudioField } from "../../../../fields/URLField";
+import { Upload } from "../../../../server/SharedMediaTypes";
 import { ViewBoxBaseComponent } from "../../DocComponent";
 import { FieldView } from "../FieldView";
+import { VideoBox } from "../VideoBox";
 import { RecordingView } from './RecordingView';
 
 
 @observer
-export class RecordingBox extends ViewBoxBaseComponent(){
+export class RecordingBox extends ViewBoxBaseComponent() {
 
-    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(RecordingBox, fieldKey); }
+      public static LayoutString(fieldKey: string) { return FieldView.LayoutString(RecordingBox, fieldKey); }
 
-    private _ref: React.RefObject<HTMLDivElement> = React.createRef();
+      private _ref: React.RefObject<HTMLDivElement> = React.createRef();
 
-    constructor(props: any) {
-        super(props);
-    }
+      constructor(props: any) {
+            super(props);
+      }
 
-    render() {
-        return <div className="recordingBox" ref={this._ref}>
-            <RecordingView/>
-        </div>;
-    }
+      @observable result: Upload.FileInformation | undefined = undefined
+
+      @action
+      setResult = (info: Upload.FileInformation) => {
+            console.log("Setting result to " + info)
+            this.result = info
+            console.log(this.result.accessPaths.agnostic.client)
+            this.props.Document[this.fieldKey] = new AudioField(this.result.accessPaths.agnostic.client);
+      }
+
+      render() {
+            return <div className="recordingBox" ref={this._ref}>
+                  {!this.result ? <RecordingView setResult={this.setResult} /> :
+                        <p>video box</p>}
+            </div>;
+      }
 }
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.scss b/src/client/views/nodes/RecordingBox/RecordingView.scss
index e4d971d51..1fea231b7 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.scss
+++ b/src/client/views/nodes/RecordingBox/RecordingView.scss
@@ -15,6 +15,7 @@ button {
       height: 100%;
       width: 100%;
       display: flex;
+      pointer-events: all;
 }
 
 .video-wrapper {
@@ -157,8 +158,8 @@ button {
             background-color: red;
             border: 0px;
             border-radius: 10%;
-            height: 80%;
-            width: 80%;
+            height: 70%;
+            width: 70%;
             align-self: center;
             margin: 0;
 
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 905f87a1a..0d24f3c74 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -5,6 +5,8 @@ import { ProgressBar } from "./ProgressBar"
 import { MdBackspace } from 'react-icons/md';
 import { FaCheckCircle } from 'react-icons/fa';
 import { IconContext } from "react-icons";
+import { Networking } from '../../../Network';
+import { Upload } from '../../../../server/SharedMediaTypes';
 
 
 enum RecordingStatus {
@@ -18,9 +20,14 @@ interface VideoSegment {
       endTime: number
 }
 
+interface IRecordingViewProps {
+      setResult: (info: Upload.FileInformation) => void
+}
+
 const MAXTIME = 1000;
 
-export function RecordingView() {
+export function RecordingView(props: IRecordingViewProps) {
+      const { setResult } = props
 
       const [recording, setRecording] = useState(false);
       const recordingTimerRef = useRef<number>(0);
@@ -68,18 +75,27 @@ export function RecordingView() {
                         type: 'video/webm'
                   })
                   const blobUrl = URL.createObjectURL(blob)
+                  const videoFile = new File([blob], "video", { lastModified: new Date().getDate() });
 
                   videoElementRef.current!.srcObject = null
                   videoElementRef.current!.src = blobUrl
                   videoElementRef.current!.muted = false
 
-                  // upload data
-                  //       const [{ result }] = await Networking.UploadFilesToServer(e.data);
-                  // console.log("Data result", result);
-                  // if (!(result instanceof Error)) {
-                  //     this.props.Document[this.fieldKey] = new AudioField(result.accessPaths.agnostic.client);
+                  // const uploadVideo = async () => {
+                  //       const [{ result }] = await Networking.UploadFilesToServer(videoFile);
+                  //       console.log("upload result", result);
+                  //       if (!(result instanceof Error)) {
+                  //             setResult(result)
+                  //       }
                   // }
 
+                  Networking.UploadFilesToServer(allVideoChunks)
+                        .then((data) => {
+                              console.log(data)
+                        })
+                  // uploadVideo()
+
+
                   // change to one recording box
             }
 
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index 766676e95..aa7622736 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -30,376 +30,383 @@ import { List } from "../../../../fields/List";
  */
 @observer
 export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
-    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresElementBox, fieldKey); }
-    _heightDisposer: IReactionDisposer | undefined;
+      public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresElementBox, fieldKey); }
+      _heightDisposer: IReactionDisposer | undefined;
 
-    @observable _dragging = false;
-    // these fields are conditionally computed fields on the layout document that take this document as a parameter
-    @computed get indexInPres() { return Number(this.lookupField("indexInPres")); }  // the index field is where this document is in the presBox display list (since this value is different for each presentation element, the value can't be stored on the layout template which is used by all display elements)
-    @computed get collapsedHeight() { return Number(this.lookupField("presCollapsedHeight")); } // the collapsed height changes depending on the state of the presBox.  We could store this on the presentation element template if it's used by only one presentation - but if it's shared by multiple, then this value must be looked up
-    @computed get presStatus() { return StrCast(this.lookupField("presStatus")); }
-    @computed get itemIndex() { return NumCast(this.lookupField("_itemIndex")); }
-    @computed get presBox() { return Cast(this.lookupField("presBox"), Doc, null); }
-    @computed get targetDoc() { return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc; }
+      @observable _dragging = false;
+      // these fields are conditionally computed fields on the layout document that take this document as a parameter
+      @computed get indexInPres() { return Number(this.lookupField("indexInPres")); }  // the index field is where this document is in the presBox display list (since this value is different for each presentation element, the value can't be stored on the layout template which is used by all display elements)
+      @computed get collapsedHeight() { return Number(this.lookupField("presCollapsedHeight")); } // the collapsed height changes depending on the state of the presBox.  We could store this on the presentation element template if it's used by only one presentation - but if it's shared by multiple, then this value must be looked up
+      @computed get presStatus() { return StrCast(this.lookupField("presStatus")); }
+      @computed get itemIndex() { return NumCast(this.lookupField("_itemIndex")); }
+      @computed get presBox() { return Cast(this.lookupField("presBox"), Doc, null); }
+      @computed get targetDoc() { return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc; }
 
-    componentDidMount() {
-        this.layoutDoc.hideLinkButton = true;
-        this._heightDisposer = reaction(() => [this.rootDoc.presExpandInlineButton, this.collapsedHeight],
-            params => this.layoutDoc._height = NumCast(params[1]) + (Number(params[0]) ? 100 : 0), { fireImmediately: true });
-    }
-    componentWillUnmount() {
-        this._heightDisposer?.();
-    }
+      @observable isShowingVideo = false;
+      @action setIsShowingVideo(shown: boolean) {
+            this.isShowingVideo = shown
+      }
 
-    /**
-     * Returns a local transformed coordinate array for given coordinates.
-     */
-    ScreenToLocalListTransform = (xCord: number, yCord: number) => [xCord, yCord];
+      componentDidMount() {
+            this.layoutDoc.hideLinkButton = true;
+            this._heightDisposer = reaction(() => [this.rootDoc.presExpandInlineButton, this.collapsedHeight],
+                  params => this.layoutDoc._height = NumCast(params[1]) + (Number(params[0]) ? 100 : 0), { fireImmediately: true });
+      }
+      componentWillUnmount() {
+            this._heightDisposer?.();
+      }
 
-    @action
-    presExpandDocumentClick = () => {
-        this.rootDoc.presExpandInlineButton = !this.rootDoc.presExpandInlineButton;
-    }
+      /**
+       * Returns a local transformed coordinate array for given coordinates.
+       */
+      ScreenToLocalListTransform = (xCord: number, yCord: number) => [xCord, yCord];
 
-    embedHeight = (): number => 97;
-    // embedWidth = () => this.props.PanelWidth();
-    // embedHeight = () => Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - this.collapsedHeight);
-    embedWidth = (): number => this.props.PanelWidth() - 35;
-    styleProvider = (doc: (Doc | undefined), props: Opt<DocumentViewProps>, property: string): any => {
-        if (property === StyleProp.Opacity) return 1;
-        return this.props.styleProvider?.(doc, props, property);
-    }
-    /**
-     * The function that is responsible for rendering a preview or not for this
-     * presentation element.
-     */
-    @computed get renderEmbeddedInline() {
-        return !this.rootDoc.presExpandInlineButton || !this.targetDoc ? (null) :
-            <div className="presItem-embedded" style={{ height: this.embedHeight(), width: this.embedWidth() }}>
-                <DocumentView
-                    Document={this.targetDoc}
-                    DataDoc={this.targetDoc[DataSym] !== this.targetDoc && this.targetDoc[DataSym]}
-                    styleProvider={this.styleProvider}
-                    layerProvider={this.props.layerProvider}
-                    docViewPath={returnEmptyDoclist}
-                    rootSelected={returnTrue}
-                    addDocument={returnFalse}
-                    removeDocument={returnFalse}
-                    isContentActive={this.props.isContentActive}
-                    addDocTab={returnFalse}
-                    pinToPres={returnFalse}
-                    PanelWidth={this.embedWidth}
-                    PanelHeight={this.embedHeight}
-                    ScreenToLocalTransform={Transform.Identity}
-                    moveDocument={this.props.moveDocument!}
-                    renderDepth={this.props.renderDepth + 1}
-                    focus={DocUtils.DefaultFocus}
-                    whenChildContentsActiveChanged={returnFalse}
-                    bringToFront={returnFalse}
-                    docFilters={this.props.docFilters}
-                    docRangeFilters={this.props.docRangeFilters}
-                    searchFilterDocs={this.props.searchFilterDocs}
-                    ContainingCollectionView={undefined}
-                    ContainingCollectionDoc={undefined}
-                    hideLinkButton={true}
-                />
-                <div className="presItem-embeddedMask" />
-            </div>;
-    }
+      @action
+      presExpandDocumentClick = () => {
+            this.rootDoc.presExpandInlineButton = !this.rootDoc.presExpandInlineButton;
+      }
 
-    @computed get duration() {
-        let durationInS: number;
-        if (this.rootDoc.type === DocumentType.AUDIO || this.rootDoc.type === DocumentType.VID) { durationInS = NumCast(this.rootDoc.presEndTime) - NumCast(this.rootDoc.presStartTime); durationInS = Math.round(durationInS * 10) / 10; }
-        else if (this.rootDoc.presDuration) durationInS = NumCast(this.rootDoc.presDuration) / 1000;
-        else durationInS = 2;
-        return "D: " + durationInS + "s";
-    }
+      embedHeight = (): number => 97;
+      // embedWidth = () => this.props.PanelWidth();
+      // embedHeight = () => Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - this.collapsedHeight);
+      embedWidth = (): number => this.props.PanelWidth() - 35;
+      styleProvider = (doc: (Doc | undefined), props: Opt<DocumentViewProps>, property: string): any => {
+            if (property === StyleProp.Opacity) return 1;
+            return this.props.styleProvider?.(doc, props, property);
+      }
+      /**
+       * The function that is responsible for rendering a preview or not for this
+       * presentation element.
+       */
+      @computed get renderEmbeddedInline() {
+            return !this.rootDoc.presExpandInlineButton || !this.targetDoc ? (null) :
+                  <div className="presItem-embedded" style={{ height: this.embedHeight(), width: this.embedWidth() }}>
+                        <DocumentView
+                              Document={this.targetDoc}
+                              DataDoc={this.targetDoc[DataSym] !== this.targetDoc && this.targetDoc[DataSym]}
+                              styleProvider={this.styleProvider}
+                              layerProvider={this.props.layerProvider}
+                              docViewPath={returnEmptyDoclist}
+                              rootSelected={returnTrue}
+                              addDocument={returnFalse}
+                              removeDocument={returnFalse}
+                              isContentActive={this.props.isContentActive}
+                              addDocTab={returnFalse}
+                              pinToPres={returnFalse}
+                              PanelWidth={this.embedWidth}
+                              PanelHeight={this.embedHeight}
+                              ScreenToLocalTransform={Transform.Identity}
+                              moveDocument={this.props.moveDocument!}
+                              renderDepth={this.props.renderDepth + 1}
+                              focus={DocUtils.DefaultFocus}
+                              whenChildContentsActiveChanged={returnFalse}
+                              bringToFront={returnFalse}
+                              docFilters={this.props.docFilters}
+                              docRangeFilters={this.props.docRangeFilters}
+                              searchFilterDocs={this.props.searchFilterDocs}
+                              ContainingCollectionView={undefined}
+                              ContainingCollectionDoc={undefined}
+                              hideLinkButton={true}
+                        />
+                        <div className="presItem-embeddedMask" />
+                  </div>;
+      }
 
-    @computed get transition() {
-        let transitionInS: number;
-        if (this.rootDoc.presTransition) transitionInS = NumCast(this.rootDoc.presTransition) / 1000;
-        else transitionInS = 0.5;
-        return this.rootDoc.presMovement === PresMovement.Jump || this.rootDoc.presMovement === PresMovement.None ? (null) : "M: " + transitionInS + "s";
-    }
+      @computed get duration() {
+            let durationInS: number;
+            if (this.rootDoc.type === DocumentType.AUDIO || this.rootDoc.type === DocumentType.VID) { durationInS = NumCast(this.rootDoc.presEndTime) - NumCast(this.rootDoc.presStartTime); durationInS = Math.round(durationInS * 10) / 10; }
+            else if (this.rootDoc.presDuration) durationInS = NumCast(this.rootDoc.presDuration) / 1000;
+            else durationInS = 2;
+            return "D: " + durationInS + "s";
+      }
 
-    private _itemRef: React.RefObject<HTMLDivElement> = React.createRef();
-    private _dragRef: React.RefObject<HTMLDivElement> = React.createRef();
-    private _titleRef: React.RefObject<EditableView> = React.createRef();
+      @computed get transition() {
+            let transitionInS: number;
+            if (this.rootDoc.presTransition) transitionInS = NumCast(this.rootDoc.presTransition) / 1000;
+            else transitionInS = 0.5;
+            return this.rootDoc.presMovement === PresMovement.Jump || this.rootDoc.presMovement === PresMovement.None ? (null) : "M: " + transitionInS + "s";
+      }
 
+      private _itemRef: React.RefObject<HTMLDivElement> = React.createRef();
+      private _dragRef: React.RefObject<HTMLDivElement> = React.createRef();
+      private _titleRef: React.RefObject<EditableView> = React.createRef();
 
-    @action
-    headerDown = (e: React.PointerEvent<HTMLDivElement>) => {
-        const element = e.target as any;
-        e.stopPropagation();
-        e.preventDefault();
-        if (element && !(e.ctrlKey || e.metaKey)) {
-            if (PresBox.Instance._selectedArray.has(this.rootDoc)) {
-                PresBox.Instance._selectedArray.size === 1 && PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, false);
-                setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction);
-            } else {
-                setupMoveUpEvents(this, e, ((e: PointerEvent) => {
-                    PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, false);
-                    return this.startDrag(e);
-                }), emptyFunction, emptyFunction);
+
+      @action
+      headerDown = (e: React.PointerEvent<HTMLDivElement>) => {
+            const element = e.target as any;
+            e.stopPropagation();
+            e.preventDefault();
+            if (element && !(e.ctrlKey || e.metaKey)) {
+                  if (PresBox.Instance._selectedArray.has(this.rootDoc)) {
+                        PresBox.Instance._selectedArray.size === 1 && PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, false);
+                        setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction);
+                  } else {
+                        setupMoveUpEvents(this, e, ((e: PointerEvent) => {
+                              PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, false);
+                              return this.startDrag(e);
+                        }), emptyFunction, emptyFunction);
+                  }
+            }
+      }
+
+      headerUp = (e: React.PointerEvent<HTMLDivElement>) => {
+            e.stopPropagation();
+            e.preventDefault();
+      }
+
+      /**
+       * Function to drag and drop the pres element to a diferent location
+       */
+      startDrag = (e: PointerEvent) => {
+            const miniView: boolean = this.toolbarWidth <= 100;
+            const activeItem = this.rootDoc;
+            const dragArray = PresBox.Instance._dragArray;
+            const dragData = new DragManager.DocumentDragData(PresBox.Instance.sortArray());
+            const dragItem: HTMLElement[] = [];
+            if (dragArray.length === 1) {
+                  const doc = dragArray[0];
+                  doc.className = miniView ? "presItem-miniSlide" : "presItem-slide";
+                  dragItem.push(doc);
+            } else if (dragArray.length >= 1) {
+                  const doc = document.createElement('div');
+                  doc.className = "presItem-multiDrag";
+                  doc.innerText = "Move " + PresBox.Instance._selectedArray.size + " slides";
+                  doc.style.position = 'absolute';
+                  doc.style.top = (e.clientY) + 'px';
+                  doc.style.left = (e.clientX - 50) + 'px';
+                  dragItem.push(doc);
             }
-        }
-    }
 
-    headerUp = (e: React.PointerEvent<HTMLDivElement>) => {
-        e.stopPropagation();
-        e.preventDefault();
-    }
+            // const dropEvent = () => runInAction(() => this._dragging = false);
+            if (activeItem) {
+                  DragManager.StartDocumentDrag(dragItem.map(ele => ele), dragData, e.clientX, e.clientY, undefined);
+                  // runInAction(() => this._dragging = true);
+                  return true;
+            }
+            return false;
+      }
 
-    /**
-     * Function to drag and drop the pres element to a diferent location
-     */
-    startDrag = (e: PointerEvent) => {
-        const miniView: boolean = this.toolbarWidth <= 100;
-        const activeItem = this.rootDoc;
-        const dragArray = PresBox.Instance._dragArray;
-        const dragData = new DragManager.DocumentDragData(PresBox.Instance.sortArray());
-        const dragItem: HTMLElement[] = [];
-        if (dragArray.length === 1) {
-            const doc = dragArray[0];
-            doc.className = miniView ? "presItem-miniSlide" : "presItem-slide";
-            dragItem.push(doc);
-        } else if (dragArray.length >= 1) {
-            const doc = document.createElement('div');
-            doc.className = "presItem-multiDrag";
-            doc.innerText = "Move " + PresBox.Instance._selectedArray.size + " slides";
-            doc.style.position = 'absolute';
-            doc.style.top = (e.clientY) + 'px';
-            doc.style.left = (e.clientX - 50) + 'px';
-            dragItem.push(doc);
-        }
+      onPointerOver = (e: any) => {
+            document.removeEventListener("pointermove", this.onPointerMove);
+            document.addEventListener("pointermove", this.onPointerMove);
+      }
 
-        // const dropEvent = () => runInAction(() => this._dragging = false);
-        if (activeItem) {
-            DragManager.StartDocumentDrag(dragItem.map(ele => ele), dragData, e.clientX, e.clientY, undefined);
-            // runInAction(() => this._dragging = true);
-            return true;
-        }
-        return false;
-    }
+      onPointerMove = (e: PointerEvent) => {
+            const slide = this._itemRef.current!;
+            let dragIsPresItem: boolean = DragManager.docsBeingDragged.length > 0 ? true : false;
+            for (const doc of DragManager.docsBeingDragged) {
+                  if (!doc.presentationTargetDoc) dragIsPresItem = false;
+            }
+            if (slide && dragIsPresItem) {
+                  const rect = slide.getBoundingClientRect();
+                  const y = e.clientY - rect.top;  //y position within the element.
+                  const height = slide.clientHeight;
+                  const halfLine = height / 2;
+                  if (y <= halfLine) {
+                        slide.style.borderTop = `solid 2px ${Colors.MEDIUM_BLUE}`;
+                        slide.style.borderBottom = "0px";
+                  } else if (y > halfLine) {
+                        slide.style.borderTop = "0px";
+                        slide.style.borderBottom = `solid 2px ${Colors.MEDIUM_BLUE}`;
+                  }
+            }
+            document.removeEventListener("pointermove", this.onPointerMove);
+      }
 
-    onPointerOver = (e: any) => {
-        document.removeEventListener("pointermove", this.onPointerMove);
-        document.addEventListener("pointermove", this.onPointerMove);
-    }
+      onPointerLeave = (e: any) => {
+            this._itemRef.current!.style.borderTop = "0px";
+            this._itemRef.current!.style.borderBottom = "0px";
+            document.removeEventListener("pointermove", this.onPointerMove);
+      }
 
-    onPointerMove = (e: PointerEvent) => {
-        const slide = this._itemRef.current!;
-        let dragIsPresItem: boolean = DragManager.docsBeingDragged.length > 0 ? true : false;
-        for (const doc of DragManager.docsBeingDragged) {
-            if (!doc.presentationTargetDoc) dragIsPresItem = false;
-        }
-        if (slide && dragIsPresItem) {
-            const rect = slide.getBoundingClientRect();
-            const y = e.clientY - rect.top;  //y position within the element.
-            const height = slide.clientHeight;
-            const halfLine = height / 2;
-            if (y <= halfLine) {
-                slide.style.borderTop = `solid 2px ${Colors.MEDIUM_BLUE}`;
-                slide.style.borderBottom = "0px";
-            } else if (y > halfLine) {
-                slide.style.borderTop = "0px";
-                slide.style.borderBottom = `solid 2px ${Colors.MEDIUM_BLUE}`;
+      @action
+      toggleProperties = () => {
+            if (CurrentUserUtils.propertiesWidth < 5) {
+                  action(() => (CurrentUserUtils.propertiesWidth = 250));
             }
-        }
-        document.removeEventListener("pointermove", this.onPointerMove);
-    }
+      }
 
-    onPointerLeave = (e: any) => {
-        this._itemRef.current!.style.borderTop = "0px";
-        this._itemRef.current!.style.borderBottom = "0px";
-        document.removeEventListener("pointermove", this.onPointerMove);
-    }
+      @undoBatch
+      removeItem = action((e: React.MouseEvent) => {
+            this.props.removeDocument?.(this.rootDoc);
+            if (PresBox.Instance._selectedArray.has(this.rootDoc)) {
+                  PresBox.Instance._selectedArray.delete(this.rootDoc);
+            }
+            e.stopPropagation();
+      });
+
+      // set the value/title of the individual pres element
+      @undoBatch
+      @action
+      onSetValue = (value: string) => {
+            this.rootDoc.title = !value.trim().length ? "-untitled-" : value;
+            return true;
+      }
 
-    @action
-    toggleProperties = () => {
-        if (CurrentUserUtils.propertiesWidth < 5) {
-            action(() => (CurrentUserUtils.propertiesWidth = 250));
-        }
-    }
+      /**
+       * Method called for updating the view of the currently selected document
+       * 
+       * @param targetDoc 
+       * @param activeItem 
+       */
+      @undoBatch
+      @action
+      updateView = (targetDoc: Doc, activeItem: Doc) => {
+            if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF) {
+                  const scroll = targetDoc._scrollTop;
+                  activeItem.presPinViewScroll = scroll;
+            } else if (targetDoc.type === DocumentType.VID) {
+                  activeItem.presPinTimecode = targetDoc._currentTimecode;
+            } else if (targetDoc.type === DocumentType.COMPARISON) {
+                  const clipWidth = targetDoc._clipWidth;
+                  activeItem.presPinClipWidth = clipWidth;
+            } else {
+                  const x = targetDoc._panX;
+                  const y = targetDoc._panY;
+                  const scale = targetDoc._viewScale;
+                  activeItem.presPinViewX = x;
+                  activeItem.presPinViewY = y;
+                  activeItem.presPinViewScale = scale;
+            }
+      }
 
-    @undoBatch
-    removeItem = action((e: React.MouseEvent) => {
-        this.props.removeDocument?.(this.rootDoc);
-        if (PresBox.Instance._selectedArray.has(this.rootDoc)) {
-            PresBox.Instance._selectedArray.delete(this.rootDoc);
-        }
-        e.stopPropagation();
-    });
+      @undoBatch
+      @action
+      startRecording = (targetDoc: Doc, activeItem: Doc) => {
 
-    // set the value/title of the individual pres element
-    @undoBatch
-    @action
-    onSetValue = (value: string) => {
-        this.rootDoc.title = !value.trim().length ? "-untitled-" : value;
-        return true;
-    }
+            // TODO: Remove everything that already exists
+            if (activeItem.recording) {
+                  // if we already have an existing recording
+                  Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, Cast(activeItem.recording, Doc, null));
 
-    /**
-     * Method called for updating the view of the currently selected document
-     * 
-     * @param targetDoc 
-     * @param activeItem 
-     */
-    @undoBatch
-    @action
-    updateView = (targetDoc: Doc, activeItem: Doc) => {
-        if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF) {
-            const scroll = targetDoc._scrollTop;
-            activeItem.presPinViewScroll = scroll;
-        } else if (targetDoc.type === DocumentType.VID) {
-            activeItem.presPinTimecode = targetDoc._currentTimecode;
-        } else if (targetDoc.type === DocumentType.COMPARISON) {
-            const clipWidth = targetDoc._clipWidth;
-            activeItem.presPinClipWidth = clipWidth;
-        } else {
-            const x = targetDoc._panX;
-            const y = targetDoc._panY;
-            const scale = targetDoc._viewScale;
-            activeItem.presPinViewX = x;
-            activeItem.presPinViewY = y;
-            activeItem.presPinViewScale = scale;
-        }
-    }
+            } else {
+                  // if we dont have any recording
+                  console.log(targetDoc.title, activeItem.title);
+                  const recording = Docs.Create.WebCamDocument("", { _width: 400, _height: 200, title: "recording", system: true, cloneFieldFilter: new List<string>(["system"]) });
+                  activeItem.recording = recording
+                  // TODO: Figure out exactly where we want the video to appear
+                  const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
+                  console.log("x: ", pt[0], "y: ", pt[1]);
+                  recording.x = pt[0];
+                  recording.y = pt[1];
+                  Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, recording);
+            }
 
-    @undoBatch
-    @action 
-    startRecording = (targetDoc: Doc, activeItem: Doc) => {
-        // If we already have an existing recording
-        // TODO: Remove everything that already exists
-        if (activeItem.recording) {
-            Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, Cast(activeItem.recording, Doc, null));
-        // Recording has not yet been created
-        } else {
-            console.log(targetDoc.title, activeItem.title);
-            const recording = Docs.Create.WebCamDocument("", { _width: 400, _height: 200, title: "recording", system: true, cloneFieldFilter: new List<string>(["system"]) });
-            activeItem.recording = recording
-            // TODO: Figure out exactly where we want the video to appear
-            const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
-            console.log("x: ", pt[0], "y: ", pt[1]);
-            recording.x = pt[0];
-            recording.y = pt[1];
-            Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, recording);
-        }
-        
-    }
+      }
 
-    @computed
-    get toolbarWidth(): number {
-        const presBoxDocView = DocumentManager.Instance.getDocumentView(this.presBox);
-        let width: number = NumCast(this.presBox._width);
-        if (presBoxDocView) width = presBoxDocView.props.PanelWidth();
-        if (width === 0) width = 300;
-        return width;
-    }
+      @computed
+      get toolbarWidth(): number {
+            const presBoxDocView = DocumentManager.Instance.getDocumentView(this.presBox);
+            let width: number = NumCast(this.presBox._width);
+            if (presBoxDocView) width = presBoxDocView.props.PanelWidth();
+            if (width === 0) width = 300;
+            return width;
+      }
 
-    @computed get mainItem() {
-        const isSelected: boolean = PresBox.Instance._selectedArray.has(this.rootDoc);
-        const toolbarWidth: number = this.toolbarWidth;
-        const showMore: boolean = this.toolbarWidth >= 300;
-        const miniView: boolean = this.toolbarWidth <= 110;
-        const presBox: Doc = this.presBox; //presBox
-        const presBoxColor: string = StrCast(presBox._backgroundColor);
-        const presColorBool: boolean = presBoxColor ? (presBoxColor !== Colors.WHITE && presBoxColor !== "transparent") : false;
-        const targetDoc: Doc = this.targetDoc;
-        const activeItem: Doc = this.rootDoc;
-        return (
-            <div className={`presItem-container`}
-                key={this.props.Document[Id] + this.indexInPres}
-                ref={this._itemRef}
-                style={{
-                    backgroundColor: presColorBool ? isSelected ? "rgba(250,250,250,0.3)" : "transparent" : isSelected ? Colors.LIGHT_BLUE : "transparent",
-                    opacity: this._dragging ? 0.3 : 1
-                }}
-                onClick={e => {
-                    e.stopPropagation();
-                    e.preventDefault();
-                    PresBox.Instance.modifierSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, !e.shiftKey && !e.ctrlKey && !e.metaKey, e.ctrlKey || e.metaKey, e.shiftKey);
-                }}
-                onDoubleClick={action(e => {
-                    this.toggleProperties();
-                    PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, true);
-                })}
-                onPointerOver={this.onPointerOver}
-                onPointerLeave={this.onPointerLeave}
-                onPointerDown={this.headerDown}
-                onPointerUp={this.headerUp}
-            >
-                {miniView ?
-                    // when width is LESS than 110 px 
-                    <div className={`presItem-miniSlide ${isSelected ? "active" : ""}`} ref={miniView ? this._dragRef : null}>
-                        {`${this.indexInPres + 1}.`}
-                    </div>
-                    :
-                    // when width is MORE than 110 px 
-                    <div className="presItem-number">
-                        {`${this.indexInPres + 1}.`}
-                    </div>}
-                {miniView ? (null) : <div ref={miniView ? null : this._dragRef} className={`presItem-slide ${isSelected ? "active" : ""}`}
-                    style={{
-                        backgroundColor: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor),
-                        boxShadow: presBoxColor && presBoxColor !== "white" && presBoxColor !== "transparent" ? isSelected ? "0 0 0px 1.5px" + presBoxColor : undefined : undefined
-                    }}>
-                    <div className="presItem-name" style={{ maxWidth: showMore ? (toolbarWidth - 195) : toolbarWidth - 105, cursor: isSelected ? 'text' : 'grab' }}>
-                        <EditableView
-                            ref={this._titleRef}
-                            editing={!isSelected ? false : undefined}
-                            contents={activeItem.title}
-                            overflow={'ellipsis'}
-                            GetValue={() => StrCast(activeItem.title)}
-                            SetValue={this.onSetValue}
-                        />
-                    </div>
-                    <Tooltip title={<><div className="dash-tooltip">{"Movement speed"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.transition}</div></Tooltip>
-                    <Tooltip title={<><div className="dash-tooltip">{"Duration"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.duration}</div></Tooltip>
-                    <div className={"presItem-slideButtons"}>
-                        <Tooltip title={<><div className="dash-tooltip">{"Update view"}</div></>}>
-                            <div className="slideButton"
-                                onClick={() => this.updateView(targetDoc, activeItem)}
-                                style={{ fontWeight: 700, display: activeItem.presPinView ? "flex" : "none" }}>V</div>
-                        </Tooltip>
-                        <Tooltip title={<><div className="dash-tooltip">{"Start recording"}</div></>}>
-                            <div className="slideButton"
-                                onClick={() => this.startRecording(targetDoc, activeItem)}
-                                style={{ fontWeight: 700 }}>
-                                    <FontAwesomeIcon icon={"video"} onPointerDown={e => e.stopPropagation()} />
-                                </div>
-                        </Tooltip>
-                        {this.indexInPres === 0 ? (null) : <Tooltip title={<><div className="dash-tooltip">{activeItem.groupWithUp ? "Ungroup" : "Group with up"}</div></>}>
-                            <div className="slideButton"
-                                onClick={() => activeItem.groupWithUp = !activeItem.groupWithUp}
-                                style={{
-                                    zIndex: 1000 - this.indexInPres,
-                                    fontWeight: 700,
-                                    backgroundColor: activeItem.groupWithUp ? presColorBool ? presBoxColor : Colors.MEDIUM_BLUE : undefined,
-                                    height: activeItem.groupWithUp ? 53 : 18,
-                                    transform: activeItem.groupWithUp ? "translate(0, -17px)" : undefined
-                                }}>
-                                <div style={{ transform: activeItem.groupWithUp ? "rotate(180deg) translate(0, -17.5px)" : "rotate(0deg)" }}>
-                                    <FontAwesomeIcon icon={"arrow-up"} onPointerDown={e => e.stopPropagation()} />
-                                </div>
-                            </div>
-                        </Tooltip>}
-                        <Tooltip title={<><div className="dash-tooltip">{this.rootDoc.presExpandInlineButton ? "Minimize" : "Expand"}</div></>}><div className={"slideButton"} onClick={e => { e.stopPropagation(); this.presExpandDocumentClick(); }}>
-                            <FontAwesomeIcon icon={this.rootDoc.presExpandInlineButton ? "eye-slash" : "eye"} onPointerDown={e => e.stopPropagation()} />
-                        </div></Tooltip>
-                        <Tooltip title={<><div className="dash-tooltip">{"Remove from presentation"}</div></>}><div
-                            className={"slideButton"}
-                            onClick={this.removeItem}>
-                            <FontAwesomeIcon icon={"trash"} onPointerDown={e => e.stopPropagation()} />
-                        </div></Tooltip>
-                    </div>
-                    <div className="presItem-docName" style={{ maxWidth: showMore ? (toolbarWidth - 195) : toolbarWidth - 105 }}>{activeItem.presPinView ? (<><i>View of </i> {targetDoc.title}</>) : targetDoc.title}</div>
-                    {this.renderEmbeddedInline}
-                </div>}
-            </div >);
-    }
+      @computed get mainItem() {
+            const isSelected: boolean = PresBox.Instance._selectedArray.has(this.rootDoc);
+            const toolbarWidth: number = this.toolbarWidth;
+            const showMore: boolean = this.toolbarWidth >= 300;
+            const miniView: boolean = this.toolbarWidth <= 110;
+            const presBox: Doc = this.presBox; //presBox
+            const presBoxColor: string = StrCast(presBox._backgroundColor);
+            const presColorBool: boolean = presBoxColor ? (presBoxColor !== Colors.WHITE && presBoxColor !== "transparent") : false;
+            const targetDoc: Doc = this.targetDoc;
+            const activeItem: Doc = this.rootDoc;
+            return (
+                  <div className={`presItem-container`}
+                        key={this.props.Document[Id] + this.indexInPres}
+                        ref={this._itemRef}
+                        style={{
+                              backgroundColor: presColorBool ? isSelected ? "rgba(250,250,250,0.3)" : "transparent" : isSelected ? Colors.LIGHT_BLUE : "transparent",
+                              opacity: this._dragging ? 0.3 : 1
+                        }}
+                        onClick={e => {
+                              e.stopPropagation();
+                              e.preventDefault();
+                              PresBox.Instance.modifierSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, !e.shiftKey && !e.ctrlKey && !e.metaKey, e.ctrlKey || e.metaKey, e.shiftKey);
+                        }}
+                        onDoubleClick={action(e => {
+                              this.toggleProperties();
+                              PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, true);
+                        })}
+                        onPointerOver={this.onPointerOver}
+                        onPointerLeave={this.onPointerLeave}
+                        onPointerDown={this.headerDown}
+                        onPointerUp={this.headerUp}
+                  >
+                        {miniView ?
+                              // when width is LESS than 110 px 
+                              <div className={`presItem-miniSlide ${isSelected ? "active" : ""}`} ref={miniView ? this._dragRef : null}>
+                                    {`${this.indexInPres + 1}.`}
+                              </div>
+                              :
+                              // when width is MORE than 110 px 
+                              <div className="presItem-number">
+                                    {`${this.indexInPres + 1}.`}
+                              </div>}
+                        {miniView ? (null) : <div ref={miniView ? null : this._dragRef} className={`presItem-slide ${isSelected ? "active" : ""}`}
+                              style={{
+                                    backgroundColor: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor),
+                                    boxShadow: presBoxColor && presBoxColor !== "white" && presBoxColor !== "transparent" ? isSelected ? "0 0 0px 1.5px" + presBoxColor : undefined : undefined
+                              }}>
+                              <div className="presItem-name" style={{ maxWidth: showMore ? (toolbarWidth - 195) : toolbarWidth - 105, cursor: isSelected ? 'text' : 'grab' }}>
+                                    <EditableView
+                                          ref={this._titleRef}
+                                          editing={!isSelected ? false : undefined}
+                                          contents={activeItem.title}
+                                          overflow={'ellipsis'}
+                                          GetValue={() => StrCast(activeItem.title)}
+                                          SetValue={this.onSetValue}
+                                    />
+                              </div>
+                              <Tooltip title={<><div className="dash-tooltip">{"Movement speed"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.transition}</div></Tooltip>
+                              <Tooltip title={<><div className="dash-tooltip">{"Duration"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.duration}</div></Tooltip>
+                              <div className={"presItem-slideButtons"}>
+                                    <Tooltip title={<><div className="dash-tooltip">{"Update view"}</div></>}>
+                                          <div className="slideButton"
+                                                onClick={() => this.updateView(targetDoc, activeItem)}
+                                                style={{ fontWeight: 700, display: activeItem.presPinView ? "flex" : "none" }}>V</div>
+                                    </Tooltip>
+                                    <Tooltip title={<><div className="dash-tooltip">{"Start recording"}</div></>}>
+                                          <div className="slideButton"
+                                                onClick={() => this.startRecording(targetDoc, activeItem)}
+                                                style={{ fontWeight: 700 }}>
+                                                <FontAwesomeIcon icon={"video"} onPointerDown={e => e.stopPropagation()} />
+                                          </div>
+                                    </Tooltip>
+                                    {this.indexInPres === 0 ? (null) : <Tooltip title={<><div className="dash-tooltip">{activeItem.groupWithUp ? "Ungroup" : "Group with up"}</div></>}>
+                                          <div className="slideButton"
+                                                onClick={() => activeItem.groupWithUp = !activeItem.groupWithUp}
+                                                style={{
+                                                      zIndex: 1000 - this.indexInPres,
+                                                      fontWeight: 700,
+                                                      backgroundColor: activeItem.groupWithUp ? presColorBool ? presBoxColor : Colors.MEDIUM_BLUE : undefined,
+                                                      height: activeItem.groupWithUp ? 53 : 18,
+                                                      transform: activeItem.groupWithUp ? "translate(0, -17px)" : undefined
+                                                }}>
+                                                <div style={{ transform: activeItem.groupWithUp ? "rotate(180deg) translate(0, -17.5px)" : "rotate(0deg)" }}>
+                                                      <FontAwesomeIcon icon={"arrow-up"} onPointerDown={e => e.stopPropagation()} />
+                                                </div>
+                                          </div>
+                                    </Tooltip>}
+                                    <Tooltip title={<><div className="dash-tooltip">{this.rootDoc.presExpandInlineButton ? "Minimize" : "Expand"}</div></>}><div className={"slideButton"} onClick={e => { e.stopPropagation(); this.presExpandDocumentClick(); }}>
+                                          <FontAwesomeIcon icon={this.rootDoc.presExpandInlineButton ? "eye-slash" : "eye"} onPointerDown={e => e.stopPropagation()} />
+                                    </div></Tooltip>
+                                    <Tooltip title={<><div className="dash-tooltip">{"Remove from presentation"}</div></>}><div
+                                          className={"slideButton"}
+                                          onClick={this.removeItem}>
+                                          <FontAwesomeIcon icon={"trash"} onPointerDown={e => e.stopPropagation()} />
+                                    </div></Tooltip>
+                              </div>
+                              <div className="presItem-docName" style={{ maxWidth: showMore ? (toolbarWidth - 195) : toolbarWidth - 105 }}>{activeItem.presPinView ? (<><i>View of </i> {targetDoc.title}</>) : targetDoc.title}</div>
+                              {this.renderEmbeddedInline}
+                        </div>}
+                  </div >);
+      }
 
-    render() {
-        return !(this.rootDoc instanceof Doc) || this.targetDoc instanceof Promise ? (null) : this.mainItem;
-    }
+      render() {
+            return !(this.rootDoc instanceof Doc) || this.targetDoc instanceof Promise ? (null) : this.mainItem;
+      }
 }
\ No newline at end of file
diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts
index bfa07d47a..5a19477dd 100644
--- a/src/server/ApiManagers/UploadManager.ts
+++ b/src/server/ApiManagers/UploadManager.ts
@@ -19,288 +19,288 @@ import { SolrManager } from "./SearchManager";
 import { StringDecoder } from "string_decoder";
 
 export enum Directory {
-    parsed_files = "parsed_files",
-    images = "images",
-    videos = "videos",
-    pdfs = "pdfs",
-    text = "text",
-    pdf_thumbnails = "pdf_thumbnails",
-    audio = "audio",
+      parsed_files = "parsed_files",
+      images = "images",
+      videos = "videos",
+      pdfs = "pdfs",
+      text = "text",
+      pdf_thumbnails = "pdf_thumbnails",
+      audio = "audio",
 }
 
 export function serverPathToFile(directory: Directory, filename: string) {
-    return normalize(`${filesDirectory}/${directory}/${filename}`);
+      return normalize(`${filesDirectory}/${directory}/${filename}`);
 }
 
 export function pathToDirectory(directory: Directory) {
-    return normalize(`${filesDirectory}/${directory}`);
+      return normalize(`${filesDirectory}/${directory}`);
 }
 
 export function clientPathToFile(directory: Directory, filename: string) {
-    return `/files/${directory}/${filename}`;
+      return `/files/${directory}/${filename}`;
 }
 
 export default class UploadManager extends ApiManager {
 
-    protected initialize(register: Registration): void {
+      protected initialize(register: Registration): void {
 
-        register({
-            method: Method.POST,
-            subscription: "/uploadFormData",
-            secureHandler: async ({ req, res }) => {
-                const form = new formidable.IncomingForm();
-                form.keepExtensions = true;
-                form.uploadDir = pathToDirectory(Directory.parsed_files);
-                return new Promise<void>(resolve => {
-                    form.parse(req, async (_err, _fields, files) => {
-                        const results: Upload.FileResponse[] = [];
-                        for (const key in files) {
-                            const f = files[key];
-                            if (!Array.isArray(f)) {
-                                const result = await DashUploadUtils.upload(f);
-                                result && !(result.result instanceof Error) && results.push(result);
-                            }
-                        }
-                        _success(res, results);
-                        resolve();
-                    });
-                });
-            }
-        });
+            register({
+                  method: Method.POST,
+                  subscription: "/uploadFormData",
+                  secureHandler: async ({ req, res }) => {
+                        const form = new formidable.IncomingForm();
+                        form.keepExtensions = true;
+                        form.uploadDir = pathToDirectory(Directory.parsed_files);
+                        return new Promise<void>(resolve => {
+                              form.parse(req, async (_err, _fields, files) => {
+                                    const results: Upload.FileResponse[] = [];
+                                    for (const key in files) {
+                                          const f = files[key];
+                                          if (!Array.isArray(f)) {
+                                                const result = await DashUploadUtils.upload(f);
+                                                result && !(result.result instanceof Error) && results.push(result);
+                                          }
+                                    }
+                                    _success(res, results);
+                                    resolve();
+                              });
+                        });
+                  }
+            });
 
-        register({
-            method: Method.POST,
-            subscription: "/uploadYoutubeVideo",
-            secureHandler: async ({ req, res }) => {
-                //req.readableBuffer.head.data
-                return new Promise<void>(async resolve => {
-                    req.addListener("data", async (args) => {
-                        console.log(args);
-                        const payload = String.fromCharCode.apply(String, args);
-                        const videoId = JSON.parse(payload).videoId;
-                        const results: Upload.FileResponse[] = [];
-                        const result = await DashUploadUtils.uploadYoutube(videoId);
-                        result && !(result.result instanceof Error) && results.push(result);
-                        _success(res, results);
-                        resolve();
-                    });
-                });
-            }
-        });
+            register({
+                  method: Method.POST,
+                  subscription: "/uploadYoutubeVideo",
+                  secureHandler: async ({ req, res }) => {
+                        //req.readableBuffer.head.data
+                        return new Promise<void>(async resolve => {
+                              req.addListener("data", async (args) => {
+                                    console.log(args);
+                                    const payload = String.fromCharCode.apply(String, args);
+                                    const videoId = JSON.parse(payload).videoId;
+                                    const results: Upload.FileResponse[] = [];
+                                    const result = await DashUploadUtils.uploadYoutube(videoId);
+                                    result && !(result.result instanceof Error) && results.push(result);
+                                    _success(res, results);
+                                    resolve();
+                              });
+                        });
+                  }
+            });
 
-        register({
-            method: Method.POST,
-            subscription: new RouteSubscriber("youtubeScreenshot"),
-            secureHandler: async ({ req, res }) => {
-                const { id, timecode } = req.body;
-                const convert = (raw: string) => {
-                    const number = Math.floor(Number(raw));
-                    const seconds = number % 60;
-                    const minutes = (number - seconds) / 60;
-                    return `${minutes}m${seconds}s`;
-                };
-                const suffix = timecode ? `&t=${convert(timecode)}` : ``;
-                const targetUrl = `https://www.youtube.com/watch?v=${id}${suffix}`;
-                const buffer = await captureYoutubeScreenshot(targetUrl);
-                if (!buffer) {
-                    return res.send();
-                }
-                const resolvedName = `youtube_capture_${id}_${suffix}.png`;
-                const resolvedPath = serverPathToFile(Directory.images, resolvedName);
-                return new Promise<void>(resolve => {
-                    writeFile(resolvedPath, buffer, async error => {
-                        if (error) {
-                            return res.send();
+            register({
+                  method: Method.POST,
+                  subscription: new RouteSubscriber("youtubeScreenshot"),
+                  secureHandler: async ({ req, res }) => {
+                        const { id, timecode } = req.body;
+                        const convert = (raw: string) => {
+                              const number = Math.floor(Number(raw));
+                              const seconds = number % 60;
+                              const minutes = (number - seconds) / 60;
+                              return `${minutes}m${seconds}s`;
+                        };
+                        const suffix = timecode ? `&t=${convert(timecode)}` : ``;
+                        const targetUrl = `https://www.youtube.com/watch?v=${id}${suffix}`;
+                        const buffer = await captureYoutubeScreenshot(targetUrl);
+                        if (!buffer) {
+                              return res.send();
                         }
-                        await DashUploadUtils.outputResizedImages(() => createReadStream(resolvedPath), resolvedName, pathToDirectory(Directory.images));
-                        res.send({
-                            accessPaths: {
-                                agnostic: DashUploadUtils.getAccessPaths(Directory.images, resolvedName)
-                            }
-                        } as Upload.FileInformation);
-                        resolve();
-                    });
-                });
-            }
-        });
+                        const resolvedName = `youtube_capture_${id}_${suffix}.png`;
+                        const resolvedPath = serverPathToFile(Directory.images, resolvedName);
+                        return new Promise<void>(resolve => {
+                              writeFile(resolvedPath, buffer, async error => {
+                                    if (error) {
+                                          return res.send();
+                                    }
+                                    await DashUploadUtils.outputResizedImages(() => createReadStream(resolvedPath), resolvedName, pathToDirectory(Directory.images));
+                                    res.send({
+                                          accessPaths: {
+                                                agnostic: DashUploadUtils.getAccessPaths(Directory.images, resolvedName)
+                                          }
+                                    } as Upload.FileInformation);
+                                    resolve();
+                              });
+                        });
+                  }
+            });
 
-        register({
-            method: Method.POST,
-            subscription: "/uploadRemoteImage",
-            secureHandler: async ({ req, res }) => {
+            register({
+                  method: Method.POST,
+                  subscription: "/uploadRemoteImage",
+                  secureHandler: async ({ req, res }) => {
 
-                const { sources } = req.body;
-                if (Array.isArray(sources)) {
-                    const results = await Promise.all(sources.map(source => DashUploadUtils.UploadImage(source)));
-                    return res.send(results);
-                }
-                res.send();
-            }
-        });
+                        const { sources } = req.body;
+                        if (Array.isArray(sources)) {
+                              const results = await Promise.all(sources.map(source => DashUploadUtils.UploadImage(source)));
+                              return res.send(results);
+                        }
+                        res.send();
+                  }
+            });
 
-        register({
-            method: Method.POST,
-            subscription: "/uploadDoc",
-            secureHandler: ({ req, res }) => {
+            register({
+                  method: Method.POST,
+                  subscription: "/uploadDoc",
+                  secureHandler: ({ req, res }) => {
 
-                const form = new formidable.IncomingForm();
-                form.keepExtensions = true;
-                // let path = req.body.path;
-                const ids: { [id: string]: string } = {};
-                let remap = true;
-                const getId = (id: string): string => {
-                    if (!remap) return id;
-                    if (id.endsWith("Proto")) return id;
-                    if (id in ids) {
-                        return ids[id];
-                    } else {
-                        return ids[id] = v4();
-                    }
-                };
-                const mapFn = (doc: any) => {
-                    if (doc.id) {
-                        doc.id = getId(doc.id);
-                    }
-                    for (const key in doc.fields) {
-                        if (!doc.fields.hasOwnProperty(key)) { continue; }
-                        const field = doc.fields[key];
-                        if (field === undefined || field === null) { continue; }
+                        const form = new formidable.IncomingForm();
+                        form.keepExtensions = true;
+                        // let path = req.body.path;
+                        const ids: { [id: string]: string } = {};
+                        let remap = true;
+                        const getId = (id: string): string => {
+                              if (!remap) return id;
+                              if (id.endsWith("Proto")) return id;
+                              if (id in ids) {
+                                    return ids[id];
+                              } else {
+                                    return ids[id] = v4();
+                              }
+                        };
+                        const mapFn = (doc: any) => {
+                              if (doc.id) {
+                                    doc.id = getId(doc.id);
+                              }
+                              for (const key in doc.fields) {
+                                    if (!doc.fields.hasOwnProperty(key)) { continue; }
+                                    const field = doc.fields[key];
+                                    if (field === undefined || field === null) { continue; }
 
-                        if (field.__type === "Doc") {
-                            mapFn(field);
-                        } else if (field.__type === "proxy" || field.__type === "prefetch_proxy") {
-                            field.fieldId = getId(field.fieldId);
-                        } else if (field.__type === "script" || field.__type === "computed") {
-                            if (field.captures) {
-                                field.captures.fieldId = getId(field.captures.fieldId);
-                            }
-                        } else if (field.__type === "list") {
-                            mapFn(field);
-                        } else if (typeof field === "string") {
-                            const re = /("(?:dataD|d)ocumentId"\s*:\s*")([\w\-]*)"/g;
-                            doc.fields[key] = (field as any).replace(re, (match: any, p1: string, p2: string) => {
-                                return `${p1}${getId(p2)}"`;
-                            });
-                        } else if (field.__type === "RichTextField") {
-                            const re = /("href"\s*:\s*")(.*?)"/g;
-                            field.Data = field.Data.replace(re, (match: any, p1: string, p2: string) => {
-                                return `${p1}${getId(p2)}"`;
-                            });
-                        }
-                    }
-                };
-                return new Promise<void>(resolve => {
-                    form.parse(req, async (_err, fields, files) => {
-                        remap = fields.remap !== "false";
-                        let id: string = "";
-                        try {
-                            for (const name in files) {
-                                const f = files[name];
-                                const path_2 = Array.isArray(f) ? "" : f.path;
-                                const zip = new AdmZip(path_2);
-                                zip.getEntries().forEach((entry: any) => {
-                                    if (!entry.entryName.startsWith("files/")) return;
-                                    let directory = dirname(entry.entryName) + "/";
-                                    const extension = extname(entry.entryName);
-                                    const base = basename(entry.entryName).split(".")[0];
+                                    if (field.__type === "Doc") {
+                                          mapFn(field);
+                                    } else if (field.__type === "proxy" || field.__type === "prefetch_proxy") {
+                                          field.fieldId = getId(field.fieldId);
+                                    } else if (field.__type === "script" || field.__type === "computed") {
+                                          if (field.captures) {
+                                                field.captures.fieldId = getId(field.captures.fieldId);
+                                          }
+                                    } else if (field.__type === "list") {
+                                          mapFn(field);
+                                    } else if (typeof field === "string") {
+                                          const re = /("(?:dataD|d)ocumentId"\s*:\s*")([\w\-]*)"/g;
+                                          doc.fields[key] = (field as any).replace(re, (match: any, p1: string, p2: string) => {
+                                                return `${p1}${getId(p2)}"`;
+                                          });
+                                    } else if (field.__type === "RichTextField") {
+                                          const re = /("href"\s*:\s*")(.*?)"/g;
+                                          field.Data = field.Data.replace(re, (match: any, p1: string, p2: string) => {
+                                                return `${p1}${getId(p2)}"`;
+                                          });
+                                    }
+                              }
+                        };
+                        return new Promise<void>(resolve => {
+                              form.parse(req, async (_err, fields, files) => {
+                                    remap = fields.remap !== "false";
+                                    let id: string = "";
                                     try {
-                                        zip.extractEntryTo(entry.entryName, publicDirectory, true, false);
-                                        directory = "/" + directory;
+                                          for (const name in files) {
+                                                const f = files[name];
+                                                const path_2 = Array.isArray(f) ? "" : f.path;
+                                                const zip = new AdmZip(path_2);
+                                                zip.getEntries().forEach((entry: any) => {
+                                                      if (!entry.entryName.startsWith("files/")) return;
+                                                      let directory = dirname(entry.entryName) + "/";
+                                                      const extension = extname(entry.entryName);
+                                                      const base = basename(entry.entryName).split(".")[0];
+                                                      try {
+                                                            zip.extractEntryTo(entry.entryName, publicDirectory, true, false);
+                                                            directory = "/" + directory;
 
-                                        createReadStream(publicDirectory + directory + base + extension).pipe(createWriteStream(publicDirectory + directory + base + "_o" + extension));
-                                        createReadStream(publicDirectory + directory + base + extension).pipe(createWriteStream(publicDirectory + directory + base + "_s" + extension));
-                                        createReadStream(publicDirectory + directory + base + extension).pipe(createWriteStream(publicDirectory + directory + base + "_m" + extension));
-                                        createReadStream(publicDirectory + directory + base + extension).pipe(createWriteStream(publicDirectory + directory + base + "_l" + extension));
-                                    } catch (e) {
-                                        console.log(e);
-                                    }
-                                });
-                                const json = zip.getEntry("doc.json");
-                                try {
-                                    const data = JSON.parse(json.getData().toString("utf8"));
-                                    const datadocs = data.docs;
-                                    id = getId(data.id);
-                                    const docs = Object.keys(datadocs).map(key => datadocs[key]);
-                                    docs.forEach(mapFn);
-                                    await Promise.all(docs.map((doc: any) => new Promise<void>(res => {
-                                        Database.Instance.replace(doc.id, doc, (err, r) => {
-                                            err && console.log(err);
-                                            res();
-                                        }, true);
-                                    })));
-                                } catch (e) { console.log(e); }
-                                unlink(path_2, () => { });
-                            }
-                            SolrManager.update();
-                            res.send(JSON.stringify(id || "error"));
-                        } catch (e) { console.log(e); }
-                        resolve();
-                    });
-                });
-            }
-        });
+                                                            createReadStream(publicDirectory + directory + base + extension).pipe(createWriteStream(publicDirectory + directory + base + "_o" + extension));
+                                                            createReadStream(publicDirectory + directory + base + extension).pipe(createWriteStream(publicDirectory + directory + base + "_s" + extension));
+                                                            createReadStream(publicDirectory + directory + base + extension).pipe(createWriteStream(publicDirectory + directory + base + "_m" + extension));
+                                                            createReadStream(publicDirectory + directory + base + extension).pipe(createWriteStream(publicDirectory + directory + base + "_l" + extension));
+                                                      } catch (e) {
+                                                            console.log(e);
+                                                      }
+                                                });
+                                                const json = zip.getEntry("doc.json");
+                                                try {
+                                                      const data = JSON.parse(json.getData().toString("utf8"));
+                                                      const datadocs = data.docs;
+                                                      id = getId(data.id);
+                                                      const docs = Object.keys(datadocs).map(key => datadocs[key]);
+                                                      docs.forEach(mapFn);
+                                                      await Promise.all(docs.map((doc: any) => new Promise<void>(res => {
+                                                            Database.Instance.replace(doc.id, doc, (err, r) => {
+                                                                  err && console.log(err);
+                                                                  res();
+                                                            }, true);
+                                                      })));
+                                                } catch (e) { console.log(e); }
+                                                unlink(path_2, () => { });
+                                          }
+                                          SolrManager.update();
+                                          res.send(JSON.stringify(id || "error"));
+                                    } catch (e) { console.log(e); }
+                                    resolve();
+                              });
+                        });
+                  }
+            });
 
-        register({
-            method: Method.POST,
-            subscription: "/inspectImage",
-            secureHandler: async ({ req, res }) => {
+            register({
+                  method: Method.POST,
+                  subscription: "/inspectImage",
+                  secureHandler: async ({ req, res }) => {
 
-                const { source } = req.body;
-                if (typeof source === "string") {
-                    return res.send(await DashUploadUtils.InspectImage(source));
-                }
-                res.send({});
-            }
-        });
+                        const { source } = req.body;
+                        if (typeof source === "string") {
+                              return res.send(await DashUploadUtils.InspectImage(source));
+                        }
+                        res.send({});
+                  }
+            });
 
-        register({
-            method: Method.POST,
-            subscription: "/uploadURI",
-            secureHandler: ({ req, res }) => {
-                const uri = req.body.uri;
-                const filename = req.body.name;
-                const origSuffix = req.body.nosuffix ? SizeSuffix.None : SizeSuffix.Original;
-                if (!uri || !filename) {
-                    res.status(401).send("incorrect parameters specified");
-                    return;
-                }
-                return imageDataUri.outputFile(uri, serverPathToFile(Directory.images, InjectSize(filename, origSuffix))).then((savedName: string) => {
-                    const ext = extname(savedName).toLowerCase();
-                    const { pngs, jpgs } = AcceptableMedia;
-                    const resizers = !origSuffix ? [{ resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: "_m" }] : [
-                        { resizer: sharp().resize(100, undefined, { withoutEnlargement: true }), suffix: "_s" },
-                        { resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: "_m" },
-                        { resizer: sharp().resize(900, undefined, { withoutEnlargement: true }), suffix: "_l" },
-                    ];
-                    let isImage = false;
-                    if (pngs.includes(ext)) {
-                        resizers.forEach(element => {
-                            element.resizer = element.resizer.png();
-                        });
-                        isImage = true;
-                    } else if (jpgs.includes(ext)) {
-                        resizers.forEach(element => {
-                            element.resizer = element.resizer.jpeg();
-                        });
-                        isImage = true;
-                    }
-                    if (isImage) {
-                        resizers.forEach(resizer => {
-                            const path = serverPathToFile(Directory.images, filename + resizer.suffix + ext);
-                            createReadStream(savedName).pipe(resizer.resizer).pipe(createWriteStream(path));
-                        });
+            register({
+                  method: Method.POST,
+                  subscription: "/uploadURI",
+                  secureHandler: ({ req, res }) => {
+                        const uri = req.body.uri;
+                        const filename = req.body.name;
+                        const origSuffix = req.body.nosuffix ? SizeSuffix.None : SizeSuffix.Original;
+                        if (!uri || !filename) {
+                              res.status(401).send("incorrect parameters specified");
+                              return;
+                        }
+                        return imageDataUri.outputFile(uri, serverPathToFile(Directory.images, InjectSize(filename, origSuffix))).then((savedName: string) => {
+                              const ext = extname(savedName).toLowerCase();
+                              const { pngs, jpgs } = AcceptableMedia;
+                              const resizers = !origSuffix ? [{ resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: "_m" }] : [
+                                    { resizer: sharp().resize(100, undefined, { withoutEnlargement: true }), suffix: "_s" },
+                                    { resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: "_m" },
+                                    { resizer: sharp().resize(900, undefined, { withoutEnlargement: true }), suffix: "_l" },
+                              ];
+                              let isImage = false;
+                              if (pngs.includes(ext)) {
+                                    resizers.forEach(element => {
+                                          element.resizer = element.resizer.png();
+                                    });
+                                    isImage = true;
+                              } else if (jpgs.includes(ext)) {
+                                    resizers.forEach(element => {
+                                          element.resizer = element.resizer.jpeg();
+                                    });
+                                    isImage = true;
+                              }
+                              if (isImage) {
+                                    resizers.forEach(resizer => {
+                                          const path = serverPathToFile(Directory.images, filename + resizer.suffix + ext);
+                                          createReadStream(savedName).pipe(resizer.resizer).pipe(createWriteStream(path));
+                                    });
 
-                    }
-                    res.send(clientPathToFile(Directory.images, filename + ext));
-                });
-            }
-        });
+                              }
+                              res.send(clientPathToFile(Directory.images, filename + ext));
+                        });
+                  }
+            });
 
-    }
+      }
 
 }
 function delay(ms: number) {
-    return new Promise(resolve => setTimeout(resolve, ms));
+      return new Promise(resolve => setTimeout(resolve, ms));
 }
 /**
  * On success, returns a buffer containing the bytes of a screenshot
@@ -309,25 +309,25 @@ function delay(ms: number) {
  * On failure, returns undefined.
  */
 async function captureYoutubeScreenshot(targetUrl: string) {
-    // const browser = await launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] });
-    // const page = await browser.newPage();
-    // // await page.setViewport({ width: 1920, height: 1080 });
+      // const browser = await launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] });
+      // const page = await browser.newPage();
+      // // await page.setViewport({ width: 1920, height: 1080 });
 
-    // // await page.goto(targetUrl, { waitUntil: 'domcontentloaded' as any });
+      // // await page.goto(targetUrl, { waitUntil: 'domcontentloaded' as any });
 
-    // const videoPlayer = await page.$('.html5-video-player');
-    // videoPlayer && await page.focus("video");
-    // await delay(7000);
-    // const ad = await page.$('.ytp-ad-skip-button-text');
-    // await ad?.click();
-    // await videoPlayer?.click();
-    // await delay(1000);
-    // // hide youtube player controls.
-    // await page.evaluate(() => (document.querySelector('.ytp-chrome-bottom') as HTMLElement).style.display = 'none');
+      // const videoPlayer = await page.$('.html5-video-player');
+      // videoPlayer && await page.focus("video");
+      // await delay(7000);
+      // const ad = await page.$('.ytp-ad-skip-button-text');
+      // await ad?.click();
+      // await videoPlayer?.click();
+      // await delay(1000);
+      // // hide youtube player controls.
+      // await page.evaluate(() => (document.querySelector('.ytp-chrome-bottom') as HTMLElement).style.display = 'none');
 
-    // const buffer = await videoPlayer?.screenshot({ encoding: "binary" });
-    // await browser.close();
+      // const buffer = await videoPlayer?.screenshot({ encoding: "binary" });
+      // await browser.close();
 
-    // return buffer;
-    return null;
+      // return buffer;
+      return null;
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From ddcab916cf125817bb532b7c34617e50bcc3840d Mon Sep 17 00:00:00 2001
From: Jenny Yu <jennyyu212@outlook.com>
Date: Tue, 26 Apr 2022 01:39:51 -0400
Subject: feat: uploading works

---
 src/client/Network.ts                              |   3 -
 .../views/nodes/RecordingBox/RecordingBox.tsx      |   9 +-
 .../views/nodes/RecordingBox/RecordingView.tsx     |  27 +-
 src/client/views/nodes/ScreenshotBox.tsx           | 429 +++++++++++----------
 4 files changed, 240 insertions(+), 228 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/client/Network.ts b/src/client/Network.ts
index 58f356c90..3597e7b2b 100644
--- a/src/client/Network.ts
+++ b/src/client/Network.ts
@@ -19,7 +19,6 @@ export namespace Networking {
       }
 
       export async function UploadFilesToServer<T extends Upload.FileInformation = Upload.FileInformation>(files: File | File[]): Promise<Upload.FileResponse<T>[]> {
-            console.log(files)
             const formData = new FormData();
             if (Array.isArray(files)) {
                   if (!files.length) {
@@ -34,8 +33,6 @@ export namespace Networking {
                   body: formData
             };
             const response = await fetch("/uploadFormData", parameters);
-            console.log(response)
-            // console.log(response.json())
             return response.json();
       }
 
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 1e17e2ddd..4c7fdd278 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -1,12 +1,13 @@
 import { action, observable } from "mobx";
 import { observer } from "mobx-react";
 import * as React from "react";
-import { AudioField } from "../../../../fields/URLField";
+import { AudioField, VideoField } from "../../../../fields/URLField";
 import { Upload } from "../../../../server/SharedMediaTypes";
 import { ViewBoxBaseComponent } from "../../DocComponent";
 import { FieldView } from "../FieldView";
 import { VideoBox } from "../VideoBox";
 import { RecordingView } from './RecordingView';
+import { DocumentType } from "../../../documents/DocumentTypes";
 
 
 @observer
@@ -27,7 +28,11 @@ export class RecordingBox extends ViewBoxBaseComponent() {
             console.log("Setting result to " + info)
             this.result = info
             console.log(this.result.accessPaths.agnostic.client)
-            this.props.Document[this.fieldKey] = new AudioField(this.result.accessPaths.agnostic.client);
+            this.dataDoc.type = DocumentType.VID;
+            this.layoutDoc.layout = VideoBox.LayoutString(this.fieldKey);
+            this.dataDoc.nativeWidth = this.dataDoc.nativeHeight = undefined;
+            this.layoutDoc._fitWidth = undefined;
+            this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.agnostic.client);
       }
 
       render() {
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 0d24f3c74..3a79f790f 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -27,7 +27,6 @@ interface IRecordingViewProps {
 const MAXTIME = 1000;
 
 export function RecordingView(props: IRecordingViewProps) {
-      const { setResult } = props
 
       const [recording, setRecording] = useState(false);
       const recordingTimerRef = useRef<number>(0);
@@ -52,11 +51,11 @@ export function RecordingView(props: IRecordingViewProps) {
                   width: 1280,
                   height: 720,
             },
-            audio: {
-                  echoCancellation: true,
-                  noiseSuppression: true,
-                  sampleRate: 44100
-            }
+            // audio: {
+            //       echoCancellation: true,
+            //       noiseSuppression: true,
+            //       sampleRate: 44100
+            // }
       }
 
       useEffect(() => {
@@ -75,7 +74,7 @@ export function RecordingView(props: IRecordingViewProps) {
                         type: 'video/webm'
                   })
                   const blobUrl = URL.createObjectURL(blob)
-                  const videoFile = new File([blob], "video", { lastModified: new Date().getDate() });
+                  const videoFile = new File(allVideoChunks, "video", { type: allVideoChunks[0].type, lastModified: Date.now() });
 
                   videoElementRef.current!.srcObject = null
                   videoElementRef.current!.src = blobUrl
@@ -89,12 +88,20 @@ export function RecordingView(props: IRecordingViewProps) {
                   //       }
                   // }
 
-                  Networking.UploadFilesToServer(allVideoChunks)
+                  Networking.UploadFilesToServer(videoFile)
                         .then((data) => {
-                              console.log(data)
+                              const result = data[0].result
+                              if (!(result instanceof Error)) { // convert this screenshotBox into normal videoBox
+                                    props.setResult(result)
+                              } else {
+                                    alert("video conversion failed");
+                              }
                         })
                   // uploadVideo()
 
+                  //     this.dataDoc[this.fieldKey + "-duration"] = (new Date().getTime() - this.recordingStart!) / 1000;
+
+
 
                   // change to one recording box
             }
@@ -150,6 +157,8 @@ export function RecordingView(props: IRecordingViewProps) {
       }
       const startShowingStream = async (mediaConstraints = DEFAULT_MEDIA_CONSTRAINTS) => {
             const stream = await navigator.mediaDevices.getUserMedia(mediaConstraints)
+            // const stream = await navigator.mediaDevices.getUserMedia({ video: true });
+
 
             videoElementRef.current!.src = ""
             videoElementRef.current!.srcObject = stream
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index dbb567d3a..0c7d7dc31 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -26,7 +26,7 @@ import { FormattedTextBox } from "./formattedText/FormattedTextBox";
 import "./ScreenshotBox.scss";
 import { VideoBox } from "./VideoBox";
 declare class MediaRecorder {
-    constructor(e: any, options?: any);  // whatever MediaRecorder has
+      constructor(e: any, options?: any);  // whatever MediaRecorder has
 }
 
 // interface VideoTileProps {
@@ -107,225 +107,226 @@ declare class MediaRecorder {
 
 @observer
 export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps>() {
-    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ScreenshotBox, fieldKey); }
-    private _audioRec: any;
-    private _videoRec: any;
-    @observable private _videoRef: HTMLVideoElement | null = null;
-    @observable _screenCapture = false;
-    @computed get recordingStart() { return Cast(this.dataDoc[this.props.fieldKey + "-recordingStart"], DateField)?.date.getTime(); }
+      public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ScreenshotBox, fieldKey); }
+      private _audioRec: any;
+      private _videoRec: any;
+      @observable private _videoRef: HTMLVideoElement | null = null;
+      @observable _screenCapture = false;
+      @computed get recordingStart() { return Cast(this.dataDoc[this.props.fieldKey + "-recordingStart"], DateField)?.date.getTime(); }
 
-    constructor(props: any) {
-        super(props);
-        if (this.rootDoc.videoWall) {
-            this.rootDoc.nativeWidth = undefined;
-            this.rootDoc.nativeHeight = undefined;
-            this.layoutDoc.popOff = 0;
-            this.layoutDoc.popOut = 1;
-        } else {
-            this.setupDictation();
-        }
-    }
-    getAnchor = () => {
-        const startTime = Cast(this.layoutDoc._currentTimecode, "number", null) || (this._videoRec ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined);
-        return CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, "_timecodeToShow", "_timecodeToHide",
-            startTime, startTime === undefined ? undefined : startTime + 3)
-            || this.rootDoc;
-    }
+      constructor(props: any) {
+            super(props);
+            if (this.rootDoc.videoWall) {
+                  this.rootDoc.nativeWidth = undefined;
+                  this.rootDoc.nativeHeight = undefined;
+                  this.layoutDoc.popOff = 0;
+                  this.layoutDoc.popOut = 1;
+            } else {
+                  this.setupDictation();
+            }
+      }
+      getAnchor = () => {
+            const startTime = Cast(this.layoutDoc._currentTimecode, "number", null) || (this._videoRec ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined);
+            return CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, "_timecodeToShow", "_timecodeToHide",
+                  startTime, startTime === undefined ? undefined : startTime + 3)
+                  || this.rootDoc;
+      }
 
-    videoLoad = () => {
-        const aspect = this._videoRef!.videoWidth / this._videoRef!.videoHeight;
-        const nativeWidth = Doc.NativeWidth(this.layoutDoc);
-        const nativeHeight = Doc.NativeHeight(this.layoutDoc);
-        if (!nativeWidth || !nativeHeight) {
-            if (!nativeWidth) Doc.SetNativeWidth(this.dataDoc, 1200);
-            Doc.SetNativeHeight(this.dataDoc, (nativeWidth || 1200) / aspect);
-            this.layoutDoc._height = (this.layoutDoc[WidthSym]() || 0) / aspect;
-        }
-    }
+      videoLoad = () => {
+            const aspect = this._videoRef!.videoWidth / this._videoRef!.videoHeight;
+            const nativeWidth = Doc.NativeWidth(this.layoutDoc);
+            const nativeHeight = Doc.NativeHeight(this.layoutDoc);
+            if (!nativeWidth || !nativeHeight) {
+                  if (!nativeWidth) Doc.SetNativeWidth(this.dataDoc, 1200);
+                  Doc.SetNativeHeight(this.dataDoc, (nativeWidth || 1200) / aspect);
+                  this.layoutDoc._height = (this.layoutDoc[WidthSym]() || 0) / aspect;
+            }
+      }
 
-    componentDidMount() {
-        this.dataDoc.nativeWidth = this.dataDoc.nativeHeight = 0;
-        this.props.setContentView?.(this); // this tells the DocumentView that this ScreenshotBox is the "content" of the document.  this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link.
-        // this.rootDoc.videoWall && reaction(() => ({ width: this.props.PanelWidth(), height: this.props.PanelHeight() }),
-        //     ({ width, height }) => {
-        //         if (this._camera) {
-        //             const angle = -Math.abs(1 - width / height);
-        //             const xz = [0, (this._numScreens - 2) / Math.abs(1 + angle)];
-        //             this._camera.position.set(this._numScreens / 2 + xz[1] * Math.sin(angle), this._numScreens / 2, xz[1] * Math.cos(angle));
-        //             this._camera.lookAt(this._numScreens / 2, this._numScreens / 2, 0);
-        //             (this._camera as any).updateProjectionMatrix();
-        //         }
-        //     });
-    }
-    componentWillUnmount() {
-        const ind = DocUtils.ActiveRecordings.indexOf(this);
-        ind !== -1 && (DocUtils.ActiveRecordings.splice(ind, 1));
-    }
+      componentDidMount() {
+            this.dataDoc.nativeWidth = this.dataDoc.nativeHeight = 0;
+            this.props.setContentView?.(this); // this tells the DocumentView that this ScreenshotBox is the "content" of the document.  this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link.
+            // this.rootDoc.videoWall && reaction(() => ({ width: this.props.PanelWidth(), height: this.props.PanelHeight() }),
+            //     ({ width, height }) => {
+            //         if (this._camera) {
+            //             const angle = -Math.abs(1 - width / height);
+            //             const xz = [0, (this._numScreens - 2) / Math.abs(1 + angle)];
+            //             this._camera.position.set(this._numScreens / 2 + xz[1] * Math.sin(angle), this._numScreens / 2, xz[1] * Math.cos(angle));
+            //             this._camera.lookAt(this._numScreens / 2, this._numScreens / 2, 0);
+            //             (this._camera as any).updateProjectionMatrix();
+            //         }
+            //     });
+      }
+      componentWillUnmount() {
+            const ind = DocUtils.ActiveRecordings.indexOf(this);
+            ind !== -1 && (DocUtils.ActiveRecordings.splice(ind, 1));
+      }
 
-    specificContextMenu = (e: React.MouseEvent): void => {
-        const subitems = [{ description: "Screen Capture", event: this.toggleRecording, icon: "expand-arrows-alt" as any }];
-        ContextMenu.Instance.addItem({ description: "Options...", subitems, icon: "video" });
-    }
+      specificContextMenu = (e: React.MouseEvent): void => {
+            const subitems = [{ description: "Screen Capture", event: this.toggleRecording, icon: "expand-arrows-alt" as any }];
+            ContextMenu.Instance.addItem({ description: "Options...", subitems, icon: "video" });
+      }
 
-    @computed get content() {
-        if (this.rootDoc.videoWall) return (null);
-        return <video className={"videoBox-content"} key="video"
-            ref={r => {
-                this._videoRef = r;
-                setTimeout(() => {
-                    if (this.rootDoc.mediaState === "pendingRecording" && this._videoRef) {
-                        this.toggleRecording();
-                    }
-                }, 100);
-            }}
-            autoPlay={this._screenCapture}
-            style={{ width: this._screenCapture ? "100%" : undefined, height: this._screenCapture ? "100%" : undefined }}
-            onCanPlay={this.videoLoad}
-            controls={true}
-            onClick={e => e.preventDefault()}>
-            <source type="video/mp4" />
-            Not supported.
-        </video>;
-    }
+      @computed get content() {
+            if (this.rootDoc.videoWall) return (null);
+            return <video className={"videoBox-content"} key="video"
+                  ref={r => {
+                        this._videoRef = r;
+                        setTimeout(() => {
+                              if (this.rootDoc.mediaState === "pendingRecording" && this._videoRef) {
+                                    this.toggleRecording();
+                              }
+                        }, 100);
+                  }}
+                  autoPlay={this._screenCapture}
+                  style={{ width: this._screenCapture ? "100%" : undefined, height: this._screenCapture ? "100%" : undefined }}
+                  onCanPlay={this.videoLoad}
+                  controls={true}
+                  onClick={e => e.preventDefault()}>
+                  <source type="video/mp4" />
+                  Not supported.
+            </video>;
+      }
 
-    // _numScreens = 5;
-    // _camera: Camera | undefined;
-    // @observable _raised = [] as { coord: Vector2, off: Vector3 }[];
-    // @action setRaised = (r: { coord: Vector2, off: Vector3 }[]) => this._raised = r;
-    @computed get threed() {
-        // if (this.rootDoc.videoWall) {
-        //     const screens: any[] = [];
-        //     const colors = ["yellow", "red", "orange", "brown", "maroon", "gray"];
-        //     let count = 0;
-        //     numberRange(this._numScreens).forEach(x => numberRange(this._numScreens).forEach(y => screens.push(
-        //         <VideoTile rootDoc={this.rootDoc} color={colors[count++ % colors.length]} x={x} y={y} raised={this._raised} setRaised={this.setRaised} />)));
-        //     return <Canvas key="canvas" id="CANCAN" style={{ width: this.props.PanelWidth(), height: this.props.PanelHeight() }} gl={{ antialias: false }} colorManagement={false} onCreated={props => {
-        //         this._camera = props.camera;
-        //         props.camera.position.set(this._numScreens / 2, this._numScreens / 2, this._numScreens - 2);
-        //         props.camera.lookAt(this._numScreens / 2, this._numScreens / 2, 0);
-        //     }}>
-        //         {/* <ambientLight />*/}
-        //         <pointLight position={[10, 10, 10]} intensity={1} />
-        //         {screens}
-        //     </ Canvas>;
-        // }
-        return (null);
-    }
-    toggleRecording = async () => {
-        if (!this._screenCapture) {
-            this._audioRec = new MediaRecorder(await navigator.mediaDevices.getUserMedia({ audio: true }));
-            const aud_chunks: any = [];
-            this._audioRec.ondataavailable = (e: any) => aud_chunks.push(e.data);
-            this._audioRec.onstop = async (e: any) => {
-                const [{ result }] = await Networking.UploadFilesToServer(aud_chunks);
-                if (!(result instanceof Error)) {
-                    this.dataDoc[this.props.fieldKey + "-audio"] = new AudioField(result.accessPaths.agnostic.client);
-                }
-            };
-            this._videoRef!.srcObject = await (navigator.mediaDevices as any).getDisplayMedia({ video: true });
-            this._videoRec = new MediaRecorder(this._videoRef!.srcObject);
-            const vid_chunks: any = [];
-            this._videoRec.onstart = () => this.dataDoc[this.props.fieldKey + "-recordingStart"] = new DateField(new Date());
-            this._videoRec.ondataavailable = (e: any) => vid_chunks.push(e.data);
-            this._videoRec.onstop = async (e: any) => {
-                const file = new File(vid_chunks, `${this.rootDoc[Id]}.mkv`, { type: vid_chunks[0].type, lastModified: Date.now() });
-                const [{ result }] = await Networking.UploadFilesToServer(file);
-                this.dataDoc[this.fieldKey + "-duration"] = (new Date().getTime() - this.recordingStart!) / 1000;
-                if (!(result instanceof Error)) { // convert this screenshotBox into normal videoBox
-                    this.dataDoc.type = DocumentType.VID;
-                    this.layoutDoc.layout = VideoBox.LayoutString(this.fieldKey);
-                    this.dataDoc.nativeWidth = this.dataDoc.nativeHeight = undefined;
-                    this.layoutDoc._fitWidth = undefined;
-                    this.dataDoc[this.props.fieldKey] = new VideoField(result.accessPaths.agnostic.client);
-                } else alert("video conversion failed");
-            };
-            this._audioRec.start();
-            this._videoRec.start();
-            runInAction(() => {
-                this._screenCapture = true;
-                this.dataDoc.mediaState = "recording";
-            });
-            DocUtils.ActiveRecordings.push(this);
-        } else {
-            this._audioRec?.stop();
-            this._videoRec?.stop();
-            runInAction(() => {
-                this._screenCapture = false;
-                this.dataDoc.mediaState = "paused";
-            });
-            const ind = DocUtils.ActiveRecordings.indexOf(this);
-            ind !== -1 && (DocUtils.ActiveRecordings.splice(ind, 1));
+      // _numScreens = 5;
+      // _camera: Camera | undefined;
+      // @observable _raised = [] as { coord: Vector2, off: Vector3 }[];
+      // @action setRaised = (r: { coord: Vector2, off: Vector3 }[]) => this._raised = r;
+      @computed get threed() {
+            // if (this.rootDoc.videoWall) {
+            //     const screens: any[] = [];
+            //     const colors = ["yellow", "red", "orange", "brown", "maroon", "gray"];
+            //     let count = 0;
+            //     numberRange(this._numScreens).forEach(x => numberRange(this._numScreens).forEach(y => screens.push(
+            //         <VideoTile rootDoc={this.rootDoc} color={colors[count++ % colors.length]} x={x} y={y} raised={this._raised} setRaised={this.setRaised} />)));
+            //     return <Canvas key="canvas" id="CANCAN" style={{ width: this.props.PanelWidth(), height: this.props.PanelHeight() }} gl={{ antialias: false }} colorManagement={false} onCreated={props => {
+            //         this._camera = props.camera;
+            //         props.camera.position.set(this._numScreens / 2, this._numScreens / 2, this._numScreens - 2);
+            //         props.camera.lookAt(this._numScreens / 2, this._numScreens / 2, 0);
+            //     }}>
+            //         {/* <ambientLight />*/}
+            //         <pointLight position={[10, 10, 10]} intensity={1} />
+            //         {screens}
+            //     </ Canvas>;
+            // }
+            return (null);
+      }
+      toggleRecording = async () => {
+            if (!this._screenCapture) {
+                  this._audioRec = new MediaRecorder(await navigator.mediaDevices.getUserMedia({ audio: true }));
+                  const aud_chunks: any = [];
+                  this._audioRec.ondataavailable = (e: any) => aud_chunks.push(e.data);
+                  this._audioRec.onstop = async (e: any) => {
+                        const [{ result }] = await Networking.UploadFilesToServer(aud_chunks);
+                        if (!(result instanceof Error)) {
+                              this.dataDoc[this.props.fieldKey + "-audio"] = new AudioField(result.accessPaths.agnostic.client);
+                        }
+                  };
+                  this._videoRef!.srcObject = await (navigator.mediaDevices as any).getDisplayMedia({ video: true });
+                  this._videoRec = new MediaRecorder(this._videoRef!.srcObject);
+                  const vid_chunks: any = [];
+                  this._videoRec.onstart = () => this.dataDoc[this.props.fieldKey + "-recordingStart"] = new DateField(new Date());
+                  this._videoRec.ondataavailable = (e: any) => vid_chunks.push(e.data);
+                  this._videoRec.onstop = async (e: any) => {
+                        console.log("screenshotbox: upload")
+                        const file = new File(vid_chunks, `${this.rootDoc[Id]}.mkv`, { type: vid_chunks[0].type, lastModified: Date.now() });
+                        const [{ result }] = await Networking.UploadFilesToServer(file);
+                        this.dataDoc[this.fieldKey + "-duration"] = (new Date().getTime() - this.recordingStart!) / 1000;
+                        if (!(result instanceof Error)) { // convert this screenshotBox into normal videoBox
+                              this.dataDoc.type = DocumentType.VID;
+                              this.layoutDoc.layout = VideoBox.LayoutString(this.fieldKey);
+                              this.dataDoc.nativeWidth = this.dataDoc.nativeHeight = undefined;
+                              this.layoutDoc._fitWidth = undefined;
+                              this.dataDoc[this.props.fieldKey] = new VideoField(result.accessPaths.agnostic.client);
+                        } else alert("video conversion failed");
+                  };
+                  this._audioRec.start();
+                  this._videoRec.start();
+                  runInAction(() => {
+                        this._screenCapture = true;
+                        this.dataDoc.mediaState = "recording";
+                  });
+                  DocUtils.ActiveRecordings.push(this);
+            } else {
+                  this._audioRec?.stop();
+                  this._videoRec?.stop();
+                  runInAction(() => {
+                        this._screenCapture = false;
+                        this.dataDoc.mediaState = "paused";
+                  });
+                  const ind = DocUtils.ActiveRecordings.indexOf(this);
+                  ind !== -1 && (DocUtils.ActiveRecordings.splice(ind, 1));
 
-            CaptureManager.Instance.open(this.rootDoc);
-        }
-    }
+                  CaptureManager.Instance.open(this.rootDoc);
+            }
+      }
 
-    setupDictation = () => {
-        if (this.dataDoc[this.fieldKey + "-dictation"]) return;
-        const dictationText = CurrentUserUtils.GetNewTextDoc("dictation",
-            NumCast(this.rootDoc.x), NumCast(this.rootDoc.y) + NumCast(this.layoutDoc._height) + 10,
-            NumCast(this.layoutDoc._width), 2 * NumCast(this.layoutDoc._height));
-        dictationText._autoHeight = false;
-        const dictationTextProto = Doc.GetProto(dictationText);
-        dictationTextProto.recordingSource = this.dataDoc;
-        dictationTextProto.recordingStart = ComputedField.MakeFunction(`self.recordingSource["${this.props.fieldKey}-recordingStart"]`);
-        dictationTextProto.mediaState = ComputedField.MakeFunction("self.recordingSource.mediaState");
-        this.dataDoc[this.fieldKey + "-dictation"] = dictationText;
-    }
-    contentFunc = () => [this.threed, this.content];
-    videoPanelHeight = () => NumCast(this.dataDoc[this.fieldKey + "-nativeHeight"], this.layoutDoc[HeightSym]()) / NumCast(this.dataDoc[this.fieldKey + "-nativeWidth"], this.layoutDoc[WidthSym]()) * this.props.PanelWidth();
-    formattedPanelHeight = () => Math.max(0, this.props.PanelHeight() - this.videoPanelHeight());
-    render() {
-        TraceMobx();
-        return <div className="videoBox" onContextMenu={this.specificContextMenu} style={{ width: "100%", height: "100%" }} >
-            <div className="videoBox-viewer" >
-                <div style={{ position: "relative", height: this.videoPanelHeight() }}>
-                    <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
-                        PanelHeight={this.videoPanelHeight}
-                        PanelWidth={this.props.PanelWidth}
-                        focus={this.props.focus}
-                        isSelected={this.props.isSelected}
-                        isAnnotationOverlay={true}
-                        select={emptyFunction}
-                        isContentActive={returnFalse}
-                        scaling={returnOne}
-                        whenChildContentsActiveChanged={emptyFunction}
-                        removeDocument={returnFalse}
-                        moveDocument={returnFalse}
-                        addDocument={returnFalse}
-                        CollectionView={undefined}
-                        ScreenToLocalTransform={this.props.ScreenToLocalTransform}
-                        renderDepth={this.props.renderDepth + 1}
-                        ContainingCollectionDoc={this.props.ContainingCollectionDoc}>
-                        {this.contentFunc}
-                    </CollectionFreeFormView></div>
-                <div style={{ position: "relative", height: this.formattedPanelHeight() }}>
-                    {!(this.dataDoc[this.fieldKey + "-dictation"] instanceof Doc) ? (null) :
-                        <FormattedTextBox {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
-                            Document={this.dataDoc[this.fieldKey + "-dictation"]}
-                            fieldKey={"text"}
-                            PanelHeight={this.formattedPanelHeight}
-                            isAnnotationOverlay={true}
-                            select={emptyFunction}
-                            isContentActive={emptyFunction}
-                            scaling={returnOne}
-                            xPadding={25}
-                            yPadding={10}
-                            whenChildContentsActiveChanged={emptyFunction}
-                            removeDocument={returnFalse}
-                            moveDocument={returnFalse}
-                            addDocument={returnFalse}
-                            CollectionView={undefined}
-                            renderDepth={this.props.renderDepth + 1}
-                            ContainingCollectionDoc={this.props.ContainingCollectionDoc}>
-                        </FormattedTextBox>}
-                </div>
-            </div>
-            {!this.props.isSelected() ? (null) : <div className="screenshotBox-uiButtons">
-                <div className="screenshotBox-recorder" key="snap" onPointerDown={this.toggleRecording} >
-                    <FontAwesomeIcon icon="file" size="lg" />
-                </div>
-            </div>}
-        </div >;
-    }
+      setupDictation = () => {
+            if (this.dataDoc[this.fieldKey + "-dictation"]) return;
+            const dictationText = CurrentUserUtils.GetNewTextDoc("dictation",
+                  NumCast(this.rootDoc.x), NumCast(this.rootDoc.y) + NumCast(this.layoutDoc._height) + 10,
+                  NumCast(this.layoutDoc._width), 2 * NumCast(this.layoutDoc._height));
+            dictationText._autoHeight = false;
+            const dictationTextProto = Doc.GetProto(dictationText);
+            dictationTextProto.recordingSource = this.dataDoc;
+            dictationTextProto.recordingStart = ComputedField.MakeFunction(`self.recordingSource["${this.props.fieldKey}-recordingStart"]`);
+            dictationTextProto.mediaState = ComputedField.MakeFunction("self.recordingSource.mediaState");
+            this.dataDoc[this.fieldKey + "-dictation"] = dictationText;
+      }
+      contentFunc = () => [this.threed, this.content];
+      videoPanelHeight = () => NumCast(this.dataDoc[this.fieldKey + "-nativeHeight"], this.layoutDoc[HeightSym]()) / NumCast(this.dataDoc[this.fieldKey + "-nativeWidth"], this.layoutDoc[WidthSym]()) * this.props.PanelWidth();
+      formattedPanelHeight = () => Math.max(0, this.props.PanelHeight() - this.videoPanelHeight());
+      render() {
+            TraceMobx();
+            return <div className="videoBox" onContextMenu={this.specificContextMenu} style={{ width: "100%", height: "100%" }} >
+                  <div className="videoBox-viewer" >
+                        <div style={{ position: "relative", height: this.videoPanelHeight() }}>
+                              <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
+                                    PanelHeight={this.videoPanelHeight}
+                                    PanelWidth={this.props.PanelWidth}
+                                    focus={this.props.focus}
+                                    isSelected={this.props.isSelected}
+                                    isAnnotationOverlay={true}
+                                    select={emptyFunction}
+                                    isContentActive={returnFalse}
+                                    scaling={returnOne}
+                                    whenChildContentsActiveChanged={emptyFunction}
+                                    removeDocument={returnFalse}
+                                    moveDocument={returnFalse}
+                                    addDocument={returnFalse}
+                                    CollectionView={undefined}
+                                    ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                                    renderDepth={this.props.renderDepth + 1}
+                                    ContainingCollectionDoc={this.props.ContainingCollectionDoc}>
+                                    {this.contentFunc}
+                              </CollectionFreeFormView></div>
+                        <div style={{ position: "relative", height: this.formattedPanelHeight() }}>
+                              {!(this.dataDoc[this.fieldKey + "-dictation"] instanceof Doc) ? (null) :
+                                    <FormattedTextBox {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
+                                          Document={this.dataDoc[this.fieldKey + "-dictation"]}
+                                          fieldKey={"text"}
+                                          PanelHeight={this.formattedPanelHeight}
+                                          isAnnotationOverlay={true}
+                                          select={emptyFunction}
+                                          isContentActive={emptyFunction}
+                                          scaling={returnOne}
+                                          xPadding={25}
+                                          yPadding={10}
+                                          whenChildContentsActiveChanged={emptyFunction}
+                                          removeDocument={returnFalse}
+                                          moveDocument={returnFalse}
+                                          addDocument={returnFalse}
+                                          CollectionView={undefined}
+                                          renderDepth={this.props.renderDepth + 1}
+                                          ContainingCollectionDoc={this.props.ContainingCollectionDoc}>
+                                    </FormattedTextBox>}
+                        </div>
+                  </div>
+                  {!this.props.isSelected() ? (null) : <div className="screenshotBox-uiButtons">
+                        <div className="screenshotBox-recorder" key="snap" onPointerDown={this.toggleRecording} >
+                              <FontAwesomeIcon icon="file" size="lg" />
+                        </div>
+                  </div>}
+            </div >;
+      }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 73ed47a8fbc6c4827c5d553e385396661d940787 Mon Sep 17 00:00:00 2001
From: Jenny Yu <jennyyu212@outlook.com>
Date: Wed, 27 Apr 2022 15:05:44 -0400
Subject: recording only has 0 second

---
 .../views/nodes/RecordingBox/RecordingView.tsx     | 99 ++++++++++------------
 1 file changed, 47 insertions(+), 52 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 3a79f790f..16f750e14 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -15,8 +15,8 @@ enum RecordingStatus {
       Paused
 }
 
-interface VideoSegment {
-      chunks: any[],
+interface MediaSegment {
+      videoChunks: any[],
       endTime: number
 }
 
@@ -36,10 +36,10 @@ export function RecordingView(props: IRecordingViewProps) {
       const [speed, setSpeed] = useState(1);
       const [muted, setMuted] = useState(false);
 
-      const [videos, setVideos] = useState<VideoSegment[]>([]);
-      // const [videos, setVideos] = useState<string[]>([]);
+      const [videos, setVideos] = useState<MediaSegment[]>([]);
       const [currentVid, setCurrentVid] = useState<number>(0);
-      const recorder = useRef<MediaRecorder | null>(null);
+      const videoRecorder = useRef<MediaRecorder | null>(null);
+      const audioRecorder = useRef<MediaRecorder | null>(null);
       const videoElementRef = useRef<HTMLVideoElement | null>(null);
 
       const [finished, setFinished] = useState<Boolean>(false)
@@ -47,10 +47,13 @@ export function RecordingView(props: IRecordingViewProps) {
 
 
       const DEFAULT_MEDIA_CONSTRAINTS = {
-            video: {
-                  width: 1280,
-                  height: 720,
-            },
+            video: true,
+            // audio: true
+            // video: {
+            //       width: 1280,
+            //       height: 720,
+            // },
+            // audio: true,
             // audio: {
             //       echoCancellation: true,
             //       noiseSuppression: true,
@@ -64,8 +67,8 @@ export function RecordingView(props: IRecordingViewProps) {
                   let allVideoChunks: any = []
                   console.log(videos)
                   videos.forEach((vid) => {
-                        console.log(vid.chunks)
-                        allVideoChunks = allVideoChunks.concat(vid.chunks)
+                        console.log(vid.videoChunks)
+                        allVideoChunks = allVideoChunks.concat(vid.videoChunks)
                   })
 
                   console.log(allVideoChunks)
@@ -119,21 +122,9 @@ export function RecordingView(props: IRecordingViewProps) {
 
       useEffect(() => {
             // get access to the video element on every render
-            // videoElement = document.getElementById('video') as HTMLVideoElement;
             videoElementRef.current = document.getElementById('video') as HTMLVideoElement;
       })
 
-      // useEffect(() => {
-      //       if (playing) {
-      //             videoElement!.srcObject = null
-      //             // videoElement!.src = videos[currentVid].url
-      //             videoElement!.muted = false
-      //             videoElement!.play()
-      //       } else {
-      //             videoElement!.pause();
-      //       }
-      // }, [playing, videoElement]);
-
       useEffect(() => {
             let interval: any = null;
             if (recording) {
@@ -157,8 +148,6 @@ export function RecordingView(props: IRecordingViewProps) {
       }
       const startShowingStream = async (mediaConstraints = DEFAULT_MEDIA_CONSTRAINTS) => {
             const stream = await navigator.mediaDevices.getUserMedia(mediaConstraints)
-            // const stream = await navigator.mediaDevices.getUserMedia({ video: true });
-
 
             videoElementRef.current!.src = ""
             videoElementRef.current!.srcObject = stream
@@ -169,80 +158,86 @@ export function RecordingView(props: IRecordingViewProps) {
 
       const record = async () => {
             const stream = await startShowingStream();
-            recorder.current = new MediaRecorder(stream)
+            videoRecorder.current = new MediaRecorder(stream)
+            // audioRecorder.current = new MediaRecorder(await navigator.mediaDevices.getUserMedia({ audio: true }));
 
             // temporary chunks of video
-            let chunks: any = []
-            recorder.current.ondataavailable = (event: any) => {
-                  // store the video chunks as it is recording
-                  console.log("data available")
+            let videoChunks: any = []
+            // let audioChunks: any = []
+
+            videoRecorder.current.ondataavailable = (event: any) => {
                   if (event.data.size > 0) {
-                        chunks.push(event.data)
+                        videoChunks.push(event.data)
                   }
             }
 
-            recorder.current.onstart = (event: any) => {
-                  console.log("on start")
+            // audioRecorder.current.ondataavailable = (event: any) => {
+            //       if (event.data.size > 0) {
+            //             audioChunks.push(event.data)
+            //       }
+            // }
+
+            videoRecorder.current.onstart = (event: any) => {
                   setRecording(true);
             }
 
-            recorder.current.onstop = () => {
+            videoRecorder.current.onstop = () => {
                   // if we have a last portion
-                  if (chunks.length > 1) {
+                  if (videoChunks.length > 1) {
                         // append the current portion to the video pieces
-                        setVideos(videos => [...videos, { chunks: chunks, endTime: recordingTimerRef.current }])
+                        setVideos(videos => [...videos, { videoChunks: videoChunks, endTime: recordingTimerRef.current }])
                   }
 
                   // reset the temporary chunks
-                  chunks = []
+                  videoChunks = []
                   setRecording(false);
                   setFinished(true);
             }
 
             // recording paused
-            recorder.current.onpause = (event: any) => {
+            videoRecorder.current.onpause = (event: any) => {
                   // append the current portion to the video pieces
-                  console.log(chunks)
-                  setVideos(videos => [...videos, { chunks: chunks, endTime: recordingTimerRef.current }])
+                  console.log(videoChunks)
+                  setVideos(videos => [...videos, { videoChunks: videoChunks, endTime: recordingTimerRef.current }])
 
                   // reset the temporary chunks
-                  chunks = []
+                  videoChunks = []
                   setRecording(false);
             }
 
-            recorder.current.onresume = async (event: any) => {
+            videoRecorder.current.onresume = async (event: any) => {
                   console.log(event)
                   await startShowingStream();
                   setRecording(true);
             }
 
-            recorder.current.start(200)
+            videoRecorder.current.start(200)
       }
 
 
       const stop = () => {
-            if (recorder.current) {
-                  if (recorder.current.state !== "inactive") {
-                        recorder.current.stop();
+            if (videoRecorder.current) {
+                  if (videoRecorder.current.state !== "inactive") {
+                        videoRecorder.current.stop();
                         // recorder.current.stream.getTracks().forEach((track: any) => track.stop())
                   }
             }
       }
 
       const pause = () => {
-            if (recorder.current) {
-                  if (recorder.current.state === "recording") {
-                        recorder.current.pause();
+            if (videoRecorder.current) {
+                  if (videoRecorder.current.state === "recording") {
+                        videoRecorder.current.pause();
                   }
             }
       }
 
       const startOrResume = () => {
             console.log('[RecordingView.tsx] startOrResume')
-            if (!recorder.current || recorder.current.state === "inactive") {
+            if (!videoRecorder.current || videoRecorder.current.state === "inactive") {
                   record();
-            } else if (recorder.current.state === "paused") {
-                  recorder.current.resume();
+            } else if (videoRecorder.current.state === "paused") {
+                  videoRecorder.current.resume();
             }
       }
 
-- 
cgit v1.2.3-70-g09d2


From 0a84982e2ea59d737f394bc79fa7f26a4bf29a80 Mon Sep 17 00:00:00 2001
From: Jenny Yu <jennyyu212@outlook.com>
Date: Thu, 28 Apr 2022 16:01:49 -0400
Subject: feat: uploading works

---
 package-lock.json                                  | 45 ++++++++++++++++++++--
 src/client/Network.ts                              |  1 +
 .../views/nodes/RecordingBox/RecordingBox.tsx      | 14 ++++++-
 .../views/nodes/RecordingBox/RecordingView.tsx     | 23 ++++-------
 src/client/views/nodes/trails/PresElementBox.tsx   |  2 +
 5 files changed, 65 insertions(+), 20 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/package-lock.json b/package-lock.json
index 0f045c546..684caa92e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -768,9 +768,9 @@
             "integrity": "sha512-BJJH2OXdUreVNdfTCuuO2oHoqBmXSnXtIQvbRYj3LwZ27nnzfY87D/KEUPXnCXj/56kEeVlBbvAbcKKeMRmkSw==",
             "dependencies": {
                 "@typescript/lib-dom": {
-                    "version": "npm:@types/web@0.0.61",
-                    "resolved": "https://registry.npmjs.org/@types/web/-/web-0.0.61.tgz",
-                    "integrity": "sha512-lQ4M3OSh8eFj55fz1RJsLhCubET/7duOXoKcxVaUXYXyxikD9BA+WWrqAn5CjJxrc82b7zFY4OCVIeVdkPLaGg=="
+                    "version": "npm:@types/web@0.0.62",
+                    "resolved": "https://registry.npmjs.org/@types/web/-/web-0.0.62.tgz",
+                    "integrity": "sha512-NI9oDqfsnKHY/VI+4Uomw976LzopMphE2cCAv8cNNdd3LyA2aUolkipIDR5idnyX6Amq5oo2Lbdtj826h7gFjA=="
                 }
             }
         },
@@ -4775,6 +4775,16 @@
             "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
             "dev": true
         },
+        "d": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
+            "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
+            "dev": true,
+            "requires": {
+                "es5-ext": "^0.10.50",
+                "type": "^1.0.1"
+            }
+        },
         "d3-array": {
             "version": "2.12.1",
             "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
@@ -5882,6 +5892,28 @@
                 "is-symbol": "^1.0.2"
             }
         },
+        "es5-ext": {
+            "version": "0.10.61",
+            "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz",
+            "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==",
+            "dev": true,
+            "requires": {
+                "es6-iterator": "^2.0.3",
+                "es6-symbol": "^3.1.3",
+                "next-tick": "^1.1.0"
+            }
+        },
+        "es6-iterator": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
+            "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
+            "dev": true,
+            "requires": {
+                "d": "1",
+                "es5-ext": "^0.10.35",
+                "es6-symbol": "^3.1.1"
+            }
+        },
         "es6-promise": {
             "version": "3.2.1",
             "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz",
@@ -5893,6 +5925,7 @@
             "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
             "dev": true,
             "requires": {
+                "d": "^1.0.1",
                 "ext": "^1.1.2"
             }
         },
@@ -18441,6 +18474,12 @@
             "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
             "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
         },
+        "type": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
+            "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
+            "dev": true
+        },
         "type-check": {
             "version": "0.3.2",
             "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
diff --git a/src/client/Network.ts b/src/client/Network.ts
index 3597e7b2b..1255e5ce0 100644
--- a/src/client/Network.ts
+++ b/src/client/Network.ts
@@ -19,6 +19,7 @@ export namespace Networking {
       }
 
       export async function UploadFilesToServer<T extends Upload.FileInformation = Upload.FileInformation>(files: File | File[]): Promise<Upload.FileResponse<T>[]> {
+            console.log(files)
             const formData = new FormData();
             if (Array.isArray(files)) {
                   if (!files.length) {
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 4c7fdd278..6f9451925 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -22,6 +22,12 @@ export class RecordingBox extends ViewBoxBaseComponent() {
       }
 
       @observable result: Upload.FileInformation | undefined = undefined
+      @observable videoDuration: number | undefined = undefined
+
+      @action
+      setVideoDuration = (duration: number) => {
+            this.videoDuration = duration
+      }
 
       @action
       setResult = (info: Upload.FileInformation) => {
@@ -29,6 +35,9 @@ export class RecordingBox extends ViewBoxBaseComponent() {
             this.result = info
             console.log(this.result.accessPaths.agnostic.client)
             this.dataDoc.type = DocumentType.VID;
+            console.log(this.videoDuration)
+            this.dataDoc[this.fieldKey + "-duration"] = this.videoDuration;
+
             this.layoutDoc.layout = VideoBox.LayoutString(this.fieldKey);
             this.dataDoc.nativeWidth = this.dataDoc.nativeHeight = undefined;
             this.layoutDoc._fitWidth = undefined;
@@ -37,8 +46,9 @@ export class RecordingBox extends ViewBoxBaseComponent() {
 
       render() {
             return <div className="recordingBox" ref={this._ref}>
-                  {!this.result ? <RecordingView setResult={this.setResult} /> :
-                        <p>video box</p>}
+                  {!this.result && <RecordingView setResult={this.setResult} setDuration={this.setVideoDuration} />}
+                  {/* {!this.result ? <RecordingView setResult={this.setResult} /> :
+                        <p>video box</p>} */}
             </div>;
       }
 }
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 16f750e14..6aed07c60 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -22,6 +22,7 @@ interface MediaSegment {
 
 interface IRecordingViewProps {
       setResult: (info: Upload.FileInformation) => void
+      setDuration: (seconds: number) => void
 }
 
 const MAXTIME = 1000;
@@ -47,12 +48,12 @@ export function RecordingView(props: IRecordingViewProps) {
 
 
       const DEFAULT_MEDIA_CONSTRAINTS = {
-            video: true,
+            // video: true,
             // audio: true
-            // video: {
-            //       width: 1280,
-            //       height: 720,
-            // },
+            video: {
+                  width: 1280,
+                  height: 720,
+            },
             // audio: true,
             // audio: {
             //       echoCancellation: true,
@@ -64,6 +65,7 @@ export function RecordingView(props: IRecordingViewProps) {
       useEffect(() => {
 
             if (finished) {
+                  props.setDuration(recordingTimer * 100)
                   let allVideoChunks: any = []
                   console.log(videos)
                   videos.forEach((vid) => {
@@ -72,16 +74,7 @@ export function RecordingView(props: IRecordingViewProps) {
                   })
 
                   console.log(allVideoChunks)
-
-                  const blob = new Blob(allVideoChunks, {
-                        type: 'video/webm'
-                  })
-                  const blobUrl = URL.createObjectURL(blob)
-                  const videoFile = new File(allVideoChunks, "video", { type: allVideoChunks[0].type, lastModified: Date.now() });
-
-                  videoElementRef.current!.srcObject = null
-                  videoElementRef.current!.src = blobUrl
-                  videoElementRef.current!.muted = false
+                  const videoFile = new File(allVideoChunks, "video.mkv", { type: allVideoChunks[0].type, lastModified: Date.now() });
 
                   // const uploadVideo = async () => {
                   //       const [{ result }] = await Networking.UploadFilesToServer(videoFile);
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index aa7622736..92834fb07 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -290,6 +290,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                   console.log("x: ", pt[0], "y: ", pt[1]);
                   recording.x = pt[0];
                   recording.y = pt[1];
+                  console.log(Doc.UserDoc().myOverlayDocs)
+                  // Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc);
                   Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, recording);
             }
 
-- 
cgit v1.2.3-70-g09d2


From 416d9a1ef143cffed341fdb390a245b82c4b4137 Mon Sep 17 00:00:00 2001
From: Jenny Yu <jennyyu212@outlook.com>
Date: Thu, 28 Apr 2022 17:55:49 -0400
Subject: feat: hiding recording

---
 src/client/views/MainView.tsx                      | 1220 +++++++++---------
 .../views/nodes/RecordingBox/RecordingView.tsx     |   41 -
 src/client/views/nodes/button/FontIconBox.tsx      | 1300 ++++++++++----------
 src/client/views/nodes/trails/PresElementBox.tsx   |   55 +-
 4 files changed, 1306 insertions(+), 1310 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 8e9be1eeb..7ee9f5b70 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -68,310 +68,342 @@ const _global = (window /* browser */ || global /* node */) as any;
 
 @observer
 export class MainView extends React.Component {
-    public static Instance: MainView;
-    public static Live: boolean = false;
-    private _docBtnRef = React.createRef<HTMLDivElement>();
-    @observable public LastButton: Opt<Doc>;
-    @observable private _windowWidth: number = 0;
-    @observable private _windowHeight: number = 0;
-    @observable private _dashUIWidth: number = 0;   // width of entire main dashboard region including left menu buttons and properties panel (but not including the dashboard selector button row)
-    @observable private _dashUIHeight: number = 0;  // height of entire main dashboard region including top menu buttons
-    @observable private _panelContent: string = "none";
-    @observable private _sidebarContent: any = this.userDoc?.sidebar;
-    @observable private _leftMenuFlyoutWidth: number = 0;
-
-    @computed private get dashboardTabHeight() { return 27; } //  27 comes form lm.config.defaultConfig.dimensions.headerHeight in goldenlayout.js
-    @computed private get topOfDashUI() { return Number(DASHBOARD_SELECTOR_HEIGHT.replace("px", "")); }
-    @computed private get topOfMainDoc() { return this.topOfDashUI + this.topMenuHeight(); }
-    @computed private get topOfMainDocContent() { return this.topOfMainDoc + this.dashboardTabHeight; }
-    @computed private get leftScreenOffsetOfMainDocView() { return this.leftMenuWidth() - 2; }
-    @computed private get userDoc() { return Doc.UserDoc(); }
-    @computed private get colorScheme() { return StrCast(CurrentUserUtils.ActiveDashboard?.colorScheme); }
-    @computed private get mainContainer() { return this.userDoc ? CurrentUserUtils.ActiveDashboard : CurrentUserUtils.GuestDashboard; }
-    @computed public get mainFreeform(): Opt<Doc> { return (docs => (docs?.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); }
-
-    topMenuHeight = () => 35;
-    topMenuWidth = returnZero; // value is ignored ...
-    leftMenuWidth = () => Number(LEFT_MENU_WIDTH.replace("px", ""));
-    leftMenuHeight = () => this._dashUIHeight;
-    leftMenuFlyoutWidth = () => this._leftMenuFlyoutWidth;
-    leftMenuFlyoutHeight = () => this._dashUIHeight;
-    propertiesWidth = () => Math.max(0, Math.min(this._dashUIWidth - 50, CurrentUserUtils.propertiesWidth || 0));
-    propertiesHeight = () => this._dashUIHeight;
-    mainDocViewWidth = () => this._dashUIWidth - this.propertiesWidth() - this.leftMenuWidth();
-    mainDocViewHeight = () => this._dashUIHeight;
-
-    componentDidMount() {
-        document.getElementById("root")?.addEventListener("scroll", e => ((ele) => ele.scrollLeft = ele.scrollTop = 0)(document.getElementById("root")!));
-        const ele = document.getElementById("loader");
-        const prog = document.getElementById("dash-progress");
-        if (ele && prog) {
-            // remove from DOM
-            setTimeout(() => {
-                clearTimeout();
-                prog.style.transition = "1s";
-                prog.style.width = "100%";
-            }, 0);
-            setTimeout(() => ele.outerHTML = '', 1000);
-        }
-        this._sidebarContent.proto = undefined;
-        if (!MainView.Live) {
-            DocServer.setPlaygroundFields(["dataTransition", "treeViewOpen", "autoHeight", "showSidebar", "sidebarWidthPercent", "viewTransition",
-                "panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "text-scrollHeight", "text-height", "hideMinimap",
-                "viewScale", "scrollTop", "hidden", "curPage", "viewType", "chromeHidden", "nativeWidth"]); // can play with these fields on someone else's
-        }
-        DocServer.GetRefField("rtfProto").then(proto => (proto instanceof Doc) && reaction(() => StrCast(proto.BROADCAST_MESSAGE), msg => msg && alert(msg)));
-
-        const tag = document.createElement('script');
-        tag.src = "https://www.youtube.com/iframe_api";
-        const firstScriptTag = document.getElementsByTagName('script')[0];
-        firstScriptTag.parentNode!.insertBefore(tag, firstScriptTag);
-        window.removeEventListener("keydown", KeyManager.Instance.handle);
-        window.addEventListener("keydown", KeyManager.Instance.handle);
-        window.removeEventListener("keyup", KeyManager.Instance.unhandle);
-        window.addEventListener("keyup", KeyManager.Instance.unhandle);
-        window.addEventListener("paste", KeyManager.Instance.paste as any);
-        document.addEventListener("dash", (e: any) => {  // event used by chrome plugin to tell Dash which document to focus on
-            const id = FormattedTextBox.GetDocFromUrl(e.detail);
-            DocServer.GetRefField(id).then(doc => (doc instanceof Doc) ? DocumentManager.Instance.jumpToDocument(doc, false, undefined) : (null));
-        });
-        document.addEventListener("linkAnnotationToDash", Hypothesis.linkListener);
-        this.initEventListeners();
-    }
-
-    componentWillUnMount() {
-        window.removeEventListener("keyup", KeyManager.Instance.unhandle);
-        window.removeEventListener("keydown", KeyManager.Instance.handle);
-        window.removeEventListener("pointerdown", this.globalPointerDown);
-        window.removeEventListener("paste", KeyManager.Instance.paste as any);
-        document.removeEventListener("linkAnnotationToDash", Hypothesis.linkListener);
-    }
-
-    constructor(props: Readonly<{}>) {
-        super(props);
-        MainView.Instance = this;
-        CurrentUserUtils._urlState = HistoryUtil.parseUrl(window.location) || {} as any;
-
-        // causes errors to be generated when modifying an observable outside of an action
-        configure({ enforceActions: "observed" });
-
-        if (window.location.pathname !== "/home") {
-            const pathname = window.location.pathname.substr(1).split("/");
-            if (pathname.length > 1 && pathname[0] === "doc") {
-                CurrentUserUtils.MainDocId = pathname[1];
-                !this.userDoc && DocServer.GetRefField(pathname[1]).then(action(field => field instanceof Doc && (CurrentUserUtils.GuestTarget = field)));
+      public static Instance: MainView;
+      public static Live: boolean = false;
+      private _docBtnRef = React.createRef<HTMLDivElement>();
+      @observable public LastButton: Opt<Doc>;
+      @observable private _windowWidth: number = 0;
+      @observable private _windowHeight: number = 0;
+      @observable private _dashUIWidth: number = 0;   // width of entire main dashboard region including left menu buttons and properties panel (but not including the dashboard selector button row)
+      @observable private _dashUIHeight: number = 0;  // height of entire main dashboard region including top menu buttons
+      @observable private _panelContent: string = "none";
+      @observable private _sidebarContent: any = this.userDoc?.sidebar;
+      @observable private _leftMenuFlyoutWidth: number = 0;
+
+      @computed private get dashboardTabHeight() { return 27; } //  27 comes form lm.config.defaultConfig.dimensions.headerHeight in goldenlayout.js
+      @computed private get topOfDashUI() { return Number(DASHBOARD_SELECTOR_HEIGHT.replace("px", "")); }
+      @computed private get topOfMainDoc() { return this.topOfDashUI + this.topMenuHeight(); }
+      @computed private get topOfMainDocContent() { return this.topOfMainDoc + this.dashboardTabHeight; }
+      @computed private get leftScreenOffsetOfMainDocView() { return this.leftMenuWidth() - 2; }
+      @computed private get userDoc() { return Doc.UserDoc(); }
+      @computed private get colorScheme() { return StrCast(CurrentUserUtils.ActiveDashboard?.colorScheme); }
+      @computed private get mainContainer() { return this.userDoc ? CurrentUserUtils.ActiveDashboard : CurrentUserUtils.GuestDashboard; }
+      @computed public get mainFreeform(): Opt<Doc> { return (docs => (docs?.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); }
+
+      topMenuHeight = () => 35;
+      topMenuWidth = returnZero; // value is ignored ...
+      leftMenuWidth = () => Number(LEFT_MENU_WIDTH.replace("px", ""));
+      leftMenuHeight = () => this._dashUIHeight;
+      leftMenuFlyoutWidth = () => this._leftMenuFlyoutWidth;
+      leftMenuFlyoutHeight = () => this._dashUIHeight;
+      propertiesWidth = () => Math.max(0, Math.min(this._dashUIWidth - 50, CurrentUserUtils.propertiesWidth || 0));
+      propertiesHeight = () => this._dashUIHeight;
+      mainDocViewWidth = () => this._dashUIWidth - this.propertiesWidth() - this.leftMenuWidth();
+      mainDocViewHeight = () => this._dashUIHeight;
+
+      componentDidMount() {
+            document.getElementById("root")?.addEventListener("scroll", e => ((ele) => ele.scrollLeft = ele.scrollTop = 0)(document.getElementById("root")!));
+            const ele = document.getElementById("loader");
+            const prog = document.getElementById("dash-progress");
+            if (ele && prog) {
+                  // remove from DOM
+                  setTimeout(() => {
+                        clearTimeout();
+                        prog.style.transition = "1s";
+                        prog.style.width = "100%";
+                  }, 0);
+                  setTimeout(() => ele.outerHTML = '', 1000);
             }
-        }
-
-        library.add(...[fa.faEdit, fa.faTrash, fa.faTrashAlt, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faCalendar,
-        fa.faSquare, far.faSquare as any, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faMapMarker, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock,
-        fa.faLock, fa.faLaptopCode, fa.faMale, fa.faCopy, fa.faHandPointLeft, fa.faHandPointRight, fa.faCompass, fa.faSnowflake, fa.faMicrophone, fa.faKeyboard,
-        fa.faQuestion, fa.faTasks, fa.faPalette, fa.faAngleLeft, fa.faAngleRight, fa.faBell, fa.faCamera, fa.faExpand, fa.faCaretDown, fa.faCaretLeft, fa.faCaretRight,
-        fa.faCaretSquareDown, fa.faCaretSquareRight, fa.faArrowsAltH, fa.faPlus, fa.faMinus, fa.faTerminal, fa.faToggleOn, fa.faFile, fa.faLocationArrow,
-        fa.faSearch, fa.faFileDownload, fa.faFileUpload, fa.faStop, fa.faCalculator, fa.faWindowMaximize, fa.faAddressCard, fa.faQuestionCircle, fa.faArrowLeft,
-        fa.faArrowRight, fa.faArrowDown, fa.faArrowUp, fa.faBolt, fa.faBullseye, fa.faCaretUp, fa.faCat, fa.faCheck, fa.faChevronRight, fa.faChevronLeft, fa.faChevronDown, fa.faChevronUp,
-        fa.faClone, fa.faCloudUploadAlt, fa.faCommentAlt, fa.faCompressArrowsAlt, fa.faCut, fa.faEllipsisV, fa.faEraser, fa.faExclamation, fa.faFileAlt,
-        fa.faFileAudio, fa.faFileVideo, fa.faFilePdf, fa.faFilm, fa.faFilter, fa.faFont, fa.faGlobeAmericas, fa.faGlobeAsia, fa.faHighlighter, fa.faLongArrowAltRight, fa.faMousePointer,
-        fa.faMusic, fa.faObjectGroup, fa.faPause, fa.faPen, fa.faPenNib, fa.faPhone, fa.faPlay, fa.faPortrait, fa.faRedoAlt, fa.faStamp, fa.faStickyNote, fa.faArrowsAltV,
-        fa.faTimesCircle, fa.faThumbtack, fa.faTree, fa.faTv, fa.faUndoAlt, fa.faVideo, fa.faAsterisk, fa.faBrain, fa.faImage, fa.faPaintBrush, fa.faTimes,
-        fa.faEye, fa.faArrowsAlt, fa.faQuoteLeft, fa.faSortAmountDown, fa.faAlignLeft, fa.faAlignCenter, fa.faAlignRight, fa.faHeading, fa.faRulerCombined,
-        fa.faFillDrip, fa.faLink, fa.faUnlink, fa.faBold, fa.faItalic, fa.faClipboard, fa.faUnderline, fa.faStrikethrough, fa.faSuperscript, fa.faSubscript,
-        fa.faIndent, fa.faEyeDropper, fa.faPaintRoller, fa.faBars, fa.faBrush, fa.faShapes, fa.faEllipsisH, fa.faHandPaper, fa.faMap, fa.faUser, faHireAHelper as any,
-        fa.faTrashRestore, fa.faUsers, fa.faWrench, fa.faCog, fa.faMap, fa.faBellSlash, fa.faExpandAlt, fa.faArchive, fa.faBezierCurve, fa.faCircle, far.faCircle as any,
-        fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer as any, fa.faExpand, fa.faUndo, fa.faSlidersH, fa.faAngleDoubleLeft, fa.faAngleUp,
-        fa.faAngleDown, fa.faPlayCircle, fa.faClock, fa.faRocket, fa.faExchangeAlt, fa.faHashtag, fa.faAlignJustify, fa.faCheckSquare, fa.faListUl,
-        fa.faWindowMinimize, fa.faWindowRestore, fa.faTextWidth, fa.faTextHeight, fa.faClosedCaptioning, fa.faInfoCircle, fa.faTag, fa.faSyncAlt, fa.faPhotoVideo,
-        fa.faArrowAltCircleDown, fa.faArrowAltCircleUp, fa.faArrowAltCircleLeft, fa.faArrowAltCircleRight, fa.faStopCircle, fa.faCheckCircle, fa.faGripVertical,
-        fa.faSortUp, fa.faSortDown, fa.faTable, fa.faTh, fa.faThList, fa.faProjectDiagram, fa.faSignature, fa.faColumns, fa.faChevronCircleUp, fa.faUpload, fa.faBorderAll,
-        fa.faBraille, fa.faChalkboard, fa.faPencilAlt, fa.faEyeSlash, fa.faSmile, fa.faIndent, fa.faOutdent, fa.faChartBar, fa.faBan, fa.faPhoneSlash, fa.faGripLines,
-        fa.faSave, fa.faBookmark, fa.faList, fa.faListOl, fa.faFolderPlus, fa.faLightbulb, fa.faBookOpen, fa.faMapMarkerAlt, fa.faSearchPlus, fa.faVolumeUp, fa.faVolumeDown]);
-        this.initAuthenticationRouters();
-    }
-
-    globalPointerDown = action((e: PointerEvent) => {
-        AudioBox.Enabled = true;
-        const targets = document.elementsFromPoint(e.x, e.y);
-        if (targets.length) {
-            const targClass = targets[0].className.toString();
-            !targClass.includes("contextMenu") && ContextMenu.Instance.closeMenu();
-            !["timeline-menu-desc", "timeline-menu-item", "timeline-menu-input"].includes(targClass) && TimelineMenu.Instance.closeMenu();
-        }
-    });
-
-    initEventListeners = () => {
-        window.addEventListener("drop", e => e.preventDefault(), false);  // prevent default behavior of navigating to a new web page
-        window.addEventListener("dragover", e => e.preventDefault(), false);
-        // document.addEventListener("pointermove", action(e => SearchBox.Instance._undoBackground = UndoManager.batchCounter ? "#000000a8" : undefined));
-        document.addEventListener("pointerdown", this.globalPointerDown);
-        document.addEventListener("click", (e: MouseEvent) => {
-            if (!e.cancelBubble) {
-                const pathstr = (e as any)?.path?.map((p: any) => p.classList?.toString()).join();
-                if (pathstr?.includes("libraryFlyout")) {
-                    SelectionManager.DeselectAll();
-                }
+            this._sidebarContent.proto = undefined;
+            if (!MainView.Live) {
+                  DocServer.setPlaygroundFields(["dataTransition", "treeViewOpen", "autoHeight", "showSidebar", "sidebarWidthPercent", "viewTransition",
+                        "panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "text-scrollHeight", "text-height", "hideMinimap",
+                        "viewScale", "scrollTop", "hidden", "curPage", "viewType", "chromeHidden", "nativeWidth"]); // can play with these fields on someone else's
             }
-        }, false);
-        document.oncontextmenu = () => false;
-    }
-
-    initAuthenticationRouters = async () => {
-        // Load the user's active dashboard, or create a new one if initial session after signup
-        const received = CurrentUserUtils.MainDocId;
-        if (received && !this.userDoc) {
-            reaction(() => CurrentUserUtils.GuestTarget, target => target && CurrentUserUtils.createNewDashboard(Doc.UserDoc()), { fireImmediately: true });
-        } else {
-            if (received && CurrentUserUtils._urlState.sharing) {
-                reaction(() => CollectionDockingView.Instance && CollectionDockingView.Instance.initialized,
-                    initialized => initialized && received && DocServer.GetRefField(received).then(docField => {
-                        if (docField instanceof Doc && docField._viewType !== CollectionViewType.Docking) {
-                            CollectionDockingView.AddSplit(docField, "right");
+            DocServer.GetRefField("rtfProto").then(proto => (proto instanceof Doc) && reaction(() => StrCast(proto.BROADCAST_MESSAGE), msg => msg && alert(msg)));
+
+            const tag = document.createElement('script');
+            tag.src = "https://www.youtube.com/iframe_api";
+            const firstScriptTag = document.getElementsByTagName('script')[0];
+            firstScriptTag.parentNode!.insertBefore(tag, firstScriptTag);
+            window.removeEventListener("keydown", KeyManager.Instance.handle);
+            window.addEventListener("keydown", KeyManager.Instance.handle);
+            window.removeEventListener("keyup", KeyManager.Instance.unhandle);
+            window.addEventListener("keyup", KeyManager.Instance.unhandle);
+            window.addEventListener("paste", KeyManager.Instance.paste as any);
+            document.addEventListener("dash", (e: any) => {  // event used by chrome plugin to tell Dash which document to focus on
+                  const id = FormattedTextBox.GetDocFromUrl(e.detail);
+                  DocServer.GetRefField(id).then(doc => (doc instanceof Doc) ? DocumentManager.Instance.jumpToDocument(doc, false, undefined) : (null));
+            });
+            document.addEventListener("linkAnnotationToDash", Hypothesis.linkListener);
+            this.initEventListeners();
+      }
+
+      componentWillUnMount() {
+            window.removeEventListener("keyup", KeyManager.Instance.unhandle);
+            window.removeEventListener("keydown", KeyManager.Instance.handle);
+            window.removeEventListener("pointerdown", this.globalPointerDown);
+            window.removeEventListener("paste", KeyManager.Instance.paste as any);
+            document.removeEventListener("linkAnnotationToDash", Hypothesis.linkListener);
+      }
+
+      constructor(props: Readonly<{}>) {
+            super(props);
+            MainView.Instance = this;
+            CurrentUserUtils._urlState = HistoryUtil.parseUrl(window.location) || {} as any;
+
+            // causes errors to be generated when modifying an observable outside of an action
+            configure({ enforceActions: "observed" });
+
+            if (window.location.pathname !== "/home") {
+                  const pathname = window.location.pathname.substr(1).split("/");
+                  if (pathname.length > 1 && pathname[0] === "doc") {
+                        CurrentUserUtils.MainDocId = pathname[1];
+                        !this.userDoc && DocServer.GetRefField(pathname[1]).then(action(field => field instanceof Doc && (CurrentUserUtils.GuestTarget = field)));
+                  }
+            }
+
+            library.add(...[fa.faEdit, fa.faTrash, fa.faTrashAlt, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faCalendar, fa.faVideoSlash, fa.faVideo,
+            fa.faSquare, far.faSquare as any, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faMapMarker, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock,
+            fa.faLock, fa.faLaptopCode, fa.faMale, fa.faCopy, fa.faHandPointLeft, fa.faHandPointRight, fa.faCompass, fa.faSnowflake, fa.faMicrophone, fa.faKeyboard,
+            fa.faQuestion, fa.faTasks, fa.faPalette, fa.faAngleLeft, fa.faAngleRight, fa.faBell, fa.faCamera, fa.faExpand, fa.faCaretDown, fa.faCaretLeft, fa.faCaretRight,
+            fa.faCaretSquareDown, fa.faCaretSquareRight, fa.faArrowsAltH, fa.faPlus, fa.faMinus, fa.faTerminal, fa.faToggleOn, fa.faFile, fa.faLocationArrow,
+            fa.faSearch, fa.faFileDownload, fa.faFileUpload, fa.faStop, fa.faCalculator, fa.faWindowMaximize, fa.faAddressCard, fa.faQuestionCircle, fa.faArrowLeft,
+            fa.faArrowRight, fa.faArrowDown, fa.faArrowUp, fa.faBolt, fa.faBullseye, fa.faCaretUp, fa.faCat, fa.faCheck, fa.faChevronRight, fa.faChevronLeft, fa.faChevronDown, fa.faChevronUp,
+            fa.faClone, fa.faCloudUploadAlt, fa.faCommentAlt, fa.faCompressArrowsAlt, fa.faCut, fa.faEllipsisV, fa.faEraser, fa.faExclamation, fa.faFileAlt,
+            fa.faFileAudio, fa.faFileVideo, fa.faFilePdf, fa.faFilm, fa.faFilter, fa.faFont, fa.faGlobeAmericas, fa.faGlobeAsia, fa.faHighlighter, fa.faLongArrowAltRight, fa.faMousePointer,
+            fa.faMusic, fa.faObjectGroup, fa.faPause, fa.faPen, fa.faPenNib, fa.faPhone, fa.faPlay, fa.faPortrait, fa.faRedoAlt, fa.faStamp, fa.faStickyNote, fa.faArrowsAltV,
+            fa.faTimesCircle, fa.faThumbtack, fa.faTree, fa.faTv, fa.faUndoAlt, fa.faVideo, fa.faAsterisk, fa.faBrain, fa.faImage, fa.faPaintBrush, fa.faTimes,
+            fa.faEye, fa.faArrowsAlt, fa.faQuoteLeft, fa.faSortAmountDown, fa.faAlignLeft, fa.faAlignCenter, fa.faAlignRight, fa.faHeading, fa.faRulerCombined,
+            fa.faFillDrip, fa.faLink, fa.faUnlink, fa.faBold, fa.faItalic, fa.faClipboard, fa.faUnderline, fa.faStrikethrough, fa.faSuperscript, fa.faSubscript,
+            fa.faIndent, fa.faEyeDropper, fa.faPaintRoller, fa.faBars, fa.faBrush, fa.faShapes, fa.faEllipsisH, fa.faHandPaper, fa.faMap, fa.faUser, faHireAHelper as any,
+            fa.faTrashRestore, fa.faUsers, fa.faWrench, fa.faCog, fa.faMap, fa.faBellSlash, fa.faExpandAlt, fa.faArchive, fa.faBezierCurve, fa.faCircle, far.faCircle as any,
+            fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer as any, fa.faExpand, fa.faUndo, fa.faSlidersH, fa.faAngleDoubleLeft, fa.faAngleUp,
+            fa.faAngleDown, fa.faPlayCircle, fa.faClock, fa.faRocket, fa.faExchangeAlt, fa.faHashtag, fa.faAlignJustify, fa.faCheckSquare, fa.faListUl,
+            fa.faWindowMinimize, fa.faWindowRestore, fa.faTextWidth, fa.faTextHeight, fa.faClosedCaptioning, fa.faInfoCircle, fa.faTag, fa.faSyncAlt, fa.faPhotoVideo,
+            fa.faArrowAltCircleDown, fa.faArrowAltCircleUp, fa.faArrowAltCircleLeft, fa.faArrowAltCircleRight, fa.faStopCircle, fa.faCheckCircle, fa.faGripVertical,
+            fa.faSortUp, fa.faSortDown, fa.faTable, fa.faTh, fa.faThList, fa.faProjectDiagram, fa.faSignature, fa.faColumns, fa.faChevronCircleUp, fa.faUpload, fa.faBorderAll,
+            fa.faBraille, fa.faChalkboard, fa.faPencilAlt, fa.faEyeSlash, fa.faSmile, fa.faIndent, fa.faOutdent, fa.faChartBar, fa.faBan, fa.faPhoneSlash, fa.faGripLines,
+            fa.faSave, fa.faBookmark, fa.faList, fa.faListOl, fa.faFolderPlus, fa.faLightbulb, fa.faBookOpen, fa.faMapMarkerAlt, fa.faSearchPlus, fa.faVolumeUp, fa.faVolumeDown]);
+            this.initAuthenticationRouters();
+      }
+
+      globalPointerDown = action((e: PointerEvent) => {
+            AudioBox.Enabled = true;
+            const targets = document.elementsFromPoint(e.x, e.y);
+            if (targets.length) {
+                  const targClass = targets[0].className.toString();
+                  !targClass.includes("contextMenu") && ContextMenu.Instance.closeMenu();
+                  !["timeline-menu-desc", "timeline-menu-item", "timeline-menu-input"].includes(targClass) && TimelineMenu.Instance.closeMenu();
+            }
+      });
+
+      initEventListeners = () => {
+            window.addEventListener("drop", e => e.preventDefault(), false);  // prevent default behavior of navigating to a new web page
+            window.addEventListener("dragover", e => e.preventDefault(), false);
+            // document.addEventListener("pointermove", action(e => SearchBox.Instance._undoBackground = UndoManager.batchCounter ? "#000000a8" : undefined));
+            document.addEventListener("pointerdown", this.globalPointerDown);
+            document.addEventListener("click", (e: MouseEvent) => {
+                  if (!e.cancelBubble) {
+                        const pathstr = (e as any)?.path?.map((p: any) => p.classList?.toString()).join();
+                        if (pathstr?.includes("libraryFlyout")) {
+                              SelectionManager.DeselectAll();
                         }
-                    }),
-                );
+                  }
+            }, false);
+            document.oncontextmenu = () => false;
+      }
+
+      initAuthenticationRouters = async () => {
+            // Load the user's active dashboard, or create a new one if initial session after signup
+            const received = CurrentUserUtils.MainDocId;
+            if (received && !this.userDoc) {
+                  reaction(() => CurrentUserUtils.GuestTarget, target => target && CurrentUserUtils.createNewDashboard(Doc.UserDoc()), { fireImmediately: true });
+            } else {
+                  if (received && CurrentUserUtils._urlState.sharing) {
+                        reaction(() => CollectionDockingView.Instance && CollectionDockingView.Instance.initialized,
+                              initialized => initialized && received && DocServer.GetRefField(received).then(docField => {
+                                    if (docField instanceof Doc && docField._viewType !== CollectionViewType.Docking) {
+                                          CollectionDockingView.AddSplit(docField, "right");
+                                    }
+                              }),
+                        );
+                  }
+                  const activeDash = PromiseValue(this.userDoc.activeDashboard);
+                  activeDash.then(dash => {
+                        if (dash instanceof Doc) CurrentUserUtils.openDashboard(this.userDoc, dash);
+                        else CurrentUserUtils.createNewDashboard(this.userDoc);
+                  });
             }
-            const activeDash = PromiseValue(this.userDoc.activeDashboard);
-            activeDash.then(dash => {
-                if (dash instanceof Doc) CurrentUserUtils.openDashboard(this.userDoc, dash);
-                else CurrentUserUtils.createNewDashboard(this.userDoc);
-            });
-        }
-    }
-
-    @action
-    createNewPresentation = async () => {
-        if (!await this.userDoc.myTrails) {
-            this.userDoc.myTrails = new PrefetchProxy(Docs.Create.TreeDocument([], {
-                title: "TRAILS", childDontRegisterViews: true, _height: 100, _forceActive: true, boxShadow: "0 0", _lockedPosition: true, treeViewOpen: true, system: true
-            }));
-        }
-        const pres = Docs.Create.PresDocument(new List<Doc>(),
-            { title: "Untitled Trail", _viewType: CollectionViewType.Stacking, _fitWidth: true, _width: 400, _height: 500, targetDropAction: "alias", _chromeHidden: true, boxShadow: "0 0" });
-        CollectionDockingView.AddSplit(pres, "right");
-        this.userDoc.activePresentation = pres;
-        Doc.AddDocToList(this.userDoc.myTrails as Doc, "data", pres);
-    }
-
-    @action
-    createNewFolder = async () => {
-        if (!await this.userDoc.myFilesystem) {
-            this.userDoc.myFileOrphans = Docs.Create.TreeDocument([], { title: "Unfiled", _stayInCollection: true, system: true, isFolder: true });
-            const newFolder = ScriptField.MakeFunction(`createNewFolder()`, { scriptContext: "any" })!;
-            const newFolderButton: Doc = Docs.Create.FontIconDocument({
-                onClick: newFolder, _forceActive: true, toolTip: "New folder", _stayInCollection: true, _hideContextMenu: true, title: "New folder",
-                btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New folder", icon: "folder-plus", system: true
-            });
-            this.userDoc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([this.userDoc.myFileOrphans as Doc], {
-                title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100,
-                treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
-                treeViewTruncateTitleWidth: 150, ignoreClick: true,
-                isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true,
-                _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true,
-                explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard."
-            }));
-        }
-        const folder = Docs.Create.TreeDocument([], { title: "Untitled folder", _stayInCollection: true, isFolder: true });
-        Doc.AddDocToList(this.userDoc.myFilesystem as Doc, "data", folder);
-    }
-
-    @computed get mainDocView() {
-        return <DocumentView key="main"
-            Document={this.mainContainer!}
-            DataDoc={undefined}
-            addDocument={undefined}
-            addDocTab={this.addDocTabFunc}
-            pinToPres={emptyFunction}
-            docViewPath={returnEmptyDoclist}
-            layerProvider={undefined}
-            styleProvider={undefined}
-            rootSelected={returnTrue}
-            isContentActive={returnTrue}
-            removeDocument={undefined}
-            ScreenToLocalTransform={Transform.Identity}
-            PanelWidth={this.mainDocViewWidth}
-            PanelHeight={this.mainDocViewHeight}
-            focus={DocUtils.DefaultFocus}
-            whenChildContentsActiveChanged={emptyFunction}
-            bringToFront={emptyFunction}
-            docFilters={returnEmptyFilter}
-            docRangeFilters={returnEmptyFilter}
-            searchFilterDocs={returnEmptyDoclist}
-            ContainingCollectionView={undefined}
-            ContainingCollectionDoc={undefined}
-            suppressSetHeight={true}
-            renderDepth={-1}
-        />;
-    }
-
-    @computed get dockingContent() {
-        return <div key="docking" className={`mainView-dockingContent${this._leftMenuFlyoutWidth ? "-flyout" : ""}`} onDrop={e => { e.stopPropagation(); e.preventDefault(); }}
-            style={{
-                minWidth: `calc(100% - ${this._leftMenuFlyoutWidth + this.leftMenuWidth() + this.propertiesWidth()}px)`,
-                transform: LightboxView.LightboxDoc ? "scale(0.0001)" : undefined,
-            }}>
-            {!this.mainContainer ? (null) : this.mainDocView}
-        </div>;
-    }
-
-    @action
-    onPropertiesPointerDown = (e: React.PointerEvent) => {
-        setupMoveUpEvents(this, e,
-            action(e => (CurrentUserUtils.propertiesWidth = Math.max(0, this._dashUIWidth - e.clientX)) ? false : false),
-            action(() => CurrentUserUtils.propertiesWidth < 5 && (CurrentUserUtils.propertiesWidth = 0)),
-            action(() => CurrentUserUtils.propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._dashUIWidth - 50, 250) : 0), false);
-    }
-
-    @action
-    onFlyoutPointerDown = (e: React.PointerEvent) => {
-        setupMoveUpEvents(this, e,
-            action(e => (this._leftMenuFlyoutWidth = Math.max(e.clientX - 58, 0)) ? false : false),
-            () => this._leftMenuFlyoutWidth < 5 && this.closeFlyout(),
-            this.closeFlyout);
-    }
-
-    sidebarScreenToLocal = () => new Transform(0, -this.topOfMainDoc, 1);
-    mainContainerXf = () => this.sidebarScreenToLocal().translate(-this.leftScreenOffsetOfMainDocView, 0);
-    addDocTabFunc = (doc: Doc, location: string): boolean => {
-        const locationFields = doc._viewType === CollectionViewType.Docking ? ["dashboard"] : location.split(":");
-        const locationParams = locationFields.length > 1 ? locationFields[1] : "";
-        if (doc.dockingConfig) return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc);
-        switch (locationFields[0]) {
-            case "dashboard": return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc);
-            case "close": return CollectionDockingView.CloseSplit(doc, locationParams);
-            case "fullScreen": return CollectionDockingView.OpenFullScreen(doc);
-            case "lightbox": return LightboxView.AddDocTab(doc, location);
-            case "toggle": return CollectionDockingView.ToggleSplit(doc, locationParams);
-            case "inPlace":
-            case "add":
-            default:
-                return CollectionDockingView.AddSplit(doc, locationParams);
-        }
-    }
-
-
-    @computed get flyout() {
-        return !this._leftMenuFlyoutWidth ? <div key="flyout" className={`mainView-libraryFlyout-out`}>
-            {this.docButtons}
-        </div> :
-            <div key="libFlyout" className="mainView-libraryFlyout" style={{ minWidth: this._leftMenuFlyoutWidth, width: this._leftMenuFlyoutWidth }} >
-                <div className="mainView-contentArea" >
-                    <DocumentView
-                        Document={this._sidebarContent.proto || this._sidebarContent}
+      }
+
+      @action
+      createNewPresentation = async () => {
+            if (!await this.userDoc.myTrails) {
+                  this.userDoc.myTrails = new PrefetchProxy(Docs.Create.TreeDocument([], {
+                        title: "TRAILS", childDontRegisterViews: true, _height: 100, _forceActive: true, boxShadow: "0 0", _lockedPosition: true, treeViewOpen: true, system: true
+                  }));
+            }
+            const pres = Docs.Create.PresDocument(new List<Doc>(),
+                  { title: "Untitled Trail", _viewType: CollectionViewType.Stacking, _fitWidth: true, _width: 400, _height: 500, targetDropAction: "alias", _chromeHidden: true, boxShadow: "0 0" });
+            CollectionDockingView.AddSplit(pres, "right");
+            this.userDoc.activePresentation = pres;
+            Doc.AddDocToList(this.userDoc.myTrails as Doc, "data", pres);
+      }
+
+      @action
+      createNewFolder = async () => {
+            if (!await this.userDoc.myFilesystem) {
+                  this.userDoc.myFileOrphans = Docs.Create.TreeDocument([], { title: "Unfiled", _stayInCollection: true, system: true, isFolder: true });
+                  const newFolder = ScriptField.MakeFunction(`createNewFolder()`, { scriptContext: "any" })!;
+                  const newFolderButton: Doc = Docs.Create.FontIconDocument({
+                        onClick: newFolder, _forceActive: true, toolTip: "New folder", _stayInCollection: true, _hideContextMenu: true, title: "New folder",
+                        btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New folder", icon: "folder-plus", system: true
+                  });
+                  this.userDoc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([this.userDoc.myFileOrphans as Doc], {
+                        title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100,
+                        treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
+                        treeViewTruncateTitleWidth: 150, ignoreClick: true,
+                        isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true,
+                        _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true,
+                        explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard."
+                  }));
+            }
+            const folder = Docs.Create.TreeDocument([], { title: "Untitled folder", _stayInCollection: true, isFolder: true });
+            Doc.AddDocToList(this.userDoc.myFilesystem as Doc, "data", folder);
+      }
+
+      @computed get mainDocView() {
+            return <DocumentView key="main"
+                  Document={this.mainContainer!}
+                  DataDoc={undefined}
+                  addDocument={undefined}
+                  addDocTab={this.addDocTabFunc}
+                  pinToPres={emptyFunction}
+                  docViewPath={returnEmptyDoclist}
+                  layerProvider={undefined}
+                  styleProvider={undefined}
+                  rootSelected={returnTrue}
+                  isContentActive={returnTrue}
+                  removeDocument={undefined}
+                  ScreenToLocalTransform={Transform.Identity}
+                  PanelWidth={this.mainDocViewWidth}
+                  PanelHeight={this.mainDocViewHeight}
+                  focus={DocUtils.DefaultFocus}
+                  whenChildContentsActiveChanged={emptyFunction}
+                  bringToFront={emptyFunction}
+                  docFilters={returnEmptyFilter}
+                  docRangeFilters={returnEmptyFilter}
+                  searchFilterDocs={returnEmptyDoclist}
+                  ContainingCollectionView={undefined}
+                  ContainingCollectionDoc={undefined}
+                  suppressSetHeight={true}
+                  renderDepth={-1}
+            />;
+      }
+
+      @computed get dockingContent() {
+            return <div key="docking" className={`mainView-dockingContent${this._leftMenuFlyoutWidth ? "-flyout" : ""}`} onDrop={e => { e.stopPropagation(); e.preventDefault(); }}
+                  style={{
+                        minWidth: `calc(100% - ${this._leftMenuFlyoutWidth + this.leftMenuWidth() + this.propertiesWidth()}px)`,
+                        transform: LightboxView.LightboxDoc ? "scale(0.0001)" : undefined,
+                  }}>
+                  {!this.mainContainer ? (null) : this.mainDocView}
+            </div>;
+      }
+
+      @action
+      onPropertiesPointerDown = (e: React.PointerEvent) => {
+            setupMoveUpEvents(this, e,
+                  action(e => (CurrentUserUtils.propertiesWidth = Math.max(0, this._dashUIWidth - e.clientX)) ? false : false),
+                  action(() => CurrentUserUtils.propertiesWidth < 5 && (CurrentUserUtils.propertiesWidth = 0)),
+                  action(() => CurrentUserUtils.propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._dashUIWidth - 50, 250) : 0), false);
+      }
+
+      @action
+      onFlyoutPointerDown = (e: React.PointerEvent) => {
+            setupMoveUpEvents(this, e,
+                  action(e => (this._leftMenuFlyoutWidth = Math.max(e.clientX - 58, 0)) ? false : false),
+                  () => this._leftMenuFlyoutWidth < 5 && this.closeFlyout(),
+                  this.closeFlyout);
+      }
+
+      sidebarScreenToLocal = () => new Transform(0, -this.topOfMainDoc, 1);
+      mainContainerXf = () => this.sidebarScreenToLocal().translate(-this.leftScreenOffsetOfMainDocView, 0);
+      addDocTabFunc = (doc: Doc, location: string): boolean => {
+            const locationFields = doc._viewType === CollectionViewType.Docking ? ["dashboard"] : location.split(":");
+            const locationParams = locationFields.length > 1 ? locationFields[1] : "";
+            if (doc.dockingConfig) return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc);
+            switch (locationFields[0]) {
+                  case "dashboard": return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc);
+                  case "close": return CollectionDockingView.CloseSplit(doc, locationParams);
+                  case "fullScreen": return CollectionDockingView.OpenFullScreen(doc);
+                  case "lightbox": return LightboxView.AddDocTab(doc, location);
+                  case "toggle": return CollectionDockingView.ToggleSplit(doc, locationParams);
+                  case "inPlace":
+                  case "add":
+                  default:
+                        return CollectionDockingView.AddSplit(doc, locationParams);
+            }
+      }
+
+
+      @computed get flyout() {
+            return !this._leftMenuFlyoutWidth ? <div key="flyout" className={`mainView-libraryFlyout-out`}>
+                  {this.docButtons}
+            </div> :
+                  <div key="libFlyout" className="mainView-libraryFlyout" style={{ minWidth: this._leftMenuFlyoutWidth, width: this._leftMenuFlyoutWidth }} >
+                        <div className="mainView-contentArea" >
+                              <DocumentView
+                                    Document={this._sidebarContent.proto || this._sidebarContent}
+                                    DataDoc={undefined}
+                                    addDocument={undefined}
+                                    addDocTab={this.addDocTabFunc}
+                                    pinToPres={emptyFunction}
+                                    docViewPath={returnEmptyDoclist}
+                                    layerProvider={undefined}
+                                    styleProvider={this._sidebarContent.proto === Doc.UserDoc().myDashboards || this._sidebarContent.proto === Doc.UserDoc().myFilesystem ? DashboardStyleProvider : DefaultStyleProvider}
+                                    rootSelected={returnTrue}
+                                    removeDocument={returnFalse}
+                                    ScreenToLocalTransform={this.mainContainerXf}
+                                    PanelWidth={this.leftMenuFlyoutWidth}
+                                    PanelHeight={this.leftMenuFlyoutHeight}
+                                    renderDepth={0}
+                                    isContentActive={returnTrue}
+                                    scriptContext={CollectionDockingView.Instance?.props.Document}
+                                    focus={DocUtils.DefaultFocus}
+                                    whenChildContentsActiveChanged={emptyFunction}
+                                    bringToFront={emptyFunction}
+                                    docFilters={returnEmptyFilter}
+                                    docRangeFilters={returnEmptyFilter}
+                                    searchFilterDocs={returnEmptyDoclist}
+                                    ContainingCollectionView={undefined}
+                                    ContainingCollectionDoc={undefined}
+                              />
+                        </div>
+                        {this.docButtons}
+                  </div>;
+      }
+
+      @computed get leftMenuPanel() {
+            return <div key="menu" className="mainView-leftMenuPanel">
+                  <DocumentView
+                        Document={Doc.UserDoc().menuStack as Doc}
                         DataDoc={undefined}
                         addDocument={undefined}
                         addDocTab={this.addDocTabFunc}
                         pinToPres={emptyFunction}
-                        docViewPath={returnEmptyDoclist}
-                        layerProvider={undefined}
-                        styleProvider={this._sidebarContent.proto === Doc.UserDoc().myDashboards || this._sidebarContent.proto === Doc.UserDoc().myFilesystem ? DashboardStyleProvider : DefaultStyleProvider}
                         rootSelected={returnTrue}
                         removeDocument={returnFalse}
-                        ScreenToLocalTransform={this.mainContainerXf}
-                        PanelWidth={this.leftMenuFlyoutWidth}
-                        PanelHeight={this.leftMenuFlyoutHeight}
+                        ScreenToLocalTransform={this.sidebarScreenToLocal}
+                        PanelWidth={this.leftMenuWidth}
+                        PanelHeight={this.leftMenuHeight}
                         renderDepth={0}
-                        isContentActive={returnTrue}
-                        scriptContext={CollectionDockingView.Instance?.props.Document}
+                        docViewPath={returnEmptyDoclist}
                         focus={DocUtils.DefaultFocus}
+                        styleProvider={DefaultStyleProvider}
+                        layerProvider={undefined}
+                        isContentActive={returnTrue}
                         whenChildContentsActiveChanged={emptyFunction}
                         bringToFront={emptyFunction}
                         docFilters={returnEmptyFilter}
@@ -379,333 +411,301 @@ export class MainView extends React.Component {
                         searchFilterDocs={returnEmptyDoclist}
                         ContainingCollectionView={undefined}
                         ContainingCollectionDoc={undefined}
-                    />
-                </div>
-                {this.docButtons}
+                        scriptContext={this}
+                  />
             </div>;
-    }
-
-    @computed get leftMenuPanel() {
-        return <div key="menu" className="mainView-leftMenuPanel">
-            <DocumentView
-                Document={Doc.UserDoc().menuStack as Doc}
-                DataDoc={undefined}
-                addDocument={undefined}
-                addDocTab={this.addDocTabFunc}
-                pinToPres={emptyFunction}
-                rootSelected={returnTrue}
-                removeDocument={returnFalse}
-                ScreenToLocalTransform={this.sidebarScreenToLocal}
-                PanelWidth={this.leftMenuWidth}
-                PanelHeight={this.leftMenuHeight}
-                renderDepth={0}
-                docViewPath={returnEmptyDoclist}
-                focus={DocUtils.DefaultFocus}
-                styleProvider={DefaultStyleProvider}
-                layerProvider={undefined}
-                isContentActive={returnTrue}
-                whenChildContentsActiveChanged={emptyFunction}
-                bringToFront={emptyFunction}
-                docFilters={returnEmptyFilter}
-                docRangeFilters={returnEmptyFilter}
-                searchFilterDocs={returnEmptyDoclist}
-                ContainingCollectionView={undefined}
-                ContainingCollectionDoc={undefined}
-                scriptContext={this}
-            />
-        </div>;
-    }
-
-    @action
-    selectMenu = (button: Doc) => {
-        const title = StrCast(Doc.GetProto(button).title);
-        const willOpen = !this._leftMenuFlyoutWidth || this._panelContent !== title;
-        this.closeFlyout();
-        if (willOpen) {
-            switch (this._panelContent = title) {
-                case "Settings":
-                    SettingsManager.Instance.open();
-                    break;
-                case "Help":
-                    break;
-                default:
-                    this.expandFlyout(button);
+      }
+
+      @action
+      selectMenu = (button: Doc) => {
+            const title = StrCast(Doc.GetProto(button).title);
+            const willOpen = !this._leftMenuFlyoutWidth || this._panelContent !== title;
+            this.closeFlyout();
+            if (willOpen) {
+                  switch (this._panelContent = title) {
+                        case "Settings":
+                              SettingsManager.Instance.open();
+                              break;
+                        case "Help":
+                              break;
+                        default:
+                              this.expandFlyout(button);
+                  }
             }
-        }
-        return true;
-    }
-
-    @computed get mainInnerContent() {
-        const leftMenuFlyoutWidth = this._leftMenuFlyoutWidth + this.leftMenuWidth();
-        const width = this.propertiesWidth() + leftMenuFlyoutWidth;
-        return <>
-            {this.leftMenuPanel}
-            <div key="inner" className={`mainView-innerContent${this.colorScheme}`}>
-                {this.flyout}
-                <div className="mainView-libraryHandle" style={{ left: leftMenuFlyoutWidth - 10 /* ~half width of handle */, display: !this._leftMenuFlyoutWidth ? "none" : undefined }} onPointerDown={this.onFlyoutPointerDown} >
-                    <FontAwesomeIcon icon="chevron-left" color={this.colorScheme === ColorScheme.Dark ? "white" : "black"} style={{ opacity: "50%" }} size="sm" />
-                </div>
-                <div className="mainView-innerContainer" style={{ width: `calc(100% - ${width}px)` }}>
-
-                    {this.dockingContent}
-
-                    <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ right: this.propertiesWidth() - 1 }}>
-                        <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? "chevron-left" : "chevron-right"} color={this.colorScheme === ColorScheme.Dark ? Colors.WHITE : Colors.BLACK} size="sm" />
-                    </div>
-                    <div className="properties-container" style={{ width: this.propertiesWidth() }}>
-                        {this.propertiesWidth() < 10 ? (null) : <PropertiesView styleProvider={DefaultStyleProvider} addDocTab={this.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />}
-                    </div>
-                </div>
-            </div>
-        </>;
-    }
-
-    @computed get mainDashboardArea() {
-        return !this.userDoc ? (null) :
-            <div className="mainView-dashboardArea" ref={r => {
-                r && new _global.ResizeObserver(action(() => {
-                    this._dashUIWidth = r.getBoundingClientRect().width;
-                    this._dashUIHeight = r.getBoundingClientRect().height;
-                })).observe(r);
-            }} style={{
-                color: this.colorScheme === ColorScheme.Dark ? "rgb(205,205,205)" : "black",
-                height: `calc(100% - ${this.topOfDashUI + this.topMenuHeight()}px)`,
-                width: "100%",
-            }} >
-                {this.mainInnerContent}
-            </div>;
-    }
-
-
-    expandFlyout = action((button: Doc) => {
-        // bcz: What's going on here!?  
-        // Chrome(not firefox) seems to have a bug when the flyout expands and there's a zoomed freeform tab.  All of the div below the CollectionFreeFormView's main div
-        // generate the wrong value from getClientRectangle() -- specifically they return an 'x' that is the flyout's width greater than it should be.
-        // interactively adjusting the flyout fixes the problem.  So does programmatically changing the value after a timeout to something *fractionally* different (ie, 1.5, not 1);)
-        this._leftMenuFlyoutWidth = (this._leftMenuFlyoutWidth || 250);
-        setTimeout(action(() => this._leftMenuFlyoutWidth += 0.5), 0);
-
-        this._sidebarContent.proto = button.target as any;
-        this.LastButton = button;
-    });
-
-    closeFlyout = action(() => {
-        this.LastButton = undefined;
-        this._panelContent = "none";
-        this._sidebarContent.proto = undefined;
-        this._leftMenuFlyoutWidth = 0;
-    });
-
-    remButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.RemoveDocFromList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true);
-    moveButtonDoc = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => this.remButtonDoc(doc) && addDocument(doc);
-    addButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true);
-
-    buttonBarXf = () => {
-        if (!this._docBtnRef.current) return Transform.Identity();
-        const { scale, translateX, translateY } = Utils.GetScreenTransform(this._docBtnRef.current);
-        return new Transform(-translateX, -translateY, 1 / scale);
-    }
-
-    @computed get docButtons() {
-        return !(this.userDoc.dockedBtns instanceof Doc) ? (null) :
-            <div className="mainView-docButtons" ref={this._docBtnRef} style={{ height: !this.userDoc.dockedBtns.linearViewIsExpanded ? "42px" : undefined }} >
-                <CollectionLinearView
-                    Document={this.userDoc.dockedBtns}
-                    DataDoc={undefined}
-                    fieldKey={"data"}
-                    dropAction={"alias"}
-                    setHeight={returnFalse}
-                    styleProvider={DefaultStyleProvider}
-                    layerProvider={undefined}
-                    rootSelected={returnTrue}
-                    bringToFront={emptyFunction}
-                    select={emptyFunction}
-                    isAnyChildContentActive={returnFalse}
-                    isContentActive={emptyFunction}
-                    isSelected={returnFalse}
-                    docViewPath={returnEmptyDoclist}
-                    moveDocument={this.moveButtonDoc}
-                    CollectionView={undefined}
-                    addDocument={this.addButtonDoc}
-                    addDocTab={this.addDocTabFunc}
-                    pinToPres={emptyFunction}
-                    removeDocument={this.remButtonDoc}
-                    ScreenToLocalTransform={this.buttonBarXf}
-                    PanelWidth={this.leftMenuFlyoutWidth}
-                    PanelHeight={this.leftMenuFlyoutHeight}
-                    renderDepth={0}
-                    focus={DocUtils.DefaultFocus}
-                    whenChildContentsActiveChanged={emptyFunction}
-                    docFilters={returnEmptyFilter}
-                    docRangeFilters={returnEmptyFilter}
-                    searchFilterDocs={returnEmptyDoclist}
-                    ContainingCollectionView={undefined}
-                    ContainingCollectionDoc={undefined} />
-                {['watching', 'recording'].includes(String(this.userDoc?.presentationMode) ?? '') ? <div style={{ border: '.5rem solid green', padding: '5px' }}>{this.userDoc?.presentationMode}</div>: <></>}
+            return true;
+      }
+
+      @computed get mainInnerContent() {
+            const leftMenuFlyoutWidth = this._leftMenuFlyoutWidth + this.leftMenuWidth();
+            const width = this.propertiesWidth() + leftMenuFlyoutWidth;
+            return <>
+                  {this.leftMenuPanel}
+                  <div key="inner" className={`mainView-innerContent${this.colorScheme}`}>
+                        {this.flyout}
+                        <div className="mainView-libraryHandle" style={{ left: leftMenuFlyoutWidth - 10 /* ~half width of handle */, display: !this._leftMenuFlyoutWidth ? "none" : undefined }} onPointerDown={this.onFlyoutPointerDown} >
+                              <FontAwesomeIcon icon="chevron-left" color={this.colorScheme === ColorScheme.Dark ? "white" : "black"} style={{ opacity: "50%" }} size="sm" />
+                        </div>
+                        <div className="mainView-innerContainer" style={{ width: `calc(100% - ${width}px)` }}>
+
+                              {this.dockingContent}
+
+                              <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ right: this.propertiesWidth() - 1 }}>
+                                    <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? "chevron-left" : "chevron-right"} color={this.colorScheme === ColorScheme.Dark ? Colors.WHITE : Colors.BLACK} size="sm" />
+                              </div>
+                              <div className="properties-container" style={{ width: this.propertiesWidth() }}>
+                                    {this.propertiesWidth() < 10 ? (null) : <PropertiesView styleProvider={DefaultStyleProvider} addDocTab={this.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />}
+                              </div>
+                        </div>
+                  </div>
+            </>;
+      }
+
+      @computed get mainDashboardArea() {
+            return !this.userDoc ? (null) :
+                  <div className="mainView-dashboardArea" ref={r => {
+                        r && new _global.ResizeObserver(action(() => {
+                              this._dashUIWidth = r.getBoundingClientRect().width;
+                              this._dashUIHeight = r.getBoundingClientRect().height;
+                        })).observe(r);
+                  }} style={{
+                        color: this.colorScheme === ColorScheme.Dark ? "rgb(205,205,205)" : "black",
+                        height: `calc(100% - ${this.topOfDashUI + this.topMenuHeight()}px)`,
+                        width: "100%",
+                  }} >
+                        {this.mainInnerContent}
+                  </div>;
+      }
+
+
+      expandFlyout = action((button: Doc) => {
+            // bcz: What's going on here!?  
+            // Chrome(not firefox) seems to have a bug when the flyout expands and there's a zoomed freeform tab.  All of the div below the CollectionFreeFormView's main div
+            // generate the wrong value from getClientRectangle() -- specifically they return an 'x' that is the flyout's width greater than it should be.
+            // interactively adjusting the flyout fixes the problem.  So does programmatically changing the value after a timeout to something *fractionally* different (ie, 1.5, not 1);)
+            this._leftMenuFlyoutWidth = (this._leftMenuFlyoutWidth || 250);
+            setTimeout(action(() => this._leftMenuFlyoutWidth += 0.5), 0);
+
+            this._sidebarContent.proto = button.target as any;
+            this.LastButton = button;
+      });
+
+      closeFlyout = action(() => {
+            this.LastButton = undefined;
+            this._panelContent = "none";
+            this._sidebarContent.proto = undefined;
+            this._leftMenuFlyoutWidth = 0;
+      });
+
+      remButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.RemoveDocFromList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true);
+      moveButtonDoc = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => this.remButtonDoc(doc) && addDocument(doc);
+      addButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true);
+
+      buttonBarXf = () => {
+            if (!this._docBtnRef.current) return Transform.Identity();
+            const { scale, translateX, translateY } = Utils.GetScreenTransform(this._docBtnRef.current);
+            return new Transform(-translateX, -translateY, 1 / scale);
+      }
+
+      @computed get docButtons() {
+            return !(this.userDoc.dockedBtns instanceof Doc) ? (null) :
+                  <div className="mainView-docButtons" ref={this._docBtnRef} style={{ height: !this.userDoc.dockedBtns.linearViewIsExpanded ? "42px" : undefined }} >
+                        <CollectionLinearView
+                              Document={this.userDoc.dockedBtns}
+                              DataDoc={undefined}
+                              fieldKey={"data"}
+                              dropAction={"alias"}
+                              setHeight={returnFalse}
+                              styleProvider={DefaultStyleProvider}
+                              layerProvider={undefined}
+                              rootSelected={returnTrue}
+                              bringToFront={emptyFunction}
+                              select={emptyFunction}
+                              isAnyChildContentActive={returnFalse}
+                              isContentActive={emptyFunction}
+                              isSelected={returnFalse}
+                              docViewPath={returnEmptyDoclist}
+                              moveDocument={this.moveButtonDoc}
+                              CollectionView={undefined}
+                              addDocument={this.addButtonDoc}
+                              addDocTab={this.addDocTabFunc}
+                              pinToPres={emptyFunction}
+                              removeDocument={this.remButtonDoc}
+                              ScreenToLocalTransform={this.buttonBarXf}
+                              PanelWidth={this.leftMenuFlyoutWidth}
+                              PanelHeight={this.leftMenuFlyoutHeight}
+                              renderDepth={0}
+                              focus={DocUtils.DefaultFocus}
+                              whenChildContentsActiveChanged={emptyFunction}
+                              docFilters={returnEmptyFilter}
+                              docRangeFilters={returnEmptyFilter}
+                              searchFilterDocs={returnEmptyDoclist}
+                              ContainingCollectionView={undefined}
+                              ContainingCollectionDoc={undefined} />
+                        {['watching', 'recording'].includes(String(this.userDoc?.presentationMode) ?? '') ? <div style={{ border: '.5rem solid green', padding: '5px' }}>{this.userDoc?.presentationMode}</div> : <></>}
+                  </div>;
+      }
+      @computed get snapLines() {
+            return !this.userDoc.showSnapLines ? (null) : <div className="mainView-snapLines">
+                  <svg style={{ width: "100%", height: "100%" }}>
+                        {SnappingManager.horizSnapLines().map(l => <line x1="0" y1={l} x2="2000" y2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={"1 1"} />)}
+                        {SnappingManager.vertSnapLines().map(l => <line y1="0" x1={l} y2="2000" x2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={"1 1"} />)}
+                  </svg>
             </div>;
-    }
-    @computed get snapLines() {
-        return !this.userDoc.showSnapLines ? (null) : <div className="mainView-snapLines">
-            <svg style={{ width: "100%", height: "100%" }}>
-                {SnappingManager.horizSnapLines().map(l => <line x1="0" y1={l} x2="2000" y2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={"1 1"} />)}
-                {SnappingManager.vertSnapLines().map(l => <line y1="0" x1={l} y2="2000" x2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={"1 1"} />)}
-            </svg>
-        </div>;
-    }
-
-    @computed get inkResources() {
-        return <svg width={0} height={0}>
-            <defs>
-                <filter id="inkSelectionHalo">
-                    <feColorMatrix type="matrix"
-                        result="color"
-                        values="1 0 0 0 0
+      }
+
+      @computed get inkResources() {
+            return <svg width={0} height={0}>
+                  <defs>
+                        <filter id="inkSelectionHalo">
+                              <feColorMatrix type="matrix"
+                                    result="color"
+                                    values="1 0 0 0 0
                 0 0 0 0 0
                 0 0 0 0 0
                 0 0 0 1 0">
-                    </feColorMatrix>
-                    <feGaussianBlur in="color" stdDeviation="4" result="blur"></feGaussianBlur>
-                    <feOffset in="blur" dx="0" dy="0" result="offset"></feOffset>
-                    <feMerge>
-                        <feMergeNode in="bg"></feMergeNode>
-                        <feMergeNode in="offset"></feMergeNode>
-                        <feMergeNode in="SourceGraphic"></feMergeNode>
-                    </feMerge>
-                </filter>
-            </defs>
-        </svg>;
-    }
-
-    @computed get topbar() {
-        TraceMobx();
-        return <div className="mainView-topbar">
-            <TopBar />
-        </div>;
-    }
-
-    @computed get invisibleWebBox() { // see note under the makeLink method in HypothesisUtils.ts
-        return !DocumentLinksButton.invisibleWebDoc ? null :
-            <div className="mainView-invisibleWebRef" ref={DocumentLinksButton.invisibleWebRef}>
-                <WebBox
-                    fieldKey={"data"}
-                    ContainingCollectionView={undefined}
-                    ContainingCollectionDoc={undefined}
-                    Document={DocumentLinksButton.invisibleWebDoc}
-                    dropAction={"move"}
-                    layerProvider={undefined}
-                    styleProvider={undefined}
-                    isSelected={returnFalse}
-                    select={returnFalse}
-                    setHeight={returnFalse}
-                    rootSelected={returnFalse}
-                    renderDepth={0}
-                    addDocTab={returnFalse}
-                    pinToPres={returnFalse}
-                    ScreenToLocalTransform={Transform.Identity}
-                    bringToFront={returnFalse}
-                    isContentActive={emptyFunction}
-                    whenChildContentsActiveChanged={returnFalse}
-                    focus={returnFalse}
-                    docViewPath={returnEmptyDoclist}
-                    PanelWidth={() => 500}
-                    PanelHeight={() => 800}
-                    docFilters={returnEmptyFilter}
-                    docRangeFilters={returnEmptyFilter}
-                    searchFilterDocs={returnEmptyDoclist}
-                />
+                              </feColorMatrix>
+                              <feGaussianBlur in="color" stdDeviation="4" result="blur"></feGaussianBlur>
+                              <feOffset in="blur" dx="0" dy="0" result="offset"></feOffset>
+                              <feMerge>
+                                    <feMergeNode in="bg"></feMergeNode>
+                                    <feMergeNode in="offset"></feMergeNode>
+                                    <feMergeNode in="SourceGraphic"></feMergeNode>
+                              </feMerge>
+                        </filter>
+                  </defs>
+            </svg>;
+      }
+
+      @computed get topbar() {
+            TraceMobx();
+            return <div className="mainView-topbar">
+                  <TopBar />
             </div>;
-    }
-
-    render() {
-        return (<div className={`mainView-container${this.colorScheme}`}
-            onScroll={() => ((ele) => ele.scrollTop = ele.scrollLeft = 0)(document.getElementById("root")!)}
-            ref={r => {
-                r && new _global.ResizeObserver(action(() => { this._windowWidth = r.getBoundingClientRect().width; this._windowHeight = r.getBoundingClientRect().height; })).observe(r);
-            }}>
-            {this.inkResources}
-            <DictationOverlay />
-            <SharingManager />
-            <SettingsManager />
-            <CaptureManager />
-            <GroupManager />
-            <GoogleAuthenticationManager />
-            <DocumentDecorations boundsLeft={this.leftScreenOffsetOfMainDocView} boundsTop={this.topOfMainDoc} PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} />
-            <ComponentDecorations boundsLeft={this.leftScreenOffsetOfMainDocView} boundsTop={this.topOfMainDocContent} />
-            {this.topbar}
-            {LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null}
-            {DocumentLinksButton.LinkEditorDocView ? <LinkMenu clearLinkEditor={action(() => DocumentLinksButton.LinkEditorDocView = undefined)} docView={DocumentLinksButton.LinkEditorDocView} /> : (null)}
-            {LinkDocPreview.LinkInfo ? <LinkDocPreview {...LinkDocPreview.LinkInfo} /> : (null)}
-            <div style={{ position: "relative", display: LightboxView.LightboxDoc ? "none" : undefined, zIndex: 2001 }} >
-                <CollectionMenu panelWidth={this.topMenuWidth} panelHeight={this.topMenuHeight} />
-            </div>
-            <GestureOverlay >
-                {this.mainDashboardArea}
-            </GestureOverlay>
-            <PreviewCursor />
-            <TaskCompletionBox />
-            <ContextMenu />
-            <RadialMenu />
-            <AnchorMenu />
-            <MarqueeOptionsMenu />
-            <OverlayView />
-            <TimelineMenu />
-            <RichTextMenu />
-            {this.snapLines}
-            <div className="mainView-webRef" ref={this.makeWebRef} />
-            <LightboxView PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} maxBorder={[200, 50]} />
-        </div >);
-    }
-
-    makeWebRef = (ele: HTMLDivElement) => {
-        reaction(() => DocumentLinksButton.invisibleWebDoc,
-            invisibleDoc => {
-                ReactDOM.unmountComponentAtNode(ele);
-                invisibleDoc && ReactDOM.render(<span title="Drag as document" className="invisible-webbox" >
-                    <div className="mainView-webRef" ref={DocumentLinksButton.invisibleWebRef}>
+      }
+
+      @computed get invisibleWebBox() { // see note under the makeLink method in HypothesisUtils.ts
+            return !DocumentLinksButton.invisibleWebDoc ? null :
+                  <div className="mainView-invisibleWebRef" ref={DocumentLinksButton.invisibleWebRef}>
                         <WebBox
-                            fieldKey={"data"}
-                            ContainingCollectionView={undefined}
-                            ContainingCollectionDoc={undefined}
-                            Document={invisibleDoc}
-                            dropAction={"move"}
-                            isSelected={returnFalse}
-                            docViewPath={returnEmptyDoclist}
-                            select={returnFalse}
-                            rootSelected={returnFalse}
-                            renderDepth={0}
-                            setHeight={returnFalse}
-                            layerProvider={undefined}
-                            styleProvider={undefined}
-                            addDocTab={returnFalse}
-                            pinToPres={returnFalse}
-                            ScreenToLocalTransform={Transform.Identity}
-                            bringToFront={returnFalse}
-                            isContentActive={emptyFunction}
-                            whenChildContentsActiveChanged={returnFalse}
-                            focus={returnFalse}
-                            PanelWidth={() => 500}
-                            PanelHeight={() => 800}
-                            docFilters={returnEmptyFilter}
-                            docRangeFilters={returnEmptyFilter}
-                            searchFilterDocs={returnEmptyDoclist}
+                              fieldKey={"data"}
+                              ContainingCollectionView={undefined}
+                              ContainingCollectionDoc={undefined}
+                              Document={DocumentLinksButton.invisibleWebDoc}
+                              dropAction={"move"}
+                              layerProvider={undefined}
+                              styleProvider={undefined}
+                              isSelected={returnFalse}
+                              select={returnFalse}
+                              setHeight={returnFalse}
+                              rootSelected={returnFalse}
+                              renderDepth={0}
+                              addDocTab={returnFalse}
+                              pinToPres={returnFalse}
+                              ScreenToLocalTransform={Transform.Identity}
+                              bringToFront={returnFalse}
+                              isContentActive={emptyFunction}
+                              whenChildContentsActiveChanged={returnFalse}
+                              focus={returnFalse}
+                              docViewPath={returnEmptyDoclist}
+                              PanelWidth={() => 500}
+                              PanelHeight={() => 800}
+                              docFilters={returnEmptyFilter}
+                              docRangeFilters={returnEmptyFilter}
+                              searchFilterDocs={returnEmptyDoclist}
                         />
-                    </div>;
-                </span>, ele);
-
-                let success = false;
-                const onSuccess = () => {
-                    success = true;
-                    clearTimeout(interval);
-                    document.removeEventListener("editSuccess", onSuccess);
-                };
-
-                // For some reason, Hypothes.is annotations don't load until a click is registered on the page,
-                // so we keep simulating clicks until annotations have loaded and editing is successful
-                const interval = setInterval(() => !success && simulateMouseClick(ele, 50, 50, 50, 50), 500);
-                setTimeout(() => !success && clearInterval(interval), 10000); // give up if no success after 10s
-                document.addEventListener("editSuccess", onSuccess);
-            });
-    }
+                  </div>;
+      }
+
+      render() {
+            return (<div className={`mainView-container${this.colorScheme}`}
+                  onScroll={() => ((ele) => ele.scrollTop = ele.scrollLeft = 0)(document.getElementById("root")!)}
+                  ref={r => {
+                        r && new _global.ResizeObserver(action(() => { this._windowWidth = r.getBoundingClientRect().width; this._windowHeight = r.getBoundingClientRect().height; })).observe(r);
+                  }}>
+                  {this.inkResources}
+                  <DictationOverlay />
+                  <SharingManager />
+                  <SettingsManager />
+                  <CaptureManager />
+                  <GroupManager />
+                  <GoogleAuthenticationManager />
+                  <DocumentDecorations boundsLeft={this.leftScreenOffsetOfMainDocView} boundsTop={this.topOfMainDoc} PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} />
+                  <ComponentDecorations boundsLeft={this.leftScreenOffsetOfMainDocView} boundsTop={this.topOfMainDocContent} />
+                  {this.topbar}
+                  {LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null}
+                  {DocumentLinksButton.LinkEditorDocView ? <LinkMenu clearLinkEditor={action(() => DocumentLinksButton.LinkEditorDocView = undefined)} docView={DocumentLinksButton.LinkEditorDocView} /> : (null)}
+                  {LinkDocPreview.LinkInfo ? <LinkDocPreview {...LinkDocPreview.LinkInfo} /> : (null)}
+                  <div style={{ position: "relative", display: LightboxView.LightboxDoc ? "none" : undefined, zIndex: 2001 }} >
+                        <CollectionMenu panelWidth={this.topMenuWidth} panelHeight={this.topMenuHeight} />
+                  </div>
+                  <GestureOverlay >
+                        {this.mainDashboardArea}
+                  </GestureOverlay>
+                  <PreviewCursor />
+                  <TaskCompletionBox />
+                  <ContextMenu />
+                  <RadialMenu />
+                  <AnchorMenu />
+                  <MarqueeOptionsMenu />
+                  <OverlayView />
+                  <TimelineMenu />
+                  <RichTextMenu />
+                  {this.snapLines}
+                  <div className="mainView-webRef" ref={this.makeWebRef} />
+                  <LightboxView PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} maxBorder={[200, 50]} />
+            </div >);
+      }
+
+      makeWebRef = (ele: HTMLDivElement) => {
+            reaction(() => DocumentLinksButton.invisibleWebDoc,
+                  invisibleDoc => {
+                        ReactDOM.unmountComponentAtNode(ele);
+                        invisibleDoc && ReactDOM.render(<span title="Drag as document" className="invisible-webbox" >
+                              <div className="mainView-webRef" ref={DocumentLinksButton.invisibleWebRef}>
+                                    <WebBox
+                                          fieldKey={"data"}
+                                          ContainingCollectionView={undefined}
+                                          ContainingCollectionDoc={undefined}
+                                          Document={invisibleDoc}
+                                          dropAction={"move"}
+                                          isSelected={returnFalse}
+                                          docViewPath={returnEmptyDoclist}
+                                          select={returnFalse}
+                                          rootSelected={returnFalse}
+                                          renderDepth={0}
+                                          setHeight={returnFalse}
+                                          layerProvider={undefined}
+                                          styleProvider={undefined}
+                                          addDocTab={returnFalse}
+                                          pinToPres={returnFalse}
+                                          ScreenToLocalTransform={Transform.Identity}
+                                          bringToFront={returnFalse}
+                                          isContentActive={emptyFunction}
+                                          whenChildContentsActiveChanged={returnFalse}
+                                          focus={returnFalse}
+                                          PanelWidth={() => 500}
+                                          PanelHeight={() => 800}
+                                          docFilters={returnEmptyFilter}
+                                          docRangeFilters={returnEmptyFilter}
+                                          searchFilterDocs={returnEmptyDoclist}
+                                    />
+                              </div>;
+                        </span>, ele);
+
+                        let success = false;
+                        const onSuccess = () => {
+                              success = true;
+                              clearTimeout(interval);
+                              document.removeEventListener("editSuccess", onSuccess);
+                        };
+
+                        // For some reason, Hypothes.is annotations don't load until a click is registered on the page,
+                        // so we keep simulating clicks until annotations have loaded and editing is successful
+                        const interval = setInterval(() => !success && simulateMouseClick(ele, 50, 50, 50, 50), 500);
+                        setTimeout(() => !success && clearInterval(interval), 10000); // give up if no success after 10s
+                        document.addEventListener("editSuccess", onSuccess);
+                  });
+      }
 }
 
 ScriptingGlobals.add(function selectMainMenu(doc: Doc, title: string) { MainView.Instance.selectMenu(doc); });
\ No newline at end of file
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 6aed07c60..a2a08f5b8 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -67,23 +67,13 @@ export function RecordingView(props: IRecordingViewProps) {
             if (finished) {
                   props.setDuration(recordingTimer * 100)
                   let allVideoChunks: any = []
-                  console.log(videos)
                   videos.forEach((vid) => {
                         console.log(vid.videoChunks)
                         allVideoChunks = allVideoChunks.concat(vid.videoChunks)
                   })
 
-                  console.log(allVideoChunks)
                   const videoFile = new File(allVideoChunks, "video.mkv", { type: allVideoChunks[0].type, lastModified: Date.now() });
 
-                  // const uploadVideo = async () => {
-                  //       const [{ result }] = await Networking.UploadFilesToServer(videoFile);
-                  //       console.log("upload result", result);
-                  //       if (!(result instanceof Error)) {
-                  //             setResult(result)
-                  //       }
-                  // }
-
                   Networking.UploadFilesToServer(videoFile)
                         .then((data) => {
                               const result = data[0].result
@@ -93,13 +83,9 @@ export function RecordingView(props: IRecordingViewProps) {
                                     alert("video conversion failed");
                               }
                         })
-                  // uploadVideo()
 
                   //     this.dataDoc[this.fieldKey + "-duration"] = (new Date().getTime() - this.recordingStart!) / 1000;
 
-
-
-                  // change to one recording box
             }
 
 
@@ -190,7 +176,6 @@ export function RecordingView(props: IRecordingViewProps) {
             // recording paused
             videoRecorder.current.onpause = (event: any) => {
                   // append the current portion to the video pieces
-                  console.log(videoChunks)
                   setVideos(videos => [...videos, { videoChunks: videoChunks, endTime: recordingTimerRef.current }])
 
                   // reset the temporary chunks
@@ -199,7 +184,6 @@ export function RecordingView(props: IRecordingViewProps) {
             }
 
             videoRecorder.current.onresume = async (event: any) => {
-                  console.log(event)
                   await startShowingStream();
                   setRecording(true);
             }
@@ -226,7 +210,6 @@ export function RecordingView(props: IRecordingViewProps) {
       }
 
       const startOrResume = () => {
-            console.log('[RecordingView.tsx] startOrResume')
             if (!videoRecorder.current || videoRecorder.current.state === "inactive") {
                   record();
             } else if (videoRecorder.current.state === "paused") {
@@ -234,22 +217,6 @@ export function RecordingView(props: IRecordingViewProps) {
             }
       }
 
-      // const playSegment = (idx: number) => {
-      //       console.log(idx)
-      //       let currentChunks = videos[idx].chunks
-      //       console.log(currentChunks)
-
-      //       const blob = new Blob(currentChunks, {
-      //             type: 'video/webm'
-      //       })
-      //       const blobUrl = URL.createObjectURL(blob)
-      //       console.log(blobUrl)
-
-      //       videoElementRef.current!.srcObject = null
-      //       videoElementRef.current!.src = blobUrl
-      //       videoElementRef.current!.muted = false
-      // }
-
       const clearPrevious = () => {
             const numVideos = videos.length
             setRecordingTimer(numVideos == 1 ? 0 : videos[numVideos - 2].endTime)
@@ -284,14 +251,6 @@ export function RecordingView(props: IRecordingViewProps) {
             return toTwoDigit(minutes) + " : " + toTwoDigit(seconds);
       }
 
-
-
-
-      useEffect(() => {
-            console.log(videos.map((elt) => elt.endTime / MAXTIME * 100))
-            console.log(videos)
-      }, [videos])
-
       return (
             <div className="recording-container">
                   <div className="video-wrapper">
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index ca13590de..71b165618 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -30,540 +30,540 @@ import { WebBox } from '../WebBox';
 import { FontIconBadge } from './FontIconBadge';
 import './FontIconBox.scss';
 const FontIconSchema = createSchema({
-    icon: "string",
+      icon: "string",
 });
 
 export enum ButtonType {
-    TextButton = "textBtn",
-    MenuButton = "menuBtn",
-    DropdownList = "drpdownList",
-    DropdownButton = "drpdownBtn",
-    ClickButton = "clickBtn",
-    DoubleButton = "dblBtn",
-    ToggleButton = "tglBtn",
-    ColorButton = "colorBtn",
-    ToolButton = "toolBtn",
-    NumberButton = "numBtn",
-    EditableText = "editableText"
+      TextButton = "textBtn",
+      MenuButton = "menuBtn",
+      DropdownList = "drpdownList",
+      DropdownButton = "drpdownBtn",
+      ClickButton = "clickBtn",
+      DoubleButton = "dblBtn",
+      ToggleButton = "tglBtn",
+      ColorButton = "colorBtn",
+      ToolButton = "toolBtn",
+      NumberButton = "numBtn",
+      EditableText = "editableText"
 }
 
 export enum NumButtonType {
-    Slider = "slider",
-    DropdownOptions = "list",
-    Inline = "inline"
+      Slider = "slider",
+      DropdownOptions = "list",
+      Inline = "inline"
 }
 
 export interface ButtonProps extends FieldViewProps {
-    type?: ButtonType;
+      type?: ButtonType;
 }
 @observer
 export class FontIconBox extends DocComponent<ButtonProps>() {
-    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FontIconBox, fieldKey); }
-    showTemplate = (): void => {
-        const dragFactory = Cast(this.layoutDoc.dragFactory, Doc, null);
-        dragFactory && this.props.addDocTab(dragFactory, "add:right");
-    }
-    dragAsTemplate = (): void => { this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); };
-    useAsPrototype = (): void => { this.layoutDoc.onDragStart = ScriptField.MakeFunction('makeDelegate(this.dragFactory, true)'); };
-
-    specificContextMenu = (): void => {
-        if (!Doc.UserDoc().noviceMode) {
-            const cm = ContextMenu.Instance;
-            cm.addItem({ description: "Show Template", event: this.showTemplate, icon: "tag" });
-            cm.addItem({ description: "Use as Render Template", event: this.dragAsTemplate, icon: "tag" });
-            cm.addItem({ description: "Use as Prototype", event: this.useAsPrototype, icon: "tag" });
-        }
-    }
-
-    // Determining UI Specs
-    @observable private label = StrCast(this.rootDoc.label, StrCast(this.rootDoc.title));
-    @observable private icon = StrCast(this.dataDoc.icon, "user") as any;
-    @observable private dropdown: boolean = BoolCast(this.rootDoc.dropDownOpen);
-    @observable private buttonList: string[] = StrListCast(this.rootDoc.btnList);
-    @observable private type = StrCast(this.rootDoc.btnType);
-
-    /**
-     * Types of buttons in dash:
-     * - Main menu button (LHS)
-     * - Tool button
-     * - Expandable button (CollectionLinearView)
-     * - Button inside of CollectionLinearView vs. outside of CollectionLinearView
-     * - Action button
-     * - Dropdown button 
-     * - Color button
-     * - Dropdown list
-     * - Number button
-    **/
-
-    _batch: UndoManager.Batch | undefined = undefined;
-    /**
-     * Number button
-     */
-    @computed get numberButton() {
-        const numBtnType: string = StrCast(this.rootDoc.numBtnType);
-        const numScript = ScriptCast(this.rootDoc.script);
-        const setValue = (value: number) => numScript?.script.run({ value, _readOnly_: false });
-
-        // Script for checking the outcome of the toggle
-        const checkResult: number = numScript?.script.run({ value: 0, _readOnly_: true }).result || 0;
-
-        if (numBtnType === NumButtonType.Slider) {
-            const dropdown =
-                <div
-                    className="menuButton-dropdownBox"
-                    onPointerDown={e => e.stopPropagation()}
-                >
-                    <input type="range" step="1" min={NumCast(this.rootDoc.numBtnMin, 0)} max={NumCast(this.rootDoc.numBtnMax, 100)} value={checkResult}
-                        className={"menu-slider"} id="slider"
-                        onPointerDown={() => this._batch = UndoManager.StartBatch("presDuration")}
-                        onPointerUp={() => this._batch?.end()}
-                        onChange={e => { e.stopPropagation(); setValue(Number(e.target.value)); }}
-                    />
-                </div>;
-            return (
-                <div
-                    className={`menuButton ${this.type} ${numBtnType}`}
-                    onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}
-                >
-                    {checkResult}
-                    {this.rootDoc.dropDownOpen ? dropdown : null}
-                </div>
-            );
-        } else if (numBtnType === NumButtonType.DropdownOptions) {
-            const items: number[] = [];
-            for (let i = 0; i < 100; i++) {
-                if (i % 2 === 0) {
-                    items.push(i);
-                }
+      public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FontIconBox, fieldKey); }
+      showTemplate = (): void => {
+            const dragFactory = Cast(this.layoutDoc.dragFactory, Doc, null);
+            dragFactory && this.props.addDocTab(dragFactory, "add:right");
+      }
+      dragAsTemplate = (): void => { this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); };
+      useAsPrototype = (): void => { this.layoutDoc.onDragStart = ScriptField.MakeFunction('makeDelegate(this.dragFactory, true)'); };
+
+      specificContextMenu = (): void => {
+            if (!Doc.UserDoc().noviceMode) {
+                  const cm = ContextMenu.Instance;
+                  cm.addItem({ description: "Show Template", event: this.showTemplate, icon: "tag" });
+                  cm.addItem({ description: "Use as Render Template", event: this.dragAsTemplate, icon: "tag" });
+                  cm.addItem({ description: "Use as Prototype", event: this.useAsPrototype, icon: "tag" });
             }
-            const list = items.map((value) => {
-                return <div className="list-item" key={`${value}`}
-                    style={{
-                        backgroundColor: value === checkResult ? Colors.LIGHT_BLUE : undefined
-                    }}
-                    onClick={() => setValue(value)}>
-                    {value}
-                </div>;
-            });
-            return (
-                <div
-                    className={`menuButton ${this.type} ${numBtnType}`}
-                >
-                    <div className={`button`} onClick={action((e) => setValue(Number(checkResult) - 1))}>
-                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={"minus"} />
-                    </div>
-                    <div
-                        className={`button ${'number'}`}
-                        onPointerDown={(e) => {
-                            e.stopPropagation();
-                            e.preventDefault();
-                        }}
-                        onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}
-                    >
-                        <input
-                            style={{ width: 30 }}
-                            className="button-input"
-                            type="number"
-                            value={checkResult}
-                            onChange={action((e) => setValue(Number(e.target.value)))}
-                        />
-                    </div>
-                    <div className={`button`} onClick={action((e) => setValue(Number(checkResult) + 1))}>
-                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={"plus"} />
-                    </div>
-
-                    {this.rootDoc.dropDownOpen ?
+      }
+
+      // Determining UI Specs
+      @observable private label = StrCast(this.rootDoc.label, StrCast(this.rootDoc.title));
+      @observable private icon = StrCast(this.dataDoc.icon, "user") as any;
+      @observable private dropdown: boolean = BoolCast(this.rootDoc.dropDownOpen);
+      @observable private buttonList: string[] = StrListCast(this.rootDoc.btnList);
+      @observable private type = StrCast(this.rootDoc.btnType);
+
+      /**
+       * Types of buttons in dash:
+       * - Main menu button (LHS)
+       * - Tool button
+       * - Expandable button (CollectionLinearView)
+       * - Button inside of CollectionLinearView vs. outside of CollectionLinearView
+       * - Action button
+       * - Dropdown button 
+       * - Color button
+       * - Dropdown list
+       * - Number button
+      **/
+
+      _batch: UndoManager.Batch | undefined = undefined;
+      /**
+       * Number button
+       */
+      @computed get numberButton() {
+            const numBtnType: string = StrCast(this.rootDoc.numBtnType);
+            const numScript = ScriptCast(this.rootDoc.script);
+            const setValue = (value: number) => numScript?.script.run({ value, _readOnly_: false });
+
+            // Script for checking the outcome of the toggle
+            const checkResult: number = numScript?.script.run({ value: 0, _readOnly_: true }).result || 0;
+
+            if (numBtnType === NumButtonType.Slider) {
+                  const dropdown =
+                        <div
+                              className="menuButton-dropdownBox"
+                              onPointerDown={e => e.stopPropagation()}
+                        >
+                              <input type="range" step="1" min={NumCast(this.rootDoc.numBtnMin, 0)} max={NumCast(this.rootDoc.numBtnMax, 100)} value={checkResult}
+                                    className={"menu-slider"} id="slider"
+                                    onPointerDown={() => this._batch = UndoManager.StartBatch("presDuration")}
+                                    onPointerUp={() => this._batch?.end()}
+                                    onChange={e => { e.stopPropagation(); setValue(Number(e.target.value)); }}
+                              />
+                        </div>;
+                  return (
+                        <div
+                              className={`menuButton ${this.type} ${numBtnType}`}
+                              onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}
+                        >
+                              {checkResult}
+                              {this.rootDoc.dropDownOpen ? dropdown : null}
+                        </div>
+                  );
+            } else if (numBtnType === NumButtonType.DropdownOptions) {
+                  const items: number[] = [];
+                  for (let i = 0; i < 100; i++) {
+                        if (i % 2 === 0) {
+                              items.push(i);
+                        }
+                  }
+                  const list = items.map((value) => {
+                        return <div className="list-item" key={`${value}`}
+                              style={{
+                                    backgroundColor: value === checkResult ? Colors.LIGHT_BLUE : undefined
+                              }}
+                              onClick={() => setValue(value)}>
+                              {value}
+                        </div>;
+                  });
+                  return (
+                        <div
+                              className={`menuButton ${this.type} ${numBtnType}`}
+                        >
+                              <div className={`button`} onClick={action((e) => setValue(Number(checkResult) - 1))}>
+                                    <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={"minus"} />
+                              </div>
+                              <div
+                                    className={`button ${'number'}`}
+                                    onPointerDown={(e) => {
+                                          e.stopPropagation();
+                                          e.preventDefault();
+                                    }}
+                                    onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}
+                              >
+                                    <input
+                                          style={{ width: 30 }}
+                                          className="button-input"
+                                          type="number"
+                                          value={checkResult}
+                                          onChange={action((e) => setValue(Number(e.target.value)))}
+                                    />
+                              </div>
+                              <div className={`button`} onClick={action((e) => setValue(Number(checkResult) + 1))}>
+                                    <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={"plus"} />
+                              </div>
+
+                              {this.rootDoc.dropDownOpen ?
+                                    <div>
+                                          <div className="menuButton-dropdownList"
+                                                style={{ left: "25%" }}>
+                                                {list}
+                                          </div>
+                                          <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} />
+                                    </div> : null}
+
+                        </div>
+                  );
+            } else {
+                  return (
                         <div>
-                            <div className="menuButton-dropdownList"
-                                style={{ left: "25%" }}>
-                                {list}
-                            </div>
-                            <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} />
-                        </div> : null}
-
-                </div>
-            );
-        } else {
-            return (
-                <div>
 
-                </div>
-            );
-        }
-
-
-    }
-
-    /**
-     * Dropdown button
-     */
-    @computed get dropdownButton() {
-        const active: string = StrCast(this.rootDoc.dropDownOpen);
-        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
-        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-        return (
-            <div className={`menuButton ${this.type} ${active}`}
-                style={{ color: color, backgroundColor: backgroundColor, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
-                onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}>
-                <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
-                {!this.label || !Doc.UserDoc()._showLabel ? (null) : <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}> {this.label} </div>}
-                <div
-                    className="menuButton-dropdown"
-                    style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
-                    <FontAwesomeIcon icon={'caret-down'} color={color} size="sm" />
-                </div>
-                {this.rootDoc.dropDownOpen ?
-                    <div className="menuButton-dropdownBox">
-                        {/* DROPDOWN BOX CONTENTS */}
-                    </div> : null}
-            </div>
-        );
-    }
-
-    /**
-     * Dropdown list
-     */
-    @computed get dropdownListButton() {
-        const active: string = StrCast(this.rootDoc.dropDownOpen);
-        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
-        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-
-        const script = ScriptCast(this.rootDoc.script);
-
-        let noviceList: string[] = [];
-        let text: string | undefined;
-        let dropdown = true;
-        let icon: IconProp = "caret-down";
-        try {
-            if (script.script.originalScript.startsWith('setView')) {
-                const selected = SelectionManager.Docs().lastElement();
-                if (selected) {
-                    if (StrCast(selected.type) === DocumentType.COL) {
-                        text = StrCast(selected._viewType);
-                    } else {
-                        dropdown = false;
-                        text = selected.type === DocumentType.RTF ? "Text" : StrCast(selected.type);
-                        icon = Doc.toIcon(selected);
-                    }
-                } else {
-                    dropdown = false;
-                    icon = "globe-asia";
-                    text = "User Default";
-                }
-                noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking];
-            } else if (script.script.originalScript.startsWith('setFont')) {
-                const editorView = RichTextMenu.Instance?.TextView?.EditorView;
-                text = StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
-                noviceList = ["Roboto", "Times New Roman", "Arial", "Georgia",
-                    "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"];
-            }
-        } catch (e) {
-            console.log(e);
-        }
-
-        // Get items to place into the list
-        const list = this.buttonList.map((value) => {
-            if (Doc.UserDoc().noviceMode && !noviceList.includes(value)) {
-                return;
+                        </div>
+                  );
             }
-            return <div className="list-item" key={`${value}`}
-                style={{
-                    fontFamily: script.script.originalScript.startsWith('setFont') ? value : undefined,
-                    backgroundColor: value === text ? Colors.LIGHT_BLUE : undefined
-                }}
-                onClick={() => script.script.run({ value }).result}>
-                {value[0].toUpperCase() + value.slice(1)}
-            </div>;
-        });
 
-        const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
-            <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor, position: "absolute" }}>
-                {this.label}
-            </div>;
 
-        return (
-            <div className={`menuButton ${this.type} ${active}`}
-                style={{ backgroundColor: this.rootDoc.dropDownOpen ? Colors.MEDIUM_BLUE : backgroundColor, color: color, display: dropdown ? undefined : "flex" }}
-                onClick={dropdown ? () => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen : undefined}>
-                {dropdown ? (null) : <FontAwesomeIcon style={{ marginLeft: 5 }} className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />}
-                <div className="menuButton-dropdown-header">
-                    {text && text[0].toUpperCase() + text.slice(1)}
-                </div>
-                {label}
-                {!dropdown ? (null) : <div className="menuButton-dropDown">
-                    <FontAwesomeIcon icon={icon} color={color} size="sm" />
-                </div>}
-                {this.rootDoc.dropDownOpen ?
-                    <div>
-                        <div className="menuButton-dropdownList"
-                            style={{ left: 0 }}>
-                            {list}
-                        </div>
-                        <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} />
-                    </div>
-                    : null}
-            </div>
-        );
-    }
-
-    @observable colorPickerClosed: boolean = true;
-    @computed get colorScript() { return ScriptCast(this.rootDoc.script); }
-
-    colorPicker = (curColor: string) => {
-        const change = (value: ColorState) => {
-            const s = this.colorScript;
-            s && undoBatch(() => s.script.run({ value: Utils.colorString(value), _readOnly_: false }).result)();
-        };
-        const presets = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
-            '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
-            '#FFFFFF', '#f1efeb', "transparent"];
-        return <SketchPicker
-            onChange={change}
-            color={curColor}
-            presetColors={presets} />;
-    }
-    /**
-     * Color button
-     */
-    @computed get colorButton() {
-        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
-        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-        const curColor = this.colorScript?.script.run({ value: undefined, _readOnly_: true }).result ?? "transparent";
-
-        const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
-            <div className="fontIconBox-label" style={{ color, backgroundColor, position: "absolute" }}>
-                {this.label}
-            </div>;
+      }
 
-        const dropdownCaret = <div
-            className="menuButton-dropDown"
-            style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
-            <FontAwesomeIcon icon={'caret-down'} color={color} size="sm" />
-        </div>;
-        setTimeout(() => this.colorPicker(curColor)); // cause an update to the color picker rendered in MainView
-        return (
-            <div className={`menuButton ${this.type} ${this.colorPickerClosed}`}
-                style={{ color: color, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
-                onClick={action(() => this.colorPickerClosed = !this.colorPickerClosed)}
-                onPointerDown={e => e.stopPropagation()}>
-                <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
-                <div className="colorButton-color" style={{ backgroundColor: curColor }} />
-                {label}
-                {/* {dropdownCaret} */}
-                {this.colorPickerClosed ? (null) :
-                    <div>
-                        <div className="menuButton-dropdownBox"
-                            onPointerDown={e => e.stopPropagation()}
-                            onClick={e => e.stopPropagation()}>
-                            {this.colorPicker(curColor)}
+      /**
+       * Dropdown button
+       */
+      @computed get dropdownButton() {
+            const active: string = StrCast(this.rootDoc.dropDownOpen);
+            const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+            const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+            return (
+                  <div className={`menuButton ${this.type} ${active}`}
+                        style={{ color: color, backgroundColor: backgroundColor, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
+                        onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}>
+                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
+                        {!this.label || !Doc.UserDoc()._showLabel ? (null) : <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}> {this.label} </div>}
+                        <div
+                              className="menuButton-dropdown"
+                              style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
+                              <FontAwesomeIcon icon={'caret-down'} color={color} size="sm" />
                         </div>
-                        <div className="dropbox-background" onClick={action((e) => {
-                            e.stopPropagation(); this.colorPickerClosed = true;
-                        })} />
-                    </div>}
-            </div>
-        );
-    }
-
-    @computed get toggleButton() {
-        // Determine the type of toggle button
-        const switchToggle: boolean = BoolCast(this.rootDoc.switchToggle);
-        const buttonText: string = StrCast(this.rootDoc.buttonText);
-        // Colors
-        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
-        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-
-        // Button label
-        const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
-            <div className="fontIconBox-label" style={{ color, backgroundColor, position: "absolute" }}>
-                {this.label}
-            </div>;
+                        {this.rootDoc.dropDownOpen ?
+                              <div className="menuButton-dropdownBox">
+                                    {/* DROPDOWN BOX CONTENTS */}
+                              </div> : null}
+                  </div>
+            );
+      }
+
+      /**
+       * Dropdown list
+       */
+      @computed get dropdownListButton() {
+            const active: string = StrCast(this.rootDoc.dropDownOpen);
+            const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+            const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+
+            const script = ScriptCast(this.rootDoc.script);
+
+            let noviceList: string[] = [];
+            let text: string | undefined;
+            let dropdown = true;
+            let icon: IconProp = "caret-down";
+            try {
+                  if (script.script.originalScript.startsWith('setView')) {
+                        const selected = SelectionManager.Docs().lastElement();
+                        if (selected) {
+                              if (StrCast(selected.type) === DocumentType.COL) {
+                                    text = StrCast(selected._viewType);
+                              } else {
+                                    dropdown = false;
+                                    text = selected.type === DocumentType.RTF ? "Text" : StrCast(selected.type);
+                                    icon = Doc.toIcon(selected);
+                              }
+                        } else {
+                              dropdown = false;
+                              icon = "globe-asia";
+                              text = "User Default";
+                        }
+                        noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking];
+                  } else if (script.script.originalScript.startsWith('setFont')) {
+                        const editorView = RichTextMenu.Instance?.TextView?.EditorView;
+                        text = StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
+                        noviceList = ["Roboto", "Times New Roman", "Arial", "Georgia",
+                              "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"];
+                  }
+            } catch (e) {
+                  console.log(e);
+            }
+
+            // Get items to place into the list
+            const list = this.buttonList.map((value) => {
+                  if (Doc.UserDoc().noviceMode && !noviceList.includes(value)) {
+                        return;
+                  }
+                  return <div className="list-item" key={`${value}`}
+                        style={{
+                              fontFamily: script.script.originalScript.startsWith('setFont') ? value : undefined,
+                              backgroundColor: value === text ? Colors.LIGHT_BLUE : undefined
+                        }}
+                        onClick={() => script.script.run({ value }).result}>
+                        {value[0].toUpperCase() + value.slice(1)}
+                  </div>;
+            });
+
+            const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
+                  <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor, position: "absolute" }}>
+                        {this.label}
+                  </div>;
 
-        if (switchToggle) {
             return (
-                <div className={`menuButton ${this.type} ${'switch'}`}>
-                    {buttonText ? buttonText : null}
-                    <label className="switch">
-                        <input type="checkbox"
-                            checked={backgroundColor === Colors.MEDIUM_BLUE}
-                        />
-                        <span className="slider round"></span>
-                    </label>
-                </div>
+                  <div className={`menuButton ${this.type} ${active}`}
+                        style={{ backgroundColor: this.rootDoc.dropDownOpen ? Colors.MEDIUM_BLUE : backgroundColor, color: color, display: dropdown ? undefined : "flex" }}
+                        onClick={dropdown ? () => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen : undefined}>
+                        {dropdown ? (null) : <FontAwesomeIcon style={{ marginLeft: 5 }} className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />}
+                        <div className="menuButton-dropdown-header">
+                              {text && text[0].toUpperCase() + text.slice(1)}
+                        </div>
+                        {label}
+                        {!dropdown ? (null) : <div className="menuButton-dropDown">
+                              <FontAwesomeIcon icon={icon} color={color} size="sm" />
+                        </div>}
+                        {this.rootDoc.dropDownOpen ?
+                              <div>
+                                    <div className="menuButton-dropdownList"
+                                          style={{ left: 0 }}>
+                                          {list}
+                                    </div>
+                                    <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} />
+                              </div>
+                              : null}
+                  </div>
             );
-        } else {
+      }
+
+      @observable colorPickerClosed: boolean = true;
+      @computed get colorScript() { return ScriptCast(this.rootDoc.script); }
+
+      colorPicker = (curColor: string) => {
+            const change = (value: ColorState) => {
+                  const s = this.colorScript;
+                  s && undoBatch(() => s.script.run({ value: Utils.colorString(value), _readOnly_: false }).result)();
+            };
+            const presets = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
+                  '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
+                  '#FFFFFF', '#f1efeb', "transparent"];
+            return <SketchPicker
+                  onChange={change}
+                  color={curColor}
+                  presetColors={presets} />;
+      }
+      /**
+       * Color button
+       */
+      @computed get colorButton() {
+            const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+            const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+            const curColor = this.colorScript?.script.run({ value: undefined, _readOnly_: true }).result ?? "transparent";
+
+            const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
+                  <div className="fontIconBox-label" style={{ color, backgroundColor, position: "absolute" }}>
+                        {this.label}
+                  </div>;
+
+            const dropdownCaret = <div
+                  className="menuButton-dropDown"
+                  style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
+                  <FontAwesomeIcon icon={'caret-down'} color={color} size="sm" />
+            </div>;
+            setTimeout(() => this.colorPicker(curColor)); // cause an update to the color picker rendered in MainView
             return (
-                <div className={`menuButton ${this.type}`}
-                    style={{ opacity: 1, backgroundColor, color }}>
-                    <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
-                    {label}
-                </div>
+                  <div className={`menuButton ${this.type} ${this.colorPickerClosed}`}
+                        style={{ color: color, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
+                        onClick={action(() => this.colorPickerClosed = !this.colorPickerClosed)}
+                        onPointerDown={e => e.stopPropagation()}>
+                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
+                        <div className="colorButton-color" style={{ backgroundColor: curColor }} />
+                        {label}
+                        {/* {dropdownCaret} */}
+                        {this.colorPickerClosed ? (null) :
+                              <div>
+                                    <div className="menuButton-dropdownBox"
+                                          onPointerDown={e => e.stopPropagation()}
+                                          onClick={e => e.stopPropagation()}>
+                                          {this.colorPicker(curColor)}
+                                    </div>
+                                    <div className="dropbox-background" onClick={action((e) => {
+                                          e.stopPropagation(); this.colorPickerClosed = true;
+                                    })} />
+                              </div>}
+                  </div>
             );
-        }
-    }
-
-
-
-    /**
-     * Default
-     */
-    @computed get defaultButton() {
-        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
-        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-        const active: string = StrCast(this.rootDoc.dropDownOpen);
-        return (
-            <div className={`menuButton ${this.type}`} onContextMenu={this.specificContextMenu}
-                style={{ backgroundColor: "transparent", borderBottomLeftRadius: this.dropdown ? 0 : undefined }}>
-                <div className="menuButton-wrap">
-                    <FontAwesomeIcon className={`menuButton-icon-${this.type}`} icon={this.icon} color={"black"} size={"sm"} />
-                    {!this.label || !Doc.UserDoc()._showLabel ? (null) : <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}> {this.label} </div>}
-                </div>
-            </div>
-        );
-    }
-
-    @computed get editableText() {
-        // Script for running the toggle
-        const script = ScriptCast(this.rootDoc.script);
-        // Function to run the script
-        const checkResult = script?.script.run({ value: "", _readOnly_: true }).result;
-
-        const setValue = (value: string, shiftDown?: boolean): boolean => script?.script.run({ value, _readOnly_: false }).result;
-        return (
-            <div className="menuButton editableText">
-                <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={"lock"} />
-                <div style={{ width: "calc(100% - .875em)", paddingLeft: "4px" }}>
-                    <EditableView GetValue={() => script?.script.run({ value: "", _readOnly_: true }).result} SetValue={setValue} contents={checkResult} />
-                </div>
-            </div>
-        );
-    }
-
-    render() {
-        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
-        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-        const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
-            <div className="fontIconBox-label" style={{ color, backgroundColor, position: "absolute" }}>
-                {this.label}
-            </div>;
+      }
+
+      @computed get toggleButton() {
+            // Determine the type of toggle button
+            const switchToggle: boolean = BoolCast(this.rootDoc.switchToggle);
+            const buttonText: string = StrCast(this.rootDoc.buttonText);
+            // Colors
+            const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+            const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+
+            // Button label
+            const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
+                  <div className="fontIconBox-label" style={{ color, backgroundColor, position: "absolute" }}>
+                        {this.label}
+                  </div>;
+
+            if (switchToggle) {
+                  return (
+                        <div className={`menuButton ${this.type} ${'switch'}`}>
+                              {buttonText ? buttonText : null}
+                              <label className="switch">
+                                    <input type="checkbox"
+                                          checked={backgroundColor === Colors.MEDIUM_BLUE}
+                                    />
+                                    <span className="slider round"></span>
+                              </label>
+                        </div>
+                  );
+            } else {
+                  return (
+                        <div className={`menuButton ${this.type}`}
+                              style={{ opacity: 1, backgroundColor, color }}>
+                              <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
+                              {label}
+                        </div>
+                  );
+            }
+      }
 
-        const menuLabel = !this.label || !Doc.UserDoc()._showMenuLabel ? (null) :
-            <div className="fontIconBox-label" style={{ color, backgroundColor: "transparent" }}>
-                {this.label}
-            </div>;
 
-        const buttonText = StrCast(this.rootDoc.buttonText);
 
-        // TODO:glr Add label of button type
-        let button = this.defaultButton;
+      /**
+       * Default
+       */
+      @computed get defaultButton() {
+            const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+            const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+            const active: string = StrCast(this.rootDoc.dropDownOpen);
+            return (
+                  <div className={`menuButton ${this.type}`} onContextMenu={this.specificContextMenu}
+                        style={{ backgroundColor: "transparent", borderBottomLeftRadius: this.dropdown ? 0 : undefined }}>
+                        <div className="menuButton-wrap">
+                              <FontAwesomeIcon className={`menuButton-icon-${this.type}`} icon={this.icon} color={"black"} size={"sm"} />
+                              {!this.label || !Doc.UserDoc()._showLabel ? (null) : <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}> {this.label} </div>}
+                        </div>
+                  </div>
+            );
+      }
 
-        switch (this.type) {
-            case ButtonType.TextButton:
-                button = (
-                    <div className={`menuButton ${this.type}`} style={{ color, backgroundColor, opacity: 1, gridAutoColumns: `${NumCast(this.rootDoc._height)} auto` }}>
-                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
-                        {buttonText ?
-                            <div className="button-text">
-                                {buttonText}
-                            </div>
-                            : null}
-                        {label}
-                    </div>
-                );
-                // button = <TextButton {...buttonProps}></TextButton>
-                break;
-            case ButtonType.EditableText:
-                button = this.editableText;
-                break;
-            case ButtonType.NumberButton:
-                button = this.numberButton;
-                break;
-            case ButtonType.DropdownButton:
-                button = this.dropdownButton;
-                break;
-            case ButtonType.DropdownList:
-                button = this.dropdownListButton;
-                break;
-            case ButtonType.ColorButton:
-                button = this.colorButton;
-                break;
-            case ButtonType.ToolButton:
-                button = (
-                    <div className={`menuButton ${this.type}`} style={{ opacity: 1, backgroundColor, color }}>
-                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
-                        {label}
-                    </div>
-                );
-                break;
-            case ButtonType.ToggleButton:
-                button = this.toggleButton;
-                // button = <ToggleButton {...buttonProps}></ToggleButton>
-                break;
-            case ButtonType.ClickButton:
-                button = (
-                    <div className={`menuButton ${this.type}`} style={{ color, backgroundColor, opacity: 1 }}>
-                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
-                        {label}
-                    </div>
-                );
-                break;
-            case ButtonType.MenuButton:
-                const trailsIcon = <img src={`/assets/${"presTrails.png"}`}
-                    style={{ width: 30, height: 30, filter: `invert(${color === Colors.DARK_GRAY ? "0%" : "100%"})` }} />;
-                button = (
-                    <div className={`menuButton ${this.type}`} style={{ color, backgroundColor }}>
-                        {this.icon === "pres-trail" ? trailsIcon : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />}
-                        {menuLabel}
-                        <FontIconBadge collection={Cast(this.rootDoc.watchedDocuments, Doc, null)} />
-                    </div >
-                );
-                break;
-            default:
-                break;
-        }
-
-        return !this.layoutDoc.toolTip || this.type === ButtonType.DropdownList || this.type === ButtonType.ColorButton || this.type === ButtonType.NumberButton || this.type === ButtonType.EditableText ? button :
-            <Tooltip title={<div className="dash-tooltip">{StrCast(this.layoutDoc.toolTip)}</div>}>
-                {button}
-            </Tooltip>;
-    }
+      @computed get editableText() {
+            // Script for running the toggle
+            const script = ScriptCast(this.rootDoc.script);
+            // Function to run the script
+            const checkResult = script?.script.run({ value: "", _readOnly_: true }).result;
+
+            const setValue = (value: string, shiftDown?: boolean): boolean => script?.script.run({ value, _readOnly_: false }).result;
+            return (
+                  <div className="menuButton editableText">
+                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={"lock"} />
+                        <div style={{ width: "calc(100% - .875em)", paddingLeft: "4px" }}>
+                              <EditableView GetValue={() => script?.script.run({ value: "", _readOnly_: true }).result} SetValue={setValue} contents={checkResult} />
+                        </div>
+                  </div>
+            );
+      }
+
+      render() {
+            const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+            const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+            const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
+                  <div className="fontIconBox-label" style={{ color, backgroundColor, position: "absolute" }}>
+                        {this.label}
+                  </div>;
+
+            const menuLabel = !this.label || !Doc.UserDoc()._showMenuLabel ? (null) :
+                  <div className="fontIconBox-label" style={{ color, backgroundColor: "transparent" }}>
+                        {this.label}
+                  </div>;
+
+            const buttonText = StrCast(this.rootDoc.buttonText);
+
+            // TODO:glr Add label of button type
+            let button = this.defaultButton;
+
+            switch (this.type) {
+                  case ButtonType.TextButton:
+                        button = (
+                              <div className={`menuButton ${this.type}`} style={{ color, backgroundColor, opacity: 1, gridAutoColumns: `${NumCast(this.rootDoc._height)} auto` }}>
+                                    <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
+                                    {buttonText ?
+                                          <div className="button-text">
+                                                {buttonText}
+                                          </div>
+                                          : null}
+                                    {label}
+                              </div>
+                        );
+                        // button = <TextButton {...buttonProps}></TextButton>
+                        break;
+                  case ButtonType.EditableText:
+                        button = this.editableText;
+                        break;
+                  case ButtonType.NumberButton:
+                        button = this.numberButton;
+                        break;
+                  case ButtonType.DropdownButton:
+                        button = this.dropdownButton;
+                        break;
+                  case ButtonType.DropdownList:
+                        button = this.dropdownListButton;
+                        break;
+                  case ButtonType.ColorButton:
+                        button = this.colorButton;
+                        break;
+                  case ButtonType.ToolButton:
+                        button = (
+                              <div className={`menuButton ${this.type}`} style={{ opacity: 1, backgroundColor, color }}>
+                                    <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
+                                    {label}
+                              </div>
+                        );
+                        break;
+                  case ButtonType.ToggleButton:
+                        button = this.toggleButton;
+                        // button = <ToggleButton {...buttonProps}></ToggleButton>
+                        break;
+                  case ButtonType.ClickButton:
+                        button = (
+                              <div className={`menuButton ${this.type}`} style={{ color, backgroundColor, opacity: 1 }}>
+                                    <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
+                                    {label}
+                              </div>
+                        );
+                        break;
+                  case ButtonType.MenuButton:
+                        const trailsIcon = <img src={`/assets/${"presTrails.png"}`}
+                              style={{ width: 30, height: 30, filter: `invert(${color === Colors.DARK_GRAY ? "0%" : "100%"})` }} />;
+                        button = (
+                              <div className={`menuButton ${this.type}`} style={{ color, backgroundColor }}>
+                                    {this.icon === "pres-trail" ? trailsIcon : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />}
+                                    {menuLabel}
+                                    <FontIconBadge collection={Cast(this.rootDoc.watchedDocuments, Doc, null)} />
+                              </div >
+                        );
+                        break;
+                  default:
+                        break;
+            }
+
+            return !this.layoutDoc.toolTip || this.type === ButtonType.DropdownList || this.type === ButtonType.ColorButton || this.type === ButtonType.NumberButton || this.type === ButtonType.EditableText ? button :
+                  <Tooltip title={<div className="dash-tooltip">{StrCast(this.layoutDoc.toolTip)}</div>}>
+                        {button}
+                  </Tooltip>;
+      }
 }
 
 
 // toggle: Set overlay status of selected document
 ScriptingGlobals.add(function setView(view: string) {
-    const selected = SelectionManager.Docs().lastElement();
-    selected ? selected._viewType = view : console.log("[FontIconBox.tsx] changeView failed");
+      const selected = SelectionManager.Docs().lastElement();
+      selected ? selected._viewType = view : console.log("[FontIconBox.tsx] changeView failed");
 });
 
 
 // toggle: Set overlay status of selected document
 ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) {
-    const selected = SelectionManager.Docs().lastElement();
-    if (checkResult) {
-        return selected?._backgroundColor ?? "transparent";
-    }
-    if (selected) selected._backgroundColor = color;
+      const selected = SelectionManager.Docs().lastElement();
+      if (checkResult) {
+            return selected?._backgroundColor ?? "transparent";
+      }
+      if (selected) selected._backgroundColor = color;
 });
 
 // toggle: Set overlay status of selected document
 ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boolean) {
-    if (checkResult) {
-        return Doc.SharingDoc().userColor;
-    }
-    Doc.SharingDoc().userColor = undefined;
-    Doc.GetProto(Doc.SharingDoc()).userColor = color;
-    Doc.UserDoc().showTitle = color === "transparent" ? undefined : StrCast(Doc.UserDoc().showTitle, "creationDate");
+      if (checkResult) {
+            return Doc.SharingDoc().userColor;
+      }
+      Doc.SharingDoc().userColor = undefined;
+      Doc.GetProto(Doc.SharingDoc()).userColor = color;
+      Doc.UserDoc().showTitle = color === "transparent" ? undefined : StrCast(Doc.UserDoc().showTitle, "creationDate");
 });
 
 // toggle: Set overlay status of selected document
 ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
-    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
-    if (checkResult && selected) {
-        if (NumCast(selected.Document.z) >= 1) return Colors.MEDIUM_BLUE;
-        return "transparent";
-    }
-    selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log("[FontIconBox.tsx] toggleOverlay failed");
+      const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
+      if (checkResult && selected) {
+            if (NumCast(selected.Document.z) >= 1) return Colors.MEDIUM_BLUE;
+            return "transparent";
+      }
+      selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log("[FontIconBox.tsx] toggleOverlay failed");
 });
 
 /** TEXT
@@ -580,115 +580,115 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
 
 // toggle: Set overlay status of selected document
 ScriptingGlobals.add(function setFont(font: string, checkResult?: boolean) {
-    SelectionManager.Docs().map(doc => doc._fontFamily = font);
-    const editorView = RichTextMenu.Instance.TextView?.EditorView;
-    if (checkResult) {
-        return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
-    }
-    if (editorView) RichTextMenu.Instance.setFontFamily(font);
-    else Doc.UserDoc().fontFamily = font;
+      SelectionManager.Docs().map(doc => doc._fontFamily = font);
+      const editorView = RichTextMenu.Instance.TextView?.EditorView;
+      if (checkResult) {
+            return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
+      }
+      if (editorView) RichTextMenu.Instance.setFontFamily(font);
+      else Doc.UserDoc().fontFamily = font;
 });
 
 ScriptingGlobals.add(function getActiveTextInfo(info: "family" | "size" | "color" | "highlight") {
-    const editorView = RichTextMenu.Instance.TextView?.EditorView;
-    const style = editorView?.state && RichTextMenu.Instance.getActiveFontStylesOnSelection();
-    switch (info) {
-        case "family": return style?.activeFamilies[0];
-        case "size": return style?.activeSizes[0];
-        case "color": return style?.activeColors[0];
-        case "highlight": return style?.activeHighlights[0];
-    }
+      const editorView = RichTextMenu.Instance.TextView?.EditorView;
+      const style = editorView?.state && RichTextMenu.Instance.getActiveFontStylesOnSelection();
+      switch (info) {
+            case "family": return style?.activeFamilies[0];
+            case "size": return style?.activeSizes[0];
+            case "color": return style?.activeColors[0];
+            case "highlight": return style?.activeHighlights[0];
+      }
 });
 
 ScriptingGlobals.add(function setAlignment(align: "left" | "right" | "center", checkResult?: boolean) {
-    const editorView = RichTextMenu.Instance?.TextView?.EditorView;
-    if (checkResult) {
-        return (editorView ? RichTextMenu.Instance.textAlign : Doc.UserDoc().textAlign) === align ? Colors.MEDIUM_BLUE : "transparent";
-    }
-    if (editorView?.state) RichTextMenu.Instance.align(editorView, editorView.dispatch, align);
-    else Doc.UserDoc().textAlign = align;
+      const editorView = RichTextMenu.Instance?.TextView?.EditorView;
+      if (checkResult) {
+            return (editorView ? RichTextMenu.Instance.textAlign : Doc.UserDoc().textAlign) === align ? Colors.MEDIUM_BLUE : "transparent";
+      }
+      if (editorView?.state) RichTextMenu.Instance.align(editorView, editorView.dispatch, align);
+      else Doc.UserDoc().textAlign = align;
 });
 
 ScriptingGlobals.add(function setBulletList(mapStyle: "bullet" | "decimal", checkResult?: boolean) {
-    const editorView = RichTextMenu.Instance?.TextView?.EditorView;
-    if (checkResult) {
-        const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle();
-        if (active === mapStyle) return Colors.MEDIUM_BLUE;
-        return "transparent";
-    }
-    if (editorView) {
-        const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle();
-        editorView?.state && RichTextMenu.Instance.changeListType(
-            editorView.state.schema.nodes.ordered_list.create({ mapStyle: active === mapStyle ? "" : mapStyle }));
-    }
+      const editorView = RichTextMenu.Instance?.TextView?.EditorView;
+      if (checkResult) {
+            const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle();
+            if (active === mapStyle) return Colors.MEDIUM_BLUE;
+            return "transparent";
+      }
+      if (editorView) {
+            const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle();
+            editorView?.state && RichTextMenu.Instance.changeListType(
+                  editorView.state.schema.nodes.ordered_list.create({ mapStyle: active === mapStyle ? "" : mapStyle }));
+      }
 });
 
 // toggle: Set overlay status of selected document
 ScriptingGlobals.add(function setFontColor(color?: string, checkResult?: boolean) {
-    const editorView = RichTextMenu.Instance?.TextView?.EditorView;
+      const editorView = RichTextMenu.Instance?.TextView?.EditorView;
 
-    if (checkResult) {
-        return editorView ? RichTextMenu.Instance.fontColor : Doc.UserDoc().fontColor;
-    }
+      if (checkResult) {
+            return editorView ? RichTextMenu.Instance.fontColor : Doc.UserDoc().fontColor;
+      }
 
-    if (editorView) color && RichTextMenu.Instance.setColor(color, editorView, editorView?.dispatch);
-    else Doc.UserDoc().fontColor = color;
+      if (editorView) color && RichTextMenu.Instance.setColor(color, editorView, editorView?.dispatch);
+      else Doc.UserDoc().fontColor = color;
 });
 
 // toggle: Set overlay status of selected document
 ScriptingGlobals.add(function setFontHighlight(color?: string, checkResult?: boolean) {
-    const selected = SelectionManager.Docs().lastElement();
-    const editorView = RichTextMenu.Instance.TextView?.EditorView;
-
-    if (checkResult) {
-        return (selected ?? Doc.UserDoc())._fontHighlight;
-    }
-    if (selected) {
-        selected._fontColor = color;
-        if (color) {
-            editorView?.state && RichTextMenu.Instance.setHighlight(color, editorView, editorView?.dispatch);
-        }
-    }
-    Doc.UserDoc()._fontHighlight = color;
+      const selected = SelectionManager.Docs().lastElement();
+      const editorView = RichTextMenu.Instance.TextView?.EditorView;
+
+      if (checkResult) {
+            return (selected ?? Doc.UserDoc())._fontHighlight;
+      }
+      if (selected) {
+            selected._fontColor = color;
+            if (color) {
+                  editorView?.state && RichTextMenu.Instance.setHighlight(color, editorView, editorView?.dispatch);
+            }
+      }
+      Doc.UserDoc()._fontHighlight = color;
 });
 
 // toggle: Set overlay status of selected document
 ScriptingGlobals.add(function setFontSize(size: string | number, checkResult?: boolean) {
-    const editorView = RichTextMenu.Instance?.TextView?.EditorView;
-    if (checkResult) {
-        return (editorView ? RichTextMenu.Instance.fontSize : StrCast(Doc.UserDoc().fontSize, "10px")).replace("px", "");
-    }
-    if (typeof size === "number") size = size.toString();
-    if (size && Number(size).toString() === size) size += "px";
-    if (editorView) RichTextMenu.Instance.setFontSize(size);
-    else Doc.UserDoc()._fontSize = size;
+      const editorView = RichTextMenu.Instance?.TextView?.EditorView;
+      if (checkResult) {
+            return (editorView ? RichTextMenu.Instance.fontSize : StrCast(Doc.UserDoc().fontSize, "10px")).replace("px", "");
+      }
+      if (typeof size === "number") size = size.toString();
+      if (size && Number(size).toString() === size) size += "px";
+      if (editorView) RichTextMenu.Instance.setFontSize(size);
+      else Doc.UserDoc()._fontSize = size;
 });
 
 ScriptingGlobals.add(function toggleBold(checkResult?: boolean) {
-    const editorView = RichTextMenu.Instance?.TextView?.EditorView;
-    if (checkResult) {
-        return (editorView ? RichTextMenu.Instance.bold : Doc.UserDoc().fontWeight === "bold") ? Colors.MEDIUM_BLUE : "transparent";
-    }
-    if (editorView) RichTextMenu.Instance?.toggleBold();
-    else Doc.UserDoc().fontWeight = Doc.UserDoc().fontWeight === "bold" ? undefined : "bold";
+      const editorView = RichTextMenu.Instance?.TextView?.EditorView;
+      if (checkResult) {
+            return (editorView ? RichTextMenu.Instance.bold : Doc.UserDoc().fontWeight === "bold") ? Colors.MEDIUM_BLUE : "transparent";
+      }
+      if (editorView) RichTextMenu.Instance?.toggleBold();
+      else Doc.UserDoc().fontWeight = Doc.UserDoc().fontWeight === "bold" ? undefined : "bold";
 });
 
 ScriptingGlobals.add(function toggleUnderline(checkResult?: boolean) {
-    const editorView = RichTextMenu.Instance?.TextView?.EditorView;
-    if (checkResult) {
-        return (editorView ? RichTextMenu.Instance.underline : Doc.UserDoc().textDecoration === "underline") ? Colors.MEDIUM_BLUE : "transparent";
-    }
-    if (editorView) RichTextMenu.Instance?.toggleUnderline();
-    else Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === "underline" ? undefined : "underline";
+      const editorView = RichTextMenu.Instance?.TextView?.EditorView;
+      if (checkResult) {
+            return (editorView ? RichTextMenu.Instance.underline : Doc.UserDoc().textDecoration === "underline") ? Colors.MEDIUM_BLUE : "transparent";
+      }
+      if (editorView) RichTextMenu.Instance?.toggleUnderline();
+      else Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === "underline" ? undefined : "underline";
 });
 
 ScriptingGlobals.add(function toggleItalic(checkResult?: boolean) {
-    const editorView = RichTextMenu.Instance?.TextView?.EditorView;
-    if (checkResult) {
-        return (editorView ? RichTextMenu.Instance.italics : Doc.UserDoc().fontStyle === "italics") ? Colors.MEDIUM_BLUE : "transparent";
-    }
-    if (editorView) RichTextMenu.Instance?.toggleItalics();
-    else Doc.UserDoc().fontStyle = Doc.UserDoc().fontStyle === "italics" ? undefined : "italics";
+      const editorView = RichTextMenu.Instance?.TextView?.EditorView;
+      if (checkResult) {
+            return (editorView ? RichTextMenu.Instance.italics : Doc.UserDoc().fontStyle === "italics") ? Colors.MEDIUM_BLUE : "transparent";
+      }
+      if (editorView) RichTextMenu.Instance?.toggleItalics();
+      else Doc.UserDoc().fontStyle = Doc.UserDoc().fontStyle === "italics" ? undefined : "italics";
 });
 
 
@@ -701,66 +701,66 @@ ScriptingGlobals.add(function toggleItalic(checkResult?: boolean) {
  **/
 
 ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boolean) {
-    if (checkResult) {
-        return ((Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool) ?
-            Colors.MEDIUM_BLUE : "transparent";
-    }
-    if (["circle", "square", "line"].includes(tool)) {
-        if (GestureOverlay.Instance.InkShape === tool) {
-            Doc.UserDoc().activeInkTool = InkTool.None;
-            GestureOverlay.Instance.InkShape = InkTool.None;
-        } else {
-            Doc.UserDoc().activeInkTool = InkTool.Pen;
-            GestureOverlay.Instance.InkShape = tool;
-        }
-    } else if (tool) { // pen or eraser
-        if (Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance.InkShape) {
+      if (checkResult) {
+            return ((Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool) ?
+                  Colors.MEDIUM_BLUE : "transparent";
+      }
+      if (["circle", "square", "line"].includes(tool)) {
+            if (GestureOverlay.Instance.InkShape === tool) {
+                  Doc.UserDoc().activeInkTool = InkTool.None;
+                  GestureOverlay.Instance.InkShape = InkTool.None;
+            } else {
+                  Doc.UserDoc().activeInkTool = InkTool.Pen;
+                  GestureOverlay.Instance.InkShape = tool;
+            }
+      } else if (tool) { // pen or eraser
+            if (Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance.InkShape) {
+                  Doc.UserDoc().activeInkTool = InkTool.None;
+            } else {
+                  Doc.UserDoc().activeInkTool = tool;
+                  GestureOverlay.Instance.InkShape = "";
+            }
+      } else {
             Doc.UserDoc().activeInkTool = InkTool.None;
-        } else {
-            Doc.UserDoc().activeInkTool = tool;
-            GestureOverlay.Instance.InkShape = "";
-        }
-    } else {
-        Doc.UserDoc().activeInkTool = InkTool.None;
-    }
+      }
 });
 
 // toggle: Set overlay status of selected document
 ScriptingGlobals.add(function setFillColor(color?: string, checkResult?: boolean) {
-    const selected = SelectionManager.Docs().lastElement();
-    if (checkResult) {
-        if (selected?.type === DocumentType.INK) {
-            return StrCast(selected.fillColor);
-        }
-        return ActiveFillColor();
-    }
-    SetActiveFillColor(StrCast(color));
-    SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.fillColor = color);
+      const selected = SelectionManager.Docs().lastElement();
+      if (checkResult) {
+            if (selected?.type === DocumentType.INK) {
+                  return StrCast(selected.fillColor);
+            }
+            return ActiveFillColor();
+      }
+      SetActiveFillColor(StrCast(color));
+      SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.fillColor = color);
 });
 
 ScriptingGlobals.add(function setStrokeWidth(width: number, checkResult?: boolean) {
-    if (checkResult) {
-        const selected = SelectionManager.Docs().lastElement();
-        if (selected?.type === DocumentType.INK) {
-            return NumCast(selected.strokeWidth);
-        }
-        return ActiveInkWidth();
-    }
-    SetActiveInkWidth(width.toString());
-    SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.strokeWidth = Number(width));
+      if (checkResult) {
+            const selected = SelectionManager.Docs().lastElement();
+            if (selected?.type === DocumentType.INK) {
+                  return NumCast(selected.strokeWidth);
+            }
+            return ActiveInkWidth();
+      }
+      SetActiveInkWidth(width.toString());
+      SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.strokeWidth = Number(width));
 });
 
 // toggle: Set overlay status of selected document
 ScriptingGlobals.add(function setStrokeColor(color?: string, checkResult?: boolean) {
-    if (checkResult) {
-        const selected = SelectionManager.Docs().lastElement();
-        if (selected?.type === DocumentType.INK) {
-            return StrCast(selected.color);
-        }
-        return ActiveInkColor();
-    }
-    SetActiveInkColor(StrCast(color));
-    SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.color = String(color));
+      if (checkResult) {
+            const selected = SelectionManager.Docs().lastElement();
+            if (selected?.type === DocumentType.INK) {
+                  return StrCast(selected.color);
+            }
+            return ActiveInkColor();
+      }
+      SetActiveInkColor(StrCast(color));
+      SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.color = String(color));
 });
 
 
@@ -768,28 +768,28 @@ ScriptingGlobals.add(function setStrokeColor(color?: string, checkResult?: boole
  *      webSetURL
  **/
 ScriptingGlobals.add(function webSetURL(url: string, checkResult?: boolean) {
-    const selected = SelectionManager.Views().lastElement();
-    if (selected?.rootDoc.type === DocumentType.WEB) {
-        if (checkResult) {
-            return StrCast(selected.rootDoc.data, Cast(selected.rootDoc.data, WebField, null)?.url?.href);
-        }
-        (selected.ComponentView as WebBox).submitURL(url);
-        //selected.rootDoc.data = new WebField(url);
-    }
+      const selected = SelectionManager.Views().lastElement();
+      if (selected?.rootDoc.type === DocumentType.WEB) {
+            if (checkResult) {
+                  return StrCast(selected.rootDoc.data, Cast(selected.rootDoc.data, WebField, null)?.url?.href);
+            }
+            (selected.ComponentView as WebBox).submitURL(url);
+            //selected.rootDoc.data = new WebField(url);
+      }
 });
 ScriptingGlobals.add(function webForward(checkResult?: boolean) {
-    const selected = (SelectionManager.Views().lastElement()?.ComponentView as WebBox);
-    if (checkResult) {
-        return selected?.forward(checkResult) ? undefined : "lightGray";
-    }
-    selected?.forward();
+      const selected = (SelectionManager.Views().lastElement()?.ComponentView as WebBox);
+      if (checkResult) {
+            return selected?.forward(checkResult) ? undefined : "lightGray";
+      }
+      selected?.forward();
 });
 ScriptingGlobals.add(function webBack(checkResult?: boolean) {
-    const selected = (SelectionManager.Views().lastElement()?.ComponentView as WebBox);
-    if (checkResult) {
-        return selected?.back(checkResult) ? undefined : "lightGray";
-    }
-    selected?.back();
+      const selected = (SelectionManager.Views().lastElement()?.ComponentView as WebBox);
+      if (checkResult) {
+            return selected?.back(checkResult) ? undefined : "lightGray";
+      }
+      selected?.back();
 });
 
 
@@ -797,30 +797,30 @@ ScriptingGlobals.add(function webBack(checkResult?: boolean) {
  *      toggleSchemaPreview
  **/
 ScriptingGlobals.add(function toggleSchemaPreview(checkResult?: boolean) {
-    const selected = SelectionManager.Docs().lastElement();
-    if (checkResult && selected) {
-        const result: boolean = NumCast(selected.schemaPreviewWidth) > 0;
-        if (result) return Colors.MEDIUM_BLUE;
-        else return "transparent";
-    }
-    else if (selected) {
-        if (NumCast(selected.schemaPreviewWidth) > 0) {
-            selected.schemaPreviewWidth = 200;
-        } else {
-            selected.schemaPreviewWidth = 0;
-        }
-    }
+      const selected = SelectionManager.Docs().lastElement();
+      if (checkResult && selected) {
+            const result: boolean = NumCast(selected.schemaPreviewWidth) > 0;
+            if (result) return Colors.MEDIUM_BLUE;
+            else return "transparent";
+      }
+      else if (selected) {
+            if (NumCast(selected.schemaPreviewWidth) > 0) {
+                  selected.schemaPreviewWidth = 200;
+            } else {
+                  selected.schemaPreviewWidth = 0;
+            }
+      }
 });
 
 /** STACK
  *      groupBy
  */
 ScriptingGlobals.add(function setGroupBy(key: string, checkResult?: boolean) {
-    SelectionManager.Docs().map(doc => doc._fontFamily = key);
-    const editorView = RichTextMenu.Instance.TextView?.EditorView;
-    if (checkResult) {
-        return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
-    }
-    if (editorView) RichTextMenu.Instance.setFontFamily(key);
-    else Doc.UserDoc().fontFamily = key;
+      SelectionManager.Docs().map(doc => doc._fontFamily = key);
+      const editorView = RichTextMenu.Instance.TextView?.EditorView;
+      if (checkResult) {
+            return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
+      }
+      if (editorView) RichTextMenu.Instance.setFontFamily(key);
+      else Doc.UserDoc().fontFamily = key;
 });
\ No newline at end of file
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index f4f33482e..bc1cea505 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -43,6 +43,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
       @computed get presBox() { return Cast(this.lookupField("presBox"), Doc, null); }
       @computed get targetDoc() { return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc; }
 
+
       @observable isShowingVideo = false;
       @action setIsShowingVideo(shown: boolean) {
             this.isShowingVideo = shown
@@ -271,10 +272,31 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
             }
       }
 
+      @computed get recordingIsInOverlay() {
+            let isInOverlay = false
+            DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => {
+                  if (doc.slides === this.rootDoc) {
+                        isInOverlay = true
+                        return
+                  }
+            })
+            return isInOverlay
+      }
+
       @undoBatch
       @action
-      startRecording = (targetDoc: Doc, activeItem: Doc) => {
+      hideRecording = (targetDoc: Doc, activeItem: Doc) => {
+            console.log("hide recording")
+            DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => {
+                  if (doc.slides === activeItem) {
+                        Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, doc);
+                  }
+            })
+      }
 
+      @undoBatch
+      @action
+      startRecording = (targetDoc: Doc, activeItem: Doc) => {
             // Remove every recording that already exists in overlay view
             DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => {
                   if (doc.slides !== null) {
@@ -284,21 +306,24 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
             if (activeItem.recording) {
                   // if we already have an existing recording
+                  console.log("recording exists")
                   Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, Cast(activeItem.recording, Doc, null));
 
             } else {
+                  console.log("creating new recording")
                   // if we dont have any recording
                   const recording = Docs.Create.WebCamDocument("", { _width: 400, _height: 200, title: "recording", system: true, cloneFieldFilter: new List<string>(["system"]) });
+
                   // attach the recording to the slide, and attach the slide to the recording
                   recording.slides = activeItem
                   activeItem.recording = recording
+
                   // TODO: Figure out exactly where we want the video to appear
                   const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
                   recording.x = pt[0];
                   recording.y = pt[1];
                   Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, recording);
             }
-
       }
 
       @computed
@@ -375,13 +400,25 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                                 onClick={() => this.updateView(targetDoc, activeItem)}
                                                 style={{ fontWeight: 700, display: activeItem.presPinView ? "flex" : "none" }}>V</div>
                                     </Tooltip>
-                                    <Tooltip title={<><div className="dash-tooltip">{"Start recording"}</div></>}>
-                                          <div className="slideButton"
-                                                onClick={() => this.startRecording(targetDoc, activeItem)}
-                                                style={{ fontWeight: 700 }}>
-                                                <FontAwesomeIcon icon={"video"} onPointerDown={e => e.stopPropagation()} />
-                                          </div>
-                                    </Tooltip>
+
+                                    {this.recordingIsInOverlay ?
+                                          <Tooltip title={<><div className="dash-tooltip">{"Hide Recording"}</div></>}>
+                                                <div className="slideButton"
+                                                      onClick={() => this.hideRecording(targetDoc, activeItem)}
+                                                      style={{ fontWeight: 700 }}>
+                                                      <FontAwesomeIcon icon={"video-slash"} onPointerDown={e => e.stopPropagation()} />
+                                                </div>
+                                          </Tooltip> :
+                                          <Tooltip title={<><div className="dash-tooltip">{"Start recording"}</div></>}>
+                                                <div className="slideButton"
+                                                      onClick={() => this.startRecording(targetDoc, activeItem)}
+                                                      style={{ fontWeight: 700 }}>
+                                                      <FontAwesomeIcon icon={"video"} onPointerDown={e => e.stopPropagation()} />
+                                                </div>
+                                          </Tooltip>
+                                    }
+
+
                                     {this.indexInPres === 0 ? (null) : <Tooltip title={<><div className="dash-tooltip">{activeItem.groupWithUp ? "Ungroup" : "Group with up"}</div></>}>
                                           <div className="slideButton"
                                                 onClick={() => activeItem.groupWithUp = !activeItem.groupWithUp}
-- 
cgit v1.2.3-70-g09d2


From 92142bba66010a8792c00dc372228b92e151c8b3 Mon Sep 17 00:00:00 2001
From: Jenny Yu <jennyyu212@outlook.com>
Date: Wed, 4 May 2022 00:15:53 -0400
Subject: fix: removed clear previous button

---
 src/client/views/DocComponent.tsx                  | 396 ++++++++++-----------
 .../views/nodes/RecordingBox/RecordingBox.tsx      |   3 +-
 .../views/nodes/RecordingBox/RecordingView.scss    |   4 +-
 .../views/nodes/RecordingBox/RecordingView.tsx     |  15 +-
 src/client/views/nodes/trails/PresElementBox.tsx   |   2 +
 5 files changed, 208 insertions(+), 212 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 79aaf2158..103560a2a 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -17,223 +17,223 @@ import { Touchable } from './Touchable';
 
 ///  DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView)
 export interface DocComponentProps {
-    Document: Doc;
-    LayoutTemplate?: () => Opt<Doc>;
-    LayoutTemplateString?: string;
+      Document: Doc;
+      LayoutTemplate?: () => Opt<Doc>;
+      LayoutTemplateString?: string;
 }
 export function DocComponent<P extends DocComponentProps>() {
-    class Component extends Touchable<P> {
-        //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then
-        @computed get Document() { return this.props.Document; }
-        // This is the "The Document" -- it encapsulates, data, layout, and any templates
-        @computed get rootDoc() { return Cast(this.props.Document.rootDocument, Doc, null) || this.props.Document; }
-        // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info
-        @computed get layoutDoc() { return this.props.LayoutTemplateString ? this.props.Document : Doc.Layout(this.props.Document, this.props.LayoutTemplate?.()); }
-        // This is the data part of a document -- ie, the data that is constant across all views of the document
-        @computed get dataDoc() { return this.props.Document[DataSym] as Doc; }
-
-        protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
-    }
-    return Component;
+      class Component extends Touchable<P> {
+            //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then
+            @computed get Document() { return this.props.Document; }
+            // This is the "The Document" -- it encapsulates, data, layout, and any templates
+            @computed get rootDoc() { return Cast(this.props.Document.rootDocument, Doc, null) || this.props.Document; }
+            // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info
+            @computed get layoutDoc() { return this.props.LayoutTemplateString ? this.props.Document : Doc.Layout(this.props.Document, this.props.LayoutTemplate?.()); }
+            // This is the data part of a document -- ie, the data that is constant across all views of the document
+            @computed get dataDoc() { return this.props.Document[DataSym] as Doc; }
+
+            protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
+      }
+      return Component;
 }
 
 /// FieldViewBoxProps  -  a generic base class for field views that are not annotatable (e.g. InkingStroke, ColorBox)
 interface ViewBoxBaseProps {
-    Document: Doc;
-    DataDoc?: Doc;
-    ContainingCollectionDoc: Opt<Doc>;
-    DocumentView?: () => DocumentView;
-    fieldKey: string;
-    layerProvider?: (doc: Doc, assign?: boolean) => boolean;
-    isSelected: (outsideReaction?: boolean) => boolean;
-    isContentActive: () => boolean | undefined;
-    renderDepth: number;
-    rootSelected: (outsideReaction?: boolean) => boolean;
+      Document: Doc;
+      DataDoc?: Doc;
+      ContainingCollectionDoc: Opt<Doc>;
+      DocumentView?: () => DocumentView;
+      fieldKey: string;
+      layerProvider?: (doc: Doc, assign?: boolean) => boolean;
+      isSelected: (outsideReaction?: boolean) => boolean;
+      isContentActive: () => boolean | undefined;
+      renderDepth: number;
+      rootSelected: (outsideReaction?: boolean) => boolean;
 }
 export function ViewBoxBaseComponent<P extends ViewBoxBaseProps>() {
-    class Component extends Touchable<P> {
-        //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then
-        //@computed get Document(): T { return schemaCtor(this.props.Document); }
-
-        // This is the "The Document" -- it encapsulates, data, layout, and any templates
-        @computed get rootDoc() { return Cast(this.props.Document.rootDocument, Doc, null) || this.props.Document; }
-        // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info
-        @computed get layoutDoc() { return Doc.Layout(this.props.Document); }
-        // This is the data part of a document -- ie, the data that is constant across all views of the document
-        @computed get dataDoc() { return this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : this.props.Document[DataSym]; }
-
-        // key where data is stored
-        @computed get fieldKey() { return this.props.fieldKey; }
-
-        lookupField = (field: string) => ScriptCast(this.layoutDoc.lookupField)?.script.run({ self: this.layoutDoc, data: this.rootDoc, field: field, container: this.props.DocumentView?.().props.treeViewDoc ?? this.props.ContainingCollectionDoc }).result;
-
-        isContentActive = (outsideReaction?: boolean) => (
-            this.props.isContentActive?.() === false ? false :
-                (CurrentUserUtils.SelectedTool !== InkTool.None ||
-                    (this.props.isContentActive?.() || this.props.Document.forceActive ||
-                        this.props.isSelected(outsideReaction) ||
-                        this.props.rootSelected(outsideReaction)) ? true : undefined))
-        protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
-    }
-    return Component;
+      class Component extends Touchable<P> {
+            //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then
+            //@computed get Document(): T { return schemaCtor(this.props.Document); }
+
+            // This is the "The Document" -- it encapsulates, data, layout, and any templates
+            @computed get rootDoc() { return Cast(this.props.Document.rootDocument, Doc, null) || this.props.Document; }
+            // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info
+            @computed get layoutDoc() { return Doc.Layout(this.props.Document); }
+            // This is the data part of a document -- ie, the data that is constant across all views of the document
+            @computed get dataDoc() { return this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : this.props.Document[DataSym]; }
+
+            // key where data is stored
+            @computed get fieldKey() { return this.props.fieldKey; }
+
+            lookupField = (field: string) => ScriptCast(this.layoutDoc.lookupField)?.script.run({ self: this.layoutDoc, data: this.rootDoc, field: field, container: this.props.DocumentView?.().props.treeViewDoc ?? this.props.ContainingCollectionDoc }).result;
+
+            isContentActive = (outsideReaction?: boolean) => (
+                  this.props.isContentActive?.() === false ? false :
+                        (CurrentUserUtils.SelectedTool !== InkTool.None ||
+                              (this.props.isContentActive?.() || this.props.Document.forceActive ||
+                                    this.props.isSelected(outsideReaction) ||
+                                    this.props.rootSelected(outsideReaction)) ? true : undefined))
+            protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
+      }
+      return Component;
 }
 
 
 ///  DocAnnotatbleComponent -return a base class for React views of document fields that are annotatable *and* interactive when selected (e.g., pdf, image)
 export interface ViewBoxAnnotatableProps {
-    Document: Doc;
-    DataDoc?: Doc;
-    fieldKey: string;
-    filterAddDocument?: (doc: Doc[]) => boolean;  // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example)
-    layerProvider?: (doc: Doc, assign?: boolean) => boolean;
-    isContentActive: () => boolean | undefined;
-    select: (isCtrlPressed: boolean) => void;
-    whenChildContentsActiveChanged: (isActive: boolean) => void;
-    isSelected: (outsideReaction?: boolean) => boolean;
-    rootSelected: (outsideReaction?: boolean) => boolean;
-    renderDepth: number;
-    isAnnotationOverlay?: boolean;
+      Document: Doc;
+      DataDoc?: Doc;
+      fieldKey: string;
+      filterAddDocument?: (doc: Doc[]) => boolean;  // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example)
+      layerProvider?: (doc: Doc, assign?: boolean) => boolean;
+      isContentActive: () => boolean | undefined;
+      select: (isCtrlPressed: boolean) => void;
+      whenChildContentsActiveChanged: (isActive: boolean) => void;
+      isSelected: (outsideReaction?: boolean) => boolean;
+      rootSelected: (outsideReaction?: boolean) => boolean;
+      renderDepth: number;
+      isAnnotationOverlay?: boolean;
 }
 export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>() {
-    class Component extends Touchable<P> {
-        @observable _annotationKeySuffix = () => "annotations";
-
-        @observable _isAnyChildContentActive = false;
-        //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then
-        @computed get Document() { return this.props.Document; }
-        // This is the "The Document" -- it encapsulates, data, layout, and any templates
-        @computed get rootDoc() { return Cast(this.props.Document.rootDocument, Doc, null) || this.props.Document; }
-        // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info
-        @computed get layoutDoc() { return Doc.Layout(this.props.Document); }
-        // This is the data part of a document -- ie, the data that is constant across all views of the document
-        @computed get dataDoc() { return this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : this.props.Document[DataSym]; }
-
-        // key where data is stored
-        @computed get fieldKey() { return this.props.fieldKey; }
-
-        isAnyChildContentActive = () => this._isAnyChildContentActive;
-
-        lookupField = (field: string) => ScriptCast((this.layoutDoc as any).lookupField)?.script.run({ self: this.layoutDoc, data: this.rootDoc, field: field }).result;
-
-        styleFromLayoutString = (scale: number) => {
-            const style: { [key: string]: any } = {};
-            const divKeys = ["width", "height", "fontSize", "transform", "left", "background", "left", "right", "top", "bottom", "pointerEvents", "position"];
-            const replacer = (match: any, expr: string, offset: any, string: any) => { // bcz: this executes a script to convert a property expression string:  { script }  into a value
-                return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name, scale: "number" })?.script.run({ self: this.rootDoc, this: this.layoutDoc, scale }).result?.toString() ?? "";
-            };
-            divKeys.map((prop: string) => {
-                const p = (this.props as any)[prop];
-                typeof p === "string" && (style[prop] = p?.replace(/{([^.'][^}']+)}/g, replacer));
-            });
-            return style;
-        }
-
-        protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
-
-        @computed public get annotationKey() { return this.fieldKey + (this._annotationKeySuffix() ? "-" + this._annotationKeySuffix() : ""); }
-
-        @action.bound
-        removeDocument(doc: Doc | Doc[], annotationKey?: string, leavePushpin?: boolean): boolean {
-            const effectiveAcl = GetEffectiveAcl(this.dataDoc);
-            const indocs = doc instanceof Doc ? [doc] : doc;
-            const docs = indocs.filter(doc => [AclEdit, AclAdmin].includes(effectiveAcl) || GetEffectiveAcl(doc) === AclAdmin);
-            if (docs.length) {
-                setTimeout(() => docs.map(doc => { // this allows 'addDocument' to see the annotationOn field in order to create a pushin
-                    Doc.SetInPlace(doc, "isPushpin", undefined, true);
-                    doc.annotationOn === this.props.Document && Doc.SetInPlace(doc, "annotationOn", undefined, true);
-                }));
-                const targetDataDoc = this.dataDoc;
-                const value = DocListCast(targetDataDoc[annotationKey ?? this.annotationKey]);
-                const toRemove = value.filter(v => docs.includes(v));
-
-                if (toRemove.length !== 0) {
-                    const recent = Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc) as Doc;
-                    toRemove.forEach(doc => {
-                        leavePushpin && DocUtils.LeavePushpin(doc, annotationKey ?? this.annotationKey);
-                        Doc.RemoveDocFromList(targetDataDoc, annotationKey ?? this.annotationKey, doc);
-                        doc.context = undefined;
-                        if (recent) {
-                            Doc.RemoveDocFromList(recent, "data", doc);
-                            Doc.AddDocToList(recent, "data", doc, undefined, true, true);
-                        }
-                    });
-                    this.isAnyChildContentActive() && this.props.select(false);
-                    return true;
-                }
+      class Component extends Touchable<P> {
+            @observable _annotationKeySuffix = () => "annotations";
+
+            @observable _isAnyChildContentActive = false;
+            //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then
+            @computed get Document() { return this.props.Document; }
+            // This is the "The Document" -- it encapsulates, data, layout, and any templates
+            @computed get rootDoc() { return Cast(this.props.Document.rootDocument, Doc, null) || this.props.Document; }
+            // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info
+            @computed get layoutDoc() { return Doc.Layout(this.props.Document); }
+            // This is the data part of a document -- ie, the data that is constant across all views of the document
+            @computed get dataDoc() { return this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : this.props.Document[DataSym]; }
+
+            // key where data is stored
+            @computed get fieldKey() { return this.props.fieldKey; }
+
+            isAnyChildContentActive = () => this._isAnyChildContentActive;
+
+            lookupField = (field: string) => ScriptCast((this.layoutDoc as any).lookupField)?.script.run({ self: this.layoutDoc, data: this.rootDoc, field: field }).result;
+
+            styleFromLayoutString = (scale: number) => {
+                  const style: { [key: string]: any } = {};
+                  const divKeys = ["width", "height", "fontSize", "transform", "left", "background", "left", "right", "top", "bottom", "pointerEvents", "position"];
+                  const replacer = (match: any, expr: string, offset: any, string: any) => { // bcz: this executes a script to convert a property expression string:  { script }  into a value
+                        return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name, scale: "number" })?.script.run({ self: this.rootDoc, this: this.layoutDoc, scale }).result?.toString() ?? "";
+                  };
+                  divKeys.map((prop: string) => {
+                        const p = (this.props as any)[prop];
+                        typeof p === "string" && (style[prop] = p?.replace(/{([^.'][^}']+)}/g, replacer));
+                  });
+                  return style;
             }
 
-            return false;
-        }
-        // this is called with the document that was dragged and the collection to move it into.
-        // if the target collection is the same as this collection, then the move will be allowed.
-        // otherwise, the document being moved must be able to be removed from its container before
-        // moving it into the target.
-        @action.bound
-        moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[], annotationKey?: string) => boolean, annotationKey?: string): boolean => {
-            if (Doc.AreProtosEqual(this.props.Document, targetCollection)) {
-                return true;
-            }
-            const first = doc instanceof Doc ? doc : doc[0];
-            if (!first?._stayInCollection && addDocument !== returnFalse) {
-                return UndoManager.RunInTempBatch(() => this.removeDocument(doc, annotationKey, true) && addDocument(doc, annotationKey));
+            protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
+
+            @computed public get annotationKey() { return this.fieldKey + (this._annotationKeySuffix() ? "-" + this._annotationKeySuffix() : ""); }
+
+            @action.bound
+            removeDocument(doc: Doc | Doc[], annotationKey?: string, leavePushpin?: boolean): boolean {
+                  const effectiveAcl = GetEffectiveAcl(this.dataDoc);
+                  const indocs = doc instanceof Doc ? [doc] : doc;
+                  const docs = indocs.filter(doc => [AclEdit, AclAdmin].includes(effectiveAcl) || GetEffectiveAcl(doc) === AclAdmin);
+                  if (docs.length) {
+                        setTimeout(() => docs.map(doc => { // this allows 'addDocument' to see the annotationOn field in order to create a pushin
+                              Doc.SetInPlace(doc, "isPushpin", undefined, true);
+                              doc.annotationOn === this.props.Document && Doc.SetInPlace(doc, "annotationOn", undefined, true);
+                        }));
+                        const targetDataDoc = this.dataDoc;
+                        const value = DocListCast(targetDataDoc[annotationKey ?? this.annotationKey]);
+                        const toRemove = value.filter(v => docs.includes(v));
+
+                        if (toRemove.length !== 0) {
+                              const recent = Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc) as Doc;
+                              toRemove.forEach(doc => {
+                                    leavePushpin && DocUtils.LeavePushpin(doc, annotationKey ?? this.annotationKey);
+                                    Doc.RemoveDocFromList(targetDataDoc, annotationKey ?? this.annotationKey, doc);
+                                    doc.context = undefined;
+                                    if (recent) {
+                                          Doc.RemoveDocFromList(recent, "data", doc);
+                                          Doc.AddDocToList(recent, "data", doc, undefined, true, true);
+                                    }
+                              });
+                              this.isAnyChildContentActive() && this.props.select(false);
+                              return true;
+                        }
+                  }
+
+                  return false;
             }
-            return false;
-        }
-        @action.bound
-        addDocument = (doc: Doc | Doc[], annotationKey?: string): boolean => {
-            const docs = doc instanceof Doc ? [doc] : doc;
-            if (this.props.filterAddDocument?.(docs) === false ||
-                docs.find(doc => Doc.AreProtosEqual(doc, this.props.Document) && Doc.LayoutField(doc) === Doc.LayoutField(this.props.Document))) {
-                return false;
+            // this is called with the document that was dragged and the collection to move it into.
+            // if the target collection is the same as this collection, then the move will be allowed.
+            // otherwise, the document being moved must be able to be removed from its container before
+            // moving it into the target.
+            @action.bound
+            moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[], annotationKey?: string) => boolean, annotationKey?: string): boolean => {
+                  if (Doc.AreProtosEqual(this.props.Document, targetCollection)) {
+                        return true;
+                  }
+                  const first = doc instanceof Doc ? doc : doc[0];
+                  if (!first?._stayInCollection && addDocument !== returnFalse) {
+                        return UndoManager.RunInTempBatch(() => this.removeDocument(doc, annotationKey, true) && addDocument(doc, annotationKey));
+                  }
+                  return false;
             }
-            const targetDataDoc = this.props.Document[DataSym];
-            const docList = DocListCast(targetDataDoc[annotationKey ?? this.annotationKey]);
-            const added = docs.filter(d => !docList.includes(d));
-            const effectiveAcl = GetEffectiveAcl(this.dataDoc);
-
-            if (added.length) {
-                if (effectiveAcl === AclPrivate || effectiveAcl === AclReadonly) {
-                    return false;
-                }
-                else {
-                    if (this.props.Document[AclSym] && Object.keys(this.props.Document[AclSym]).length) {
-                        added.forEach(d => {
-                            for (const [key, value] of Object.entries(this.props.Document[AclSym])) {
-                                if (d.author === denormalizeEmail(key.substring(4)) && !d.aliasOf) distributeAcls(key, SharingPermissions.Admin, d);
-                            }
-                        });
-                    }
-
-                    if (effectiveAcl === AclAugment) {
-                        added.map(doc => {
-                            if ([AclAdmin, AclEdit].includes(GetEffectiveAcl(doc))) inheritParentAcls(CurrentUserUtils.ActiveDashboard, doc);
-                            doc.context = this.props.Document;
-                            if (annotationKey ?? this._annotationKeySuffix()) Doc.GetProto(doc).annotationOn = this.props.Document;
-                            this.props.layerProvider?.(doc, true);
-                            Doc.AddDocToList(targetDataDoc, annotationKey ?? this.annotationKey, doc);
-                        });
-                    }
-                    else {
-                        added.filter(doc => [AclAdmin, AclEdit].includes(GetEffectiveAcl(doc))).map(doc => {  // only make a pushpin if we have acl's to edit the document
-                            this.props.layerProvider?.(doc, true);
-                            //DocUtils.LeavePushpin(doc);
-                            doc._stayInCollection = undefined;
-                            doc.context = this.props.Document;
-                            if (annotationKey ?? this._annotationKeySuffix()) Doc.GetProto(doc).annotationOn = this.props.Document;
-
-                            inheritParentAcls(CurrentUserUtils.ActiveDashboard, doc);
-                        });
-                        const annoDocs = targetDataDoc[annotationKey ?? this.annotationKey] as List<Doc>;
-                        if (annoDocs instanceof List) annoDocs.push(...added);
-                        else targetDataDoc[annotationKey ?? this.annotationKey] = new List<Doc>(added);
-                        targetDataDoc[(annotationKey ?? this.annotationKey) + "-lastModified"] = new DateField(new Date(Date.now()));
-                    }
-                }
+            @action.bound
+            addDocument = (doc: Doc | Doc[], annotationKey?: string): boolean => {
+                  const docs = doc instanceof Doc ? [doc] : doc;
+                  if (this.props.filterAddDocument?.(docs) === false ||
+                        docs.find(doc => Doc.AreProtosEqual(doc, this.props.Document) && Doc.LayoutField(doc) === Doc.LayoutField(this.props.Document))) {
+                        return false;
+                  }
+                  const targetDataDoc = this.props.Document[DataSym];
+                  const docList = DocListCast(targetDataDoc[annotationKey ?? this.annotationKey]);
+                  const added = docs.filter(d => !docList.includes(d));
+                  const effectiveAcl = GetEffectiveAcl(this.dataDoc);
+
+                  if (added.length) {
+                        if (effectiveAcl === AclPrivate || effectiveAcl === AclReadonly) {
+                              return false;
+                        }
+                        else {
+                              if (this.props.Document[AclSym] && Object.keys(this.props.Document[AclSym]).length) {
+                                    added.forEach(d => {
+                                          for (const [key, value] of Object.entries(this.props.Document[AclSym])) {
+                                                if (d.author === denormalizeEmail(key.substring(4)) && !d.aliasOf) distributeAcls(key, SharingPermissions.Admin, d);
+                                          }
+                                    });
+                              }
+
+                              if (effectiveAcl === AclAugment) {
+                                    added.map(doc => {
+                                          if ([AclAdmin, AclEdit].includes(GetEffectiveAcl(doc))) inheritParentAcls(CurrentUserUtils.ActiveDashboard, doc);
+                                          doc.context = this.props.Document;
+                                          if (annotationKey ?? this._annotationKeySuffix()) Doc.GetProto(doc).annotationOn = this.props.Document;
+                                          this.props.layerProvider?.(doc, true);
+                                          Doc.AddDocToList(targetDataDoc, annotationKey ?? this.annotationKey, doc);
+                                    });
+                              }
+                              else {
+                                    added.filter(doc => [AclAdmin, AclEdit].includes(GetEffectiveAcl(doc))).map(doc => {  // only make a pushpin if we have acl's to edit the document
+                                          this.props.layerProvider?.(doc, true);
+                                          //DocUtils.LeavePushpin(doc);
+                                          doc._stayInCollection = undefined;
+                                          doc.context = this.props.Document;
+                                          if (annotationKey ?? this._annotationKeySuffix()) Doc.GetProto(doc).annotationOn = this.props.Document;
+
+                                          inheritParentAcls(CurrentUserUtils.ActiveDashboard, doc);
+                                    });
+                                    const annoDocs = targetDataDoc[annotationKey ?? this.annotationKey] as List<Doc>;
+                                    if (annoDocs instanceof List) annoDocs.push(...added);
+                                    else targetDataDoc[annotationKey ?? this.annotationKey] = new List<Doc>(added);
+                                    targetDataDoc[(annotationKey ?? this.annotationKey) + "-lastModified"] = new DateField(new Date(Date.now()));
+                              }
+                        }
+                  }
+                  return true;
             }
-            return true;
-        }
 
-        whenChildContentsActiveChanged = action((isActive: boolean) => this.props.whenChildContentsActiveChanged(this._isAnyChildContentActive = isActive));
-    }
-    return Component;
+            whenChildContentsActiveChanged = action((isActive: boolean) => this.props.whenChildContentsActiveChanged(this._isAnyChildContentActive = isActive));
+      }
+      return Component;
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 86358e838..a49cbbea5 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -38,7 +38,8 @@ export class RecordingBox extends ViewBoxBaseComponent() {
             console.log(this.videoDuration)
             this.dataDoc[this.fieldKey + "-duration"] = this.videoDuration;
 
-            this.layoutDoc.layout = VideoBox.LayoutString(this.fieldKey);
+            // this.layoutDoc.layout = VideoBox.LayoutString(this.fieldKey);
+            this.dataDoc.layout = VideoBox.LayoutString(this.fieldKey);
             // this.dataDoc.nativeWidth = this.dataDoc.nativeHeight = undefined;
             // this.layoutDoc._fitWidth = undefined;
             this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.agnostic.client);
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.scss b/src/client/views/nodes/RecordingBox/RecordingView.scss
index 1fea231b7..0c153c9c8 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.scss
+++ b/src/client/views/nodes/RecordingBox/RecordingView.scss
@@ -1,7 +1,7 @@
 video {
       flex: 100%;
       width: 100%;
-      min-height: 400px;
+      // min-height: 400px;
       height: auto;
       display: block;
       background-color: black;
@@ -42,7 +42,7 @@ button {
       padding: 14px;
       width: 100%;
       max-width: 500px;
-      max-height: 20%;
+      // max-height: 20%;
       flex-wrap: wrap;
       background: rgba(255, 255, 255, 0.25);
       box-shadow: 0 8px 32px 0 rgba(255, 255, 255, 0.1);
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index a2a08f5b8..e5f6deca2 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -48,13 +48,8 @@ export function RecordingView(props: IRecordingViewProps) {
 
 
       const DEFAULT_MEDIA_CONSTRAINTS = {
-            // video: true,
-            // audio: true
-            video: {
-                  width: 1280,
-                  height: 720,
-            },
-            // audio: true,
+            video: true,
+            audio: true,
             // audio: {
             //       echoCancellation: true,
             //       noiseSuppression: true,
@@ -84,8 +79,6 @@ export function RecordingView(props: IRecordingViewProps) {
                               }
                         })
 
-                  //     this.dataDoc[this.fieldKey + "-duration"] = (new Date().getTime() - this.recordingStart!) / 1000;
-
             }
 
 
@@ -275,9 +268,9 @@ export function RecordingView(props: IRecordingViewProps) {
                                     {!recording && videos.length > 0 ?
 
                                           <div className="video-edit-wrapper">
-                                                <IconContext.Provider value={{ color: "grey", className: "video-edit-buttons" }}>
+                                                {/* <IconContext.Provider value={{ color: "grey", className: "video-edit-buttons" }}>
                                                       <MdBackspace onClick={clearPrevious} />
-                                                </IconContext.Provider>
+                                                </IconContext.Provider> */}
                                                 <IconContext.Provider value={{ color: "#cc1c08", className: "video-edit-buttons" }}>
                                                       <FaCheckCircle onClick={stop} />
                                                 </IconContext.Provider>
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index 23c80253c..c13f469cc 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -308,6 +308,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
             if (activeItem.recording) {
                   // if we already have an existing recording
                   console.log("recording exists")
+                  console.log(activeItem.recording)
+                  console.log(Cast(activeItem.recording, Doc, null))
                   Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, Cast(activeItem.recording, Doc, null));
 
             } else {
-- 
cgit v1.2.3-70-g09d2


From 1eb2c362b020b3cbe446bbc1585108129fda6977 Mon Sep 17 00:00:00 2001
From: Michael Foiani <sotech117@michaels-mbp-3.devices.brown.edu>
Date: Wed, 4 May 2022 01:11:54 -0400
Subject: Get storing pres data working, but is choppy due to mobx usage.

---
 src/client/apis/recording/recordingApi.ts          | 300 --------------------
 src/client/util/RecordingApi.ts                    | 303 +++++++++++++++++++++
 src/client/views/Main.tsx                          |   2 +
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   5 +-
 .../views/nodes/RecordingBox/RecordingBox.tsx      |  14 +-
 .../views/nodes/RecordingBox/RecordingView.tsx     |  26 +-
 src/client/views/nodes/VideoBox.tsx                |  14 +
 7 files changed, 348 insertions(+), 316 deletions(-)
 delete mode 100644 src/client/apis/recording/recordingApi.ts
 create mode 100644 src/client/util/RecordingApi.ts

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/client/apis/recording/recordingApi.ts b/src/client/apis/recording/recordingApi.ts
deleted file mode 100644
index b57e675b7..000000000
--- a/src/client/apis/recording/recordingApi.ts
+++ /dev/null
@@ -1,300 +0,0 @@
-import { CollectionFreeFormView } from "../../views/collections/collectionFreeForm";
-import React, { useState } from "react";
-import { IReactionDisposer, observable, reaction } from "mobx";
-import { NumCast } from "../../../fields/Types";
-
-type Movement = {
-    time: number,
-    panX: number,
-    panY: number,
-}
-
-type Presentation = {
-    movements: Array<Movement>
-    meta: Object,
-    startDate: Date | null,
-}
-
-export class RecordingApi {
-
-    private static NULL_PRESENTATION: Presentation = {
-        movements: [],
-        meta: {},
-        startDate: null,
-    }
-
-    // instance variables
-    private currentPresentation: Presentation;
-    private isRecording: boolean;
-    private absoluteStart: number;
-
-
-    // create static instance and getter for global use
-    @observable static _instance: RecordingApi;
-    public static get instance(): RecordingApi { return RecordingApi._instance }
-    public constructor() {
-        // init the global instance
-        RecordingApi._instance = this;
-
-        // init the instance variables
-        this.currentPresentation = RecordingApi.NULL_PRESENTATION
-        this.isRecording = false;
-        this.absoluteStart = -1;
-
-        // used for tracking movements in the view frame
-        this.disposeFunc = null;
-
-        // for now, set playFFView
-        this.playFFView = null;
-        this.timers = null;
-    }
-
-    // little helper :)
-    private get isInitPresenation(): boolean {
-        return this.currentPresentation.startDate === null
-    }
-
-    public start = (view: CollectionFreeFormView, meta?: Object): Error | undefined => {
-        // check if already init a presentation
-        if (!this.isInitPresenation) {
-            console.error('[recordingApi.ts] start() failed: current presentation data exists. please call clear() first.')
-            return new Error('[recordingApi.ts] start()')
-        }
-
-        // (1a) get start date for presenation
-        const startDate = new Date()
-        // (1b) set start timestamp to absolute timestamp
-        this.absoluteStart = startDate.getTime()
-
-        // (2) assign meta content if it exists
-        this.currentPresentation.meta = meta || {}
-        // (3) assign start date to currentPresenation
-        this.currentPresentation.startDate = startDate
-        // (4) set isRecording true to allow trackMovements
-        this.isRecording = true
-    }
-
-    public clear = (): Error | undefined => {
-        // TODO: maybe archive the data?
-        if (this.isRecording) {
-            console.error('[recordingApi.ts] clear() failed: currently recording presentation. call pause() or finish() first')
-            return new Error('[recordingApi.ts] clear()')
-        }
-
-        // clear presenation data
-        this.currentPresentation = RecordingApi.NULL_PRESENTATION
-        // clear isRecording
-        this.isRecording = false
-        // clear absoluteStart
-        this.absoluteStart = -1
-
-        // clear the disposeFunc
-        this.disposeFunc = null
-    }
-
-    public pause = (): Error | undefined => {
-        if (this.currentPresentation.startDate === null) {
-            console.error('[recordingApi.ts] pause() failed: no presentation started. try calling init() first')
-            return new Error('[recordingApi.ts] pause(): no presenation')
-        }
-        // don't allow track movments
-        this.isRecording = false
-
-        // set relativeStart to the pausedTimestamp
-        const timestamp = new Date().getTime()
-        this.absoluteStart = timestamp
-    }
-
-    public resume = () => {
-        const timestamp = new Date().getTime()
-        const startTimestamp = this.currentPresentation.startDate?.getTime()
-        if (!startTimestamp) {
-            console.error('[recordingApi.ts] resume() failed: no presentation data. try calling start() first')
-            return new Error('[recordingApi.ts] pause()')
-        }
-
-        // update absoluteStart to bridge the paused time
-        const absoluteTimePaused = timestamp - this.absoluteStart
-        this.absoluteStart = absoluteTimePaused
-    }
-
-    public finish = (): Error | Presentation => {
-        if (this.isInitPresenation) {
-            console.error('[recordingApi.ts] finish() failed: no presentation data. try calling start() first')
-            return new Error('[recordingApi.ts] finish()')
-        }
-
-        // return a copy of the the presentation data
-        return { ...this.currentPresentation }
-    }
-
-    private trackMovements = (panX: number, panY: number): Error | undefined => {
-        // ensure we are recording
-        if (!this.isRecording) {
-            console.error('[recordingApi.ts] pause() failed: recording is paused()')
-            return new Error('[recordingApi.ts] pause()')
-        }
-
-        // get the relative time
-        const timestamp = new Date().getTime()
-        const relativeTime = timestamp - this.absoluteStart
-
-        // make new movement struct
-        const movement: Movement = { time: relativeTime, panX, panY }
-        
-        // add that movement to the current presentation data's movement array
-        this.currentPresentation.movements.push(movement)
-    }
-
-    // instance variable for the FFView
-    private disposeFunc: IReactionDisposer | null;
-    
-    // set the FFView that will be used in a reaction to track the movements
-    public setRecordingFFView = (view: CollectionFreeFormView): void => {
-        // set the view to the current view
-        if (view === null) return;
-        
-        //this.recordingFFView = view;
-        // set the reaction to track the movements
-        this.disposeFunc = reaction(
-            () => ({ x: NumCast(view.Document.panX, -1), y: NumCast(view.Document.panY, -1) }),
-            (res) => (res.x !== -1 && res.y !== -1) && this.trackMovements(res.x, res.y)
-        )
-
-        // for now, set the most recent recordingFFView to the playFFView
-        this.playFFView = view;
-    }
-
-    // call on dispose function to stop tracking movements
-    public removeRecordingFFView = (): void => {
-        this.disposeFunc?.();
-        this.disposeFunc = null;
-    }
-
-    // TODO: extract this into different class with pause and resume recording
-    private playFFView: CollectionFreeFormView | null;
-    private timers: Timer[] | null;
-
-    public followMovements = (presentation: Presentation): undefined | Error => {
-        if (presentation.startDate === null || this.playFFView === null) {
-            return new Error('[recordingApi.ts] followMovements() failed: no presentation data or no view')
-        }
-
-        const document = this.playFFView.Document
-        const { movements } = presentation
-        this.timers = movements.map(movement => {
-            const { panX, panY, time } = movement
-            return new Timer(() => {
-                document._panX = panX;
-                document._panY = panY;
-                // TODO: consider cleaning this array to null or some state
-            }, time)
-        })
-    }
-
-    public pauseMovements = (): undefined | Error => {
-        if (this.playFFView === null) {
-            return new Error('[recordingApi.ts] pauseMovements() failed: no view')
-        }
-        // TODO: set userdoc presentMode to browsing
-        this.timers?.forEach(timer => timer.pause())
-    }
-
-    public resumeMovements = (): undefined | Error => {
-        if (this.playFFView === null) {
-            return new Error('[recordingApi.ts] resumeMovements() failed: no view')
-        }
-        this.timers?.forEach(timer => timer.resume())
-    }
-
-    // public followMovements = (presentation: Presentation): undefined | Error => {
-    //     if (presentation.startDate === null || this.playFFView === null) {
-    //         return new Error('[recordingApi.ts] followMovements() failed: no presentation data or no view')
-    //     }
-
-    //     const document = this.playFFView.Document
-    //     const { movements } = presentation
-    //     movements.forEach(movement => {
-    //         const { panX, panY, time } = movement
-    //         // set the pan to what was stored
-    //         setTimeout(() => {
-    //             document._panX = panX;
-    //             document._panY = panY;
-    //         }, time)
-    //     })
-    // }
-    // Unfinished code for tracing multiple free form views
-    // export let pres: Map<CollectionFreeFormView, IReactionDisposer> = new Map()
-
-    // export function AddRecordingFFView(ffView: CollectionFreeFormView): void {
-    //     pres.set(ffView,
-    //          reaction(() => ({ x: ffView.panX, y: ffView.panY }),
-    //     (pt) => RecordingApi.trackMovements(ffView, pt.x, pt.y)))
-    //     )
-    // }
-
-    // export function RemoveRecordingFFView(ffView: CollectionFreeFormView): void {
-    //     const disposer = pres.get(ffView);
-    //     disposer?.();
-    //     pres.delete(ffView)
-    // }
-}
-
-/** Represents the `setTimeout` with an ability to perform pause/resume actions
- * citation: https://stackoverflow.com/questions/3969475/javascript-pause-settimeout
- */
-export class Timer {
-    private _start: Date;
-    private _remaining: number;
-    private _durationTimeoutId?: NodeJS.Timeout;
-    private _callback: (...args: any[]) => void;
-    private _done = false;
-    get done () {
-        return this._done;
-    }
-
-    public constructor(callback: (...args: any[]) => void, ms = 0) {
-        this._callback = () => {
-            callback();
-            this._done = true;
-        };
-        this._remaining = ms;
-        this.resume();
-    }
-
-    /** pauses the timer */
-    public pause(): Timer {
-        if (this._durationTimeoutId && !this._done) {
-            this._clearTimeoutRef();
-            this._remaining -= new Date().getTime() - this._start.getTime();
-        }
-        return this;
-    }
-
-    /** resumes the timer */
-    public resume(): Timer {
-        if (!this._durationTimeoutId && !this._done) {
-            this._start = new Date;
-            this._durationTimeoutId = setTimeout(this._callback, this._remaining);
-        }
-        return this;
-    }
-
-    /** 
-     * clears the timeout and marks it as done. 
-     * 
-     * After called, the timeout will not resume
-     */
-    public clearTimeout() {
-        this._clearTimeoutRef();
-        this._done = true;
-    }
-
-    private _clearTimeoutRef() {
-        if (this._durationTimeoutId) {
-            clearTimeout(this._durationTimeoutId);
-            this._durationTimeoutId = undefined;
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/src/client/util/RecordingApi.ts b/src/client/util/RecordingApi.ts
new file mode 100644
index 000000000..c4f76282c
--- /dev/null
+++ b/src/client/util/RecordingApi.ts
@@ -0,0 +1,303 @@
+import { CollectionFreeFormView } from "../views/collections/collectionFreeForm";
+import { IReactionDisposer, observable, reaction } from "mobx";
+import { NumCast } from "../../fields/Types";
+
+type Movement = {
+    time: number,
+    panX: number,
+    panY: number,
+}
+
+type Presentation = {
+    movements: Array<Movement>
+    meta: Object,
+    startDate: Date | null,
+}
+
+export class RecordingApi {
+
+    private static NULL_PRESENTATION: Presentation = {
+        movements: [],
+        meta: {},
+        startDate: null,
+    }
+
+    // instance variables
+    private currentPresentation: Presentation;
+    private isRecording: boolean;
+    private absoluteStart: number;
+
+
+    // create static instance and getter for global use
+    @observable static _instance: RecordingApi;
+    public static get Instance(): RecordingApi { return RecordingApi._instance }
+    public constructor() {
+        // init the global instance
+        RecordingApi._instance = this;
+
+        // init the instance variables
+        this.currentPresentation = RecordingApi.NULL_PRESENTATION
+        this.isRecording = false;
+        this.absoluteStart = -1;
+
+        // used for tracking movements in the view frame
+        this.disposeFunc = null;
+
+        // for now, set playFFView
+        this.playFFView = null;
+        this.timers = null;
+    }
+
+    // little helper :)
+    private get isInitPresenation(): boolean {
+        return this.currentPresentation.startDate === null
+    }
+
+    public start = (meta?: Object): Error | undefined => {
+        // check if already init a presentation
+        if (!this.isInitPresenation) {
+            console.error('[recordingApi.ts] start() failed: current presentation data exists. please call clear() first.')
+            return new Error('[recordingApi.ts] start()')
+        }
+
+        // (1a) get start date for presenation
+        const startDate = new Date()
+        // (1b) set start timestamp to absolute timestamp
+        this.absoluteStart = startDate.getTime()
+
+        // (2) assign meta content if it exists
+        this.currentPresentation.meta = meta || {}
+        // (3) assign start date to currentPresenation
+        this.currentPresentation.startDate = startDate
+        // (4) set isRecording true to allow trackMovements
+        this.isRecording = true
+    }
+
+    public clear = (): Error | Presentation => {
+        // TODO: maybe archive the data?
+        if (this.isRecording) {
+            console.error('[recordingApi.ts] clear() failed: currently recording presentation. call pause() first')
+            return new Error('[recordingApi.ts] clear()')
+        }
+
+        const presCopy = { ...this.currentPresentation }
+
+        // clear presenation data
+        this.currentPresentation = RecordingApi.NULL_PRESENTATION
+        // clear isRecording
+        this.isRecording = false
+        // clear absoluteStart
+        this.absoluteStart = -1
+        // clear the disposeFunc
+        this.disposeFunc = null
+
+        return presCopy;
+    }
+
+    public pause = (): Error | undefined => {
+        if (this.currentPresentation.startDate === null) {
+            console.error('[recordingApi.ts] pause() failed: no presentation started. try calling init() first')
+            return new Error('[recordingApi.ts] pause(): no presenation')
+        }
+        // don't allow track movments
+        this.isRecording = false
+
+        // set relativeStart to the pausedTimestamp
+        const timestamp = new Date().getTime()
+        this.absoluteStart = timestamp
+    }
+
+    public resume = () => {
+        const timestamp = new Date().getTime()
+        const startTimestamp = this.currentPresentation.startDate?.getTime()
+        if (!startTimestamp) {
+            console.error('[recordingApi.ts] resume() failed: no presentation data. try calling start() first')
+            return new Error('[recordingApi.ts] pause()')
+        }
+
+        // update absoluteStart to bridge the paused time
+        const absoluteTimePaused = timestamp - this.absoluteStart
+        this.absoluteStart = absoluteTimePaused
+    }
+
+    // public finish = (): Error | Presentation => {
+    //     if (this.isInitPresenation) {
+    //         console.error('[recordingApi.ts] finish() failed: no presentation data. try calling start() first')
+    //         return new Error('[recordingApi.ts] finish()')
+    //     }
+
+    //     // return a copy of the the presentation data
+    //     return { ...this.currentPresentation }
+    // }
+
+    private trackMovements = (panX: number, panY: number): Error | undefined => {
+        // ensure we are recording
+        if (!this.isRecording) {
+            console.error('[recordingApi.ts] pause() failed: recording is paused()')
+            return new Error('[recordingApi.ts] pause()')
+        }
+
+        // get the relative time
+        const timestamp = new Date().getTime()
+        const relativeTime = timestamp - this.absoluteStart
+
+        // make new movement struct
+        const movement: Movement = { time: relativeTime, panX, panY }
+        
+        // add that movement to the current presentation data's movement array
+        this.currentPresentation.movements.push(movement)
+    }
+
+    // instance variable for the FFView
+    private disposeFunc: IReactionDisposer | null;
+    
+    // set the FFView that will be used in a reaction to track the movements
+    public setRecordingFFView = (view: CollectionFreeFormView): void => {
+        // set the view to the current view
+        if (view === null || view === this.playFFView) return;
+        
+        //this.recordingFFView = view;
+        // set the reaction to track the movements
+        this.disposeFunc = reaction(
+            () => ({ x: NumCast(view.Document.panX, -1), y: NumCast(view.Document.panY, -1) }),
+            (res) => (res.x !== -1 && res.y !== -1) && this.trackMovements(res.x, res.y)
+        )
+
+        // for now, set the most recent recordingFFView to the playFFView
+        this.playFFView = view;
+    }
+
+    // call on dispose function to stop tracking movements
+    public removeRecordingFFView = (): void => {
+        this.disposeFunc?.();
+        this.disposeFunc = null;
+    }
+
+    // TODO: extract this into different class with pause and resume recording
+    private playFFView: CollectionFreeFormView | null;
+    private timers: Timer[] | null;
+
+    // public followMovements = (presentation: Presentation): undefined | Error => {
+    //     console.log(presentation)
+    //     if (presentation.startDate === null || this.playFFView === null) {
+    //         return new Error('[recordingApi.ts] followMovements() failed: no presentation data or no view')
+    //     }
+
+    //     const document = this.playFFView.Document
+    //     const { movements } = presentation
+    //     this.timers = movements.map(movement => {
+    //         const { panX, panY, time } = movement
+    //         return new Timer(() => {
+    //             document._panX = panX;
+    //             document._panY = panY;
+    //             // TODO: consider cleaning this array to null or some state
+    //         }, time)
+    //     })
+    // }
+
+    public pauseMovements = (): undefined | Error => {
+        if (this.playFFView === null) {
+            return new Error('[recordingApi.ts] pauseMovements() failed: no view')
+        }
+        // TODO: set userdoc presentMode to browsing
+        this.timers?.forEach(timer => timer.pause())
+    }
+
+    public resumeMovements = (): undefined | Error => {
+        if (this.playFFView === null) {
+            return new Error('[recordingApi.ts] resumeMovements() failed: no view')
+        }
+        this.timers?.forEach(timer => timer.resume())
+    }
+
+    public followMovements = (presentation: Presentation): undefined | Error => {
+        if (presentation.startDate === null || this.playFFView === null) {
+            return new Error('[recordingApi.ts] followMovements() failed: no presentation data or no view')
+        }
+
+        const document = this.playFFView.Document
+        const { movements } = presentation
+        movements.forEach(movement => {
+            const { panX, panY, time } = movement
+            // set the pan to what was stored
+            setTimeout(() => {
+                document._panX = panX;
+                document._panY = panY;
+            }, time)
+        })
+    }
+    // Unfinished code for tracing multiple free form views
+    // export let pres: Map<CollectionFreeFormView, IReactionDisposer> = new Map()
+
+    // export function AddRecordingFFView(ffView: CollectionFreeFormView): void {
+    //     pres.set(ffView,
+    //          reaction(() => ({ x: ffView.panX, y: ffView.panY }),
+    //     (pt) => RecordingApi.trackMovements(ffView, pt.x, pt.y)))
+    //     )
+    // }
+
+    // export function RemoveRecordingFFView(ffView: CollectionFreeFormView): void {
+    //     const disposer = pres.get(ffView);
+    //     disposer?.();
+    //     pres.delete(ffView)
+    // }
+}
+
+/** Represents the `setTimeout` with an ability to perform pause/resume actions
+ * citation: https://stackoverflow.com/questions/3969475/javascript-pause-settimeout
+ */
+export class Timer {
+    private _start: Date;
+    private _remaining: number;
+    private _durationTimeoutId?: NodeJS.Timeout;
+    private _callback: (...args: any[]) => void;
+    private _done = false;
+    get done () {
+        return this._done;
+    }
+
+    public constructor(callback: (...args: any[]) => void, ms = 0) {
+        this._callback = () => {
+            callback();
+            this._done = true;
+        };
+        this._remaining = ms;
+        this.resume();
+    }
+
+    /** pauses the timer */
+    public pause(): Timer {
+        if (this._durationTimeoutId && !this._done) {
+            this._clearTimeoutRef();
+            this._remaining -= new Date().getTime() - this._start.getTime();
+        }
+        return this;
+    }
+
+    /** resumes the timer */
+    public resume(): Timer {
+        if (!this._durationTimeoutId && !this._done) {
+            this._start = new Date;
+            this._durationTimeoutId = setTimeout(this._callback, this._remaining);
+        }
+        return this;
+    }
+
+    /** 
+     * clears the timeout and marks it as done. 
+     * 
+     * After called, the timeout will not resume
+     */
+    public clearTimeout() {
+        this._clearTimeoutRef();
+        this._done = true;
+    }
+
+    private _clearTimeoutRef() {
+        if (this._durationTimeoutId) {
+            clearTimeout(this._durationTimeoutId);
+            this._durationTimeoutId = undefined;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 8560ccb29..517fe097c 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -8,6 +8,7 @@ import { AssignAllExtensions } from "../../extensions/General/Extensions";
 import { Docs } from "../documents/Documents";
 import { CurrentUserUtils } from "../util/CurrentUserUtils";
 import { LinkManager } from "../util/LinkManager";
+import { RecordingApi } from "../util/RecordingApi";
 import { CollectionView } from "./collections/CollectionView";
 import { MainView } from "./MainView";
 
@@ -36,5 +37,6 @@ AssignAllExtensions();
     const expires = "expires=" + d.toUTCString();
     document.cookie = `loadtime=${loading};${expires};path=/`;
     new LinkManager();
+    new RecordingApi;
     ReactDOM.render(<MainView />, document.getElementById('root'));
 })();
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 35bd9cf79..f74e526b6 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -54,7 +54,7 @@ import "./CollectionFreeFormView.scss";
 import { MarqueeView } from "./MarqueeView";
 import React = require("react");
 import e = require("connect-flash");
-import { RecordingApi } from "../../../apis/recording/RecordingApi";
+import { RecordingApi } from "../../../util/RecordingApi";
 
 export const panZoomSchema = createSchema({
     _panX: "number",
@@ -965,6 +965,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     @action
     setPan(panX: number, panY: number, panTime: number = 0, clamp: boolean = false) {
+        // set the current FFview to the tab being panned.
+        RecordingApi.Instance.setRecordingFFView(this)
+
         if (!this.isAnnotationOverlay && clamp) {
             // this section wraps the pan position, horizontally and/or vertically whenever the content is panned out of the viewing bounds
             const docs = this.childLayoutPairs.map(pair => pair.layout).filter(doc => doc instanceof Doc);
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 86358e838..1b17476f7 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -1,7 +1,7 @@
 import { action, observable } from "mobx";
 import { observer } from "mobx-react";
 import * as React from "react";
-import { AudioField, VideoField } from "../../../../fields/URLField";
+import { VideoField } from "../../../../fields/URLField";
 import { Upload } from "../../../../server/SharedMediaTypes";
 import { ViewBoxBaseComponent } from "../../DocComponent";
 import { FieldView } from "../FieldView";
@@ -9,6 +9,8 @@ import { VideoBox } from "../VideoBox";
 import { RecordingView } from './RecordingView';
 import { DocumentType } from "../../../documents/DocumentTypes";
 
+import { RecordingApi } from "../../../util/RecordingApi";
+
 
 @observer
 export class RecordingBox extends ViewBoxBaseComponent() {
@@ -31,17 +33,19 @@ export class RecordingBox extends ViewBoxBaseComponent() {
 
       @action
       setResult = (info: Upload.FileInformation) => {
-            console.log("Setting result to " + info)
+            // console.log("Setting result to " + info)
             this.result = info
-            console.log(this.result.accessPaths.agnostic.client)
+            // console.log(this.result.accessPaths.agnostic.client)
             this.dataDoc.type = DocumentType.VID;
-            console.log(this.videoDuration)
+            // console.log(this.videoDuration)
             this.dataDoc[this.fieldKey + "-duration"] = this.videoDuration;
 
             this.layoutDoc.layout = VideoBox.LayoutString(this.fieldKey);
             // this.dataDoc.nativeWidth = this.dataDoc.nativeHeight = undefined;
             // this.layoutDoc._fitWidth = undefined;
-            this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.agnostic.client);
+          this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.agnostic.client);
+          // stringify the presenation and store it
+            this.dataDoc[this.fieldKey + "-presentation"] = JSON.stringify(RecordingApi.Instance.clear());
       }
 
       render() {
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index d99492095..870ef87d7 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -8,7 +8,7 @@ import { IconContext } from "react-icons";
 import { Networking } from '../../../Network';
 import { Upload } from '../../../../server/SharedMediaTypes';
 
-import { RecordingApi } from '../../../apis/recording/RecordingApi';
+import { RecordingApi } from '../../../util/RecordingApi';
 
 
 enum RecordingStatus {
@@ -57,11 +57,11 @@ export function RecordingView(props: IRecordingViewProps) {
                   height: 720,
             },
             // audio: true,
-            // audio: {
-            //       echoCancellation: true,
-            //       noiseSuppression: true,
-            //       sampleRate: 44100
-            // }
+            audio: {
+                  echoCancellation: true,
+                  noiseSuppression: true,
+                  sampleRate: 44100
+            }
       }
 
       useEffect(() => {
@@ -159,7 +159,10 @@ export function RecordingView(props: IRecordingViewProps) {
             // }
 
             videoRecorder.current.onstart = (event: any) => {
-                  setRecording(true);
+                setRecording(true);
+                // TODO: update names
+                // RecordingApi.Instance.clear();
+                RecordingApi.Instance.start();
             }
 
             videoRecorder.current.onstop = () => {
@@ -172,7 +175,8 @@ export function RecordingView(props: IRecordingViewProps) {
                   // reset the temporary chunks
                   videoChunks = []
                   setRecording(false);
-                  setFinished(true);
+                setFinished(true);
+                RecordingApi.Instance.pause();
             }
 
             // recording paused
@@ -182,12 +186,14 @@ export function RecordingView(props: IRecordingViewProps) {
 
                   // reset the temporary chunks
                   videoChunks = []
-                  setRecording(false);
+                setRecording(false);
+                RecordingApi.Instance.pause();
             }
 
             videoRecorder.current.onresume = async (event: any) => {
                   await startShowingStream();
-                  setRecording(true);
+                setRecording(true);
+                RecordingApi.Instance.resume();
             }
 
             videoRecorder.current.start(200)
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index e57cb1abe..7364a64d9 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -28,6 +28,7 @@ import { AnchorMenu } from "../pdf/AnchorMenu";
 import { StyleProp } from "../StyleProvider";
 import { FieldView, FieldViewProps } from './FieldView';
 import "./VideoBox.scss";
+import { RecordingApi } from "../../util/RecordingApi";
 const path = require('path');
 
 
@@ -117,6 +118,12 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         return field?.url.href ?? vfield?.url.href ?? "";
     }
 
+    // returns the presentation data if it exists, null otherwise
+    @computed get presentation() {
+        const data = this.dataDoc[this.fieldKey + '-presentation'];
+        return data ? JSON.parse(data) : null;
+    }
+
 
     @computed private get timeline() { return this._stackedTimeline; }
     private get transition() { return this._clicking ? "left 0.5s, width 0.5s, height 0.5s" : ""; } // css transition for hiding/showing timeline
@@ -147,6 +154,13 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
 
     // plays video
     @action public Play = (update: boolean = true) => {
+        // if presentation isn't null, call followmovements on the recording api
+        if (this.presentation) {
+            const err = RecordingApi.Instance.followMovements(this.presentation);
+            if (err) console.log(err);
+        }
+
+
         this._playing = true;
         const eleTime = this.player?.currentTime || 0;
         if (this.timeline) {
-- 
cgit v1.2.3-70-g09d2


From 91746b4e9c570a7579e3396e2e31c73d8fa9915e Mon Sep 17 00:00:00 2001
From: Michael Foiani <sotech117@michaels-mbp-3.devices.brown.edu>
Date: Wed, 4 May 2022 01:32:27 -0400
Subject: updated to subtracting timestamps for better smoothness

---
 src/client/util/RecordingApi.ts                    | 27 +++++++++++-----------
 .../views/nodes/RecordingBox/RecordingView.tsx     |  2 ++
 2 files changed, 15 insertions(+), 14 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/client/util/RecordingApi.ts b/src/client/util/RecordingApi.ts
index c4f76282c..ab7642a90 100644
--- a/src/client/util/RecordingApi.ts
+++ b/src/client/util/RecordingApi.ts
@@ -11,7 +11,7 @@ type Movement = {
 type Presentation = {
     movements: Array<Movement>
     meta: Object,
-    startDate: Date | null,
+    startTime: number | null,
 }
 
 export class RecordingApi {
@@ -19,7 +19,7 @@ export class RecordingApi {
     private static NULL_PRESENTATION: Presentation = {
         movements: [],
         meta: {},
-        startDate: null,
+        startTime: null,
     }
 
     // instance variables
@@ -50,7 +50,7 @@ export class RecordingApi {
 
     // little helper :)
     private get isInitPresenation(): boolean {
-        return this.currentPresentation.startDate === null
+        return this.currentPresentation.startTime === null
     }
 
     public start = (meta?: Object): Error | undefined => {
@@ -63,12 +63,12 @@ export class RecordingApi {
         // (1a) get start date for presenation
         const startDate = new Date()
         // (1b) set start timestamp to absolute timestamp
-        this.absoluteStart = startDate.getTime()
+        // this.absoluteStart = startDate.getTime()
 
         // (2) assign meta content if it exists
         this.currentPresentation.meta = meta || {}
         // (3) assign start date to currentPresenation
-        this.currentPresentation.startDate = startDate
+        this.currentPresentation.startTime = startDate.getTime()
         // (4) set isRecording true to allow trackMovements
         this.isRecording = true
     }
@@ -89,15 +89,15 @@ export class RecordingApi {
         // clear absoluteStart
         this.absoluteStart = -1
         // clear the disposeFunc
-        this.disposeFunc = null
+        this.removeRecordingFFView()
 
         return presCopy;
     }
 
     public pause = (): Error | undefined => {
-        if (this.currentPresentation.startDate === null) {
+        if (this.isInitPresenation) {
             console.error('[recordingApi.ts] pause() failed: no presentation started. try calling init() first')
-            return new Error('[recordingApi.ts] pause(): no presenation')
+            return new Error('[recordingApi.ts] pause(): no presentation')
         }
         // don't allow track movments
         this.isRecording = false
@@ -109,7 +109,7 @@ export class RecordingApi {
 
     public resume = () => {
         const timestamp = new Date().getTime()
-        const startTimestamp = this.currentPresentation.startDate?.getTime()
+        const startTimestamp = this.currentPresentation.startTime
         if (!startTimestamp) {
             console.error('[recordingApi.ts] resume() failed: no presentation data. try calling start() first')
             return new Error('[recordingApi.ts] pause()')
@@ -137,12 +137,11 @@ export class RecordingApi {
             return new Error('[recordingApi.ts] pause()')
         }
 
-        // get the relative time
+        // get the time
         const timestamp = new Date().getTime()
-        const relativeTime = timestamp - this.absoluteStart
 
         // make new movement struct
-        const movement: Movement = { time: relativeTime, panX, panY }
+        const movement: Movement = { time: timestamp, panX, panY }
         
         // add that movement to the current presentation data's movement array
         this.currentPresentation.movements.push(movement)
@@ -211,7 +210,7 @@ export class RecordingApi {
     }
 
     public followMovements = (presentation: Presentation): undefined | Error => {
-        if (presentation.startDate === null || this.playFFView === null) {
+        if (presentation.startTime === null || this.playFFView === null) {
             return new Error('[recordingApi.ts] followMovements() failed: no presentation data or no view')
         }
 
@@ -223,7 +222,7 @@ export class RecordingApi {
             setTimeout(() => {
                 document._panX = panX;
                 document._panY = panY;
-            }, time)
+            }, time - presentation.startTime)
         })
     }
     // Unfinished code for tracing multiple free form views
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 870ef87d7..51cc44941 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -176,6 +176,7 @@ export function RecordingView(props: IRecordingViewProps) {
                   videoChunks = []
                   setRecording(false);
                 setFinished(true);
+                console.log("finished recording")
                 RecordingApi.Instance.pause();
             }
 
@@ -187,6 +188,7 @@ export function RecordingView(props: IRecordingViewProps) {
                   // reset the temporary chunks
                   videoChunks = []
                 setRecording(false);
+                console.log("paused recording")
                 RecordingApi.Instance.pause();
             }
 
-- 
cgit v1.2.3-70-g09d2


From 4dc4b0939d4e4afbc9f6db999ff80d434ef4ccc6 Mon Sep 17 00:00:00 2001
From: Michael Foiani <sotech117@michaels-mbp-3.devices.brown.edu>
Date: Wed, 4 May 2022 02:00:55 -0400
Subject: Added the presentation mode back in. However, pres isn't being
 recreated smoothly after being stored in the db.

---
 src/client/util/RecordingApi.ts                     | 21 +++++++++++++++++----
 .../collectionFreeForm/CollectionFreeFormView.tsx   |  6 ++++--
 .../views/nodes/RecordingBox/RecordingView.tsx      |  3 ---
 3 files changed, 21 insertions(+), 9 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/client/util/RecordingApi.ts b/src/client/util/RecordingApi.ts
index ab7642a90..b53cba79d 100644
--- a/src/client/util/RecordingApi.ts
+++ b/src/client/util/RecordingApi.ts
@@ -1,6 +1,7 @@
 import { CollectionFreeFormView } from "../views/collections/collectionFreeForm";
 import { IReactionDisposer, observable, reaction } from "mobx";
 import { NumCast } from "../../fields/Types";
+import { Doc } from "../../fields/Doc";
 
 type Movement = {
     time: number,
@@ -42,6 +43,7 @@ export class RecordingApi {
 
         // used for tracking movements in the view frame
         this.disposeFunc = null;
+        this.recordingFFView = null;
 
         // for now, set playFFView
         this.playFFView = null;
@@ -60,6 +62,9 @@ export class RecordingApi {
             return new Error('[recordingApi.ts] start()')
         }
 
+        // update the presentation mode
+        Doc.UserDoc().presentationMode = 'recording'
+
         // (1a) get start date for presenation
         const startDate = new Date()
         // (1b) set start timestamp to absolute timestamp
@@ -80,6 +85,9 @@ export class RecordingApi {
             return new Error('[recordingApi.ts] clear()')
         }
 
+        // update the presentation mode
+        Doc.UserDoc().presentationMode = 'none'
+
         const presCopy = { ...this.currentPresentation }
 
         // clear presenation data
@@ -133,8 +141,8 @@ export class RecordingApi {
     private trackMovements = (panX: number, panY: number): Error | undefined => {
         // ensure we are recording
         if (!this.isRecording) {
-            console.error('[recordingApi.ts] pause() failed: recording is paused()')
-            return new Error('[recordingApi.ts] pause()')
+            console.error('[recordingApi.ts] trackMovements() failed: recording is paused()')
+            return new Error('[recordingApi.ts] trackMovements()')
         }
 
         // get the time
@@ -149,11 +157,12 @@ export class RecordingApi {
 
     // instance variable for the FFView
     private disposeFunc: IReactionDisposer | null;
+    private recordingFFView: CollectionFreeFormView | null;
     
     // set the FFView that will be used in a reaction to track the movements
     public setRecordingFFView = (view: CollectionFreeFormView): void => {
         // set the view to the current view
-        if (view === null || view === this.playFFView) return;
+        if (view === this.recordingFFView || view === null) return;
         
         //this.recordingFFView = view;
         // set the reaction to track the movements
@@ -163,7 +172,7 @@ export class RecordingApi {
         )
 
         // for now, set the most recent recordingFFView to the playFFView
-        this.playFFView = view;
+        this.recordingFFView = view;
     }
 
     // call on dispose function to stop tracking movements
@@ -194,6 +203,10 @@ export class RecordingApi {
     //     })
     // }
 
+    public setPlayFFView = (view: CollectionFreeFormView): void => {
+        this.playFFView = view
+    }
+
     public pauseMovements = (): undefined | Error => {
         if (this.playFFView === null) {
             return new Error('[recordingApi.ts] pauseMovements() failed: no view')
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index f74e526b6..8bcf6f46f 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -965,8 +965,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     @action
     setPan(panX: number, panY: number, panTime: number = 0, clamp: boolean = false) {
-        // set the current FFview to the tab being panned.
-        RecordingApi.Instance.setRecordingFFView(this)
+        // set the current respective FFview to the tab being panned.
+        RecordingApi.Instance.setRecordingFFView(this);
+        // TODO: make this based off the specific recording FFView
+        Doc.UserDoc()?.presentationMode !== 'recording' && RecordingApi.Instance.setPlayFFView(this);
 
         if (!this.isAnnotationOverlay && clamp) {
             // this section wraps the pan position, horizontally and/or vertically whenever the content is panned out of the viewing bounds
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 51cc44941..f7446b556 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -160,7 +160,6 @@ export function RecordingView(props: IRecordingViewProps) {
 
             videoRecorder.current.onstart = (event: any) => {
                 setRecording(true);
-                // TODO: update names
                 // RecordingApi.Instance.clear();
                 RecordingApi.Instance.start();
             }
@@ -176,7 +175,6 @@ export function RecordingView(props: IRecordingViewProps) {
                   videoChunks = []
                   setRecording(false);
                 setFinished(true);
-                console.log("finished recording")
                 RecordingApi.Instance.pause();
             }
 
@@ -188,7 +186,6 @@ export function RecordingView(props: IRecordingViewProps) {
                   // reset the temporary chunks
                   videoChunks = []
                 setRecording(false);
-                console.log("paused recording")
                 RecordingApi.Instance.pause();
             }
 
-- 
cgit v1.2.3-70-g09d2


From a9ff0c90656de71e37edafba68e946807d41403f Mon Sep 17 00:00:00 2001
From: Michael Foiani <sotech117@michaels-mbp-3.devices.brown.edu>
Date: Wed, 4 May 2022 13:36:13 -0400
Subject: fix infinite pause/play bug with a stopper, but still very buggy

---
 src/client/util/RecordingApi.ts                      |  3 ++-
 .../collectionFreeForm/CollectionFreeFormView.tsx    |  4 ++--
 .../views/nodes/RecordingBox/RecordingView.scss      | 20 ++++++++++++--------
 .../views/nodes/RecordingBox/RecordingView.tsx       |  2 +-
 src/client/views/nodes/VideoBox.tsx                  |  5 +++++
 5 files changed, 22 insertions(+), 12 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/client/util/RecordingApi.ts b/src/client/util/RecordingApi.ts
index 8fb503b00..fec579486 100644
--- a/src/client/util/RecordingApi.ts
+++ b/src/client/util/RecordingApi.ts
@@ -188,7 +188,7 @@ export class RecordingApi {
         // TODO: set userdoc presentMode to browsing
         this.timers?.map(timer => clearTimeout(timer))
 
-        this.videoBox = null;
+        // this.videoBox = null;
     }
     
     private videoBox: VideoBox | null = null;
@@ -236,6 +236,7 @@ export class RecordingApi {
             }, timeDiff))
             return arr;
         }, [])
+
     }
 
     // Unfinished code for tracing multiple free form views
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 9e57bca4f..aa2e0c417 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -970,9 +970,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         // TODO: make this based off the specific recording FFView
         Doc.UserDoc()?.presentationMode === 'none' && RecordingApi.Instance.setPlayFFView(this);
         if (Doc.UserDoc()?.presentationMode === 'watching') {
-            Doc.UserDoc().presentationMode = 'none';
-            // RecordingApi.Instance.pauseMovements();
             RecordingApi.Instance.pauseVideoAndMovements();
+            Doc.UserDoc().presentationMode = 'none';
+            // RecordingApi.Instance.pauseMovements()
         }
 
         if (!this.isAnnotationOverlay && clamp) {
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.scss b/src/client/views/nodes/RecordingBox/RecordingView.scss
index 1fea231b7..d1a50a82e 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.scss
+++ b/src/client/views/nodes/RecordingBox/RecordingView.scss
@@ -1,9 +1,11 @@
 video {
-      flex: 100%;
+    // flex: 100%;
       width: 100%;
-      min-height: 400px;
-      height: auto;
-      display: block;
+      // min-height: 400px;
+      //height: auto;
+      height: 100%;
+      //display: block;
+      object-fit: cover;
       background-color: black;
 }
 
@@ -14,18 +16,20 @@ button {
 .recording-container {
       height: 100%;
       width: 100%;
-      display: flex;
+      // display: flex;
       pointer-events: all;
+      background-color: grey;
 }
 
 .video-wrapper {
-      max-width: 600px;
-      max-width: 700px;
+    //   max-width: 600px;
+    //   max-width: 700px;
       position: relative;
       display: flex;
       justify-content: center;
-      overflow: hidden;
+    //   overflow: hidden;
       border-radius: 10px;
+      margin: 0;
 }
 
 .video-wrapper:hover .controls {
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index f7446b556..e7e431b49 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -258,7 +258,7 @@ export function RecordingView(props: IRecordingViewProps) {
             return toTwoDigit(minutes) + " : " + toTwoDigit(seconds);
       }
 
-      return (
+    return (
             <div className="recording-container">
                   <div className="video-wrapper">
                         <video id="video"
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 1ff77e373..226c2b1ce 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -154,6 +154,11 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
 
     // plays video
     @action public Play = (update: boolean = true) => {
+        if (Doc.UserDoc().presentationMode === 'watching' && !this._playing) {
+            console.log('VideoBox : Play : presentation mode', this._playing);
+            return;
+        }
+
         // if presentation isn't null, call followmovements on the recording api
         if (this.presentation) {
             const err = RecordingApi.Instance.playMovements(this.presentation, this.player?.currentTime || 0, this);
-- 
cgit v1.2.3-70-g09d2


From 2259c475152543b54d7ea89dcea53927346e54ca Mon Sep 17 00:00:00 2001
From: Jenny Yu <jennyyu212@outlook.com>
Date: Wed, 4 May 2022 17:38:09 -0400
Subject: fix: show the corresponding video when clicking on slides

---
 .../views/nodes/RecordingBox/RecordingView.tsx     |   2 +-
 src/client/views/nodes/trails/PresElementBox.tsx   | 853 +++++++++++----------
 2 files changed, 437 insertions(+), 418 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index e5f6deca2..b4febfc01 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -25,7 +25,7 @@ interface IRecordingViewProps {
       setDuration: (seconds: number) => void
 }
 
-const MAXTIME = 1000;
+const MAXTIME = 100000;
 
 export function RecordingView(props: IRecordingViewProps) {
 
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index cd7b09017..6725307db 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -31,429 +31,448 @@ import { List } from "../../../../fields/List";
  */
 @observer
 export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
-    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresElementBox, fieldKey); }
-    _heightDisposer: IReactionDisposer | undefined;
-
-    @observable _dragging = false;
-    // these fields are conditionally computed fields on the layout document that take this document as a parameter
-    @computed get indexInPres() { return Number(this.lookupField("indexInPres")); }  // the index field is where this document is in the presBox display list (since this value is different for each presentation element, the value can't be stored on the layout template which is used by all display elements)
-    @computed get collapsedHeight() { return Number(this.lookupField("presCollapsedHeight")); } // the collapsed height changes depending on the state of the presBox.  We could store this on the presentation element template if it's used by only one presentation - but if it's shared by multiple, then this value must be looked up
-    @computed get presStatus() { return StrCast(this.lookupField("presStatus")); }
-    @computed get itemIndex() { return NumCast(this.lookupField("_itemIndex")); }
-    @computed get presBox() { return Cast(this.lookupField("presBox"), Doc, null); }
-    @computed get targetDoc() { return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc; }
-
-
-    @observable isShowingVideo = false;
-    @action setIsShowingVideo(shown: boolean) {
-        this.isShowingVideo = shown
-    }
-
-    componentDidMount() {
-        this.layoutDoc.hideLinkButton = true;
-        this._heightDisposer = reaction(() => [this.rootDoc.presExpandInlineButton, this.collapsedHeight],
-            params => this.layoutDoc._height = NumCast(params[1]) + (Number(params[0]) ? 100 : 0), { fireImmediately: true });
-    }
-    componentWillUnmount() {
-        this._heightDisposer?.();
-    }
-
-    /**
-     * Returns a local transformed coordinate array for given coordinates.
-     */
-    ScreenToLocalListTransform = (xCord: number, yCord: number) => [xCord, yCord];
-
-    embedHeight = (): number => 97;
-    // embedWidth = () => this.props.PanelWidth();
-    // embedHeight = () => Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - this.collapsedHeight);
-    embedWidth = (): number => this.props.PanelWidth() - 35;
-    styleProvider = (doc: (Doc | undefined), props: Opt<DocumentViewProps>, property: string): any => {
-        if (property === StyleProp.Opacity) return 1;
-        return this.props.styleProvider?.(doc, props, property);
-    }
-    /**
-     * The function that is responsible for rendering a preview or not for this
-     * presentation element.
-     */
-    @computed get renderEmbeddedInline() {
-        return !this.rootDoc.presExpandInlineButton || !this.targetDoc ? (null) :
-            <div className="presItem-embedded" style={{ height: this.embedHeight(), width: this.embedWidth() }}>
-                <DocumentView
-                    Document={this.targetDoc}
-                    DataDoc={this.targetDoc[DataSym] !== this.targetDoc && this.targetDoc[DataSym]}
-                    styleProvider={this.styleProvider}
-                    layerProvider={this.props.layerProvider}
-                    docViewPath={returnEmptyDoclist}
-                    rootSelected={returnTrue}
-                    addDocument={returnFalse}
-                    removeDocument={returnFalse}
-                    isContentActive={this.props.isContentActive}
-                    addDocTab={returnFalse}
-                    pinToPres={returnFalse}
-                    fitContentsToDoc={returnTrue}
-                    PanelWidth={this.embedWidth}
-                    PanelHeight={this.embedHeight}
-                    ScreenToLocalTransform={Transform.Identity}
-                    moveDocument={this.props.moveDocument!}
-                    renderDepth={this.props.renderDepth + 1}
-                    focus={DocUtils.DefaultFocus}
-                    whenChildContentsActiveChanged={returnFalse}
-                    bringToFront={returnFalse}
-                    docFilters={this.props.docFilters}
-                    docRangeFilters={this.props.docRangeFilters}
-                    searchFilterDocs={this.props.searchFilterDocs}
-                    ContainingCollectionView={undefined}
-                    ContainingCollectionDoc={undefined}
-                    hideLinkButton={true}
-                />
-                <div className="presItem-embeddedMask" />
-            </div>;
-    }
-    @computed get duration() {
-        let durationInS: number;
-        if (this.rootDoc.type === DocumentType.AUDIO || this.rootDoc.type === DocumentType.VID) { durationInS = NumCast(this.rootDoc.presEndTime) - NumCast(this.rootDoc.presStartTime); durationInS = Math.round(durationInS * 10) / 10; }
-        else if (this.rootDoc.presDuration) durationInS = NumCast(this.rootDoc.presDuration) / 1000;
-        else durationInS = 2;
-        return "D: " + durationInS + "s";
-    }
-
-    @computed get transition() {
-        let transitionInS: number;
-        if (this.rootDoc.presTransition) transitionInS = NumCast(this.rootDoc.presTransition) / 1000;
-        else transitionInS = 0.5;
-        return this.rootDoc.presMovement === PresMovement.Jump || this.rootDoc.presMovement === PresMovement.None ? (null) : "M: " + transitionInS + "s";
-    }
-
-    private _itemRef: React.RefObject<HTMLDivElement> = React.createRef();
-    private _dragRef: React.RefObject<HTMLDivElement> = React.createRef();
-    private _titleRef: React.RefObject<EditableView> = React.createRef();
-
-
-    @action
-    headerDown = (e: React.PointerEvent<HTMLDivElement>) => {
-        const element = e.target as any;
-        e.stopPropagation();
-        e.preventDefault();
-        if (element && !(e.ctrlKey || e.metaKey)) {
+      public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresElementBox, fieldKey); }
+      _heightDisposer: IReactionDisposer | undefined;
+
+      @observable _dragging = false;
+      // these fields are conditionally computed fields on the layout document that take this document as a parameter
+      @computed get indexInPres() { return Number(this.lookupField("indexInPres")); }  // the index field is where this document is in the presBox display list (since this value is different for each presentation element, the value can't be stored on the layout template which is used by all display elements)
+      @computed get collapsedHeight() { return Number(this.lookupField("presCollapsedHeight")); } // the collapsed height changes depending on the state of the presBox.  We could store this on the presentation element template if it's used by only one presentation - but if it's shared by multiple, then this value must be looked up
+      @computed get presStatus() { return StrCast(this.lookupField("presStatus")); }
+      @computed get itemIndex() { return NumCast(this.lookupField("_itemIndex")); }
+      @computed get presBox() { return Cast(this.lookupField("presBox"), Doc, null); }
+      @computed get targetDoc() { return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc; }
+
+
+      @observable isShowingVideo = false;
+      @action setIsShowingVideo(shown: boolean) {
+            this.isShowingVideo = shown
+      }
+
+      componentDidMount() {
+            this.layoutDoc.hideLinkButton = true;
+            this._heightDisposer = reaction(() => [this.rootDoc.presExpandInlineButton, this.collapsedHeight],
+                  params => this.layoutDoc._height = NumCast(params[1]) + (Number(params[0]) ? 100 : 0), { fireImmediately: true });
+      }
+      componentWillUnmount() {
+            this._heightDisposer?.();
+      }
+
+      /**
+       * Returns a local transformed coordinate array for given coordinates.
+       */
+      ScreenToLocalListTransform = (xCord: number, yCord: number) => [xCord, yCord];
+
+      embedHeight = (): number => 97;
+      // embedWidth = () => this.props.PanelWidth();
+      // embedHeight = () => Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - this.collapsedHeight);
+      embedWidth = (): number => this.props.PanelWidth() - 35;
+      styleProvider = (doc: (Doc | undefined), props: Opt<DocumentViewProps>, property: string): any => {
+            if (property === StyleProp.Opacity) return 1;
+            return this.props.styleProvider?.(doc, props, property);
+      }
+      /**
+       * The function that is responsible for rendering a preview or not for this
+       * presentation element.
+       */
+      @computed get renderEmbeddedInline() {
+            return !this.rootDoc.presExpandInlineButton || !this.targetDoc ? (null) :
+                  <div className="presItem-embedded" style={{ height: this.embedHeight(), width: this.embedWidth() }}>
+                        <DocumentView
+                              Document={this.targetDoc}
+                              DataDoc={this.targetDoc[DataSym] !== this.targetDoc && this.targetDoc[DataSym]}
+                              styleProvider={this.styleProvider}
+                              layerProvider={this.props.layerProvider}
+                              docViewPath={returnEmptyDoclist}
+                              rootSelected={returnTrue}
+                              addDocument={returnFalse}
+                              removeDocument={returnFalse}
+                              isContentActive={this.props.isContentActive}
+                              addDocTab={returnFalse}
+                              pinToPres={returnFalse}
+                              fitContentsToDoc={returnTrue}
+                              PanelWidth={this.embedWidth}
+                              PanelHeight={this.embedHeight}
+                              ScreenToLocalTransform={Transform.Identity}
+                              moveDocument={this.props.moveDocument!}
+                              renderDepth={this.props.renderDepth + 1}
+                              focus={DocUtils.DefaultFocus}
+                              whenChildContentsActiveChanged={returnFalse}
+                              bringToFront={returnFalse}
+                              docFilters={this.props.docFilters}
+                              docRangeFilters={this.props.docRangeFilters}
+                              searchFilterDocs={this.props.searchFilterDocs}
+                              ContainingCollectionView={undefined}
+                              ContainingCollectionDoc={undefined}
+                              hideLinkButton={true}
+                        />
+                        <div className="presItem-embeddedMask" />
+                  </div>;
+      }
+      @computed get duration() {
+            let durationInS: number;
+            if (this.rootDoc.type === DocumentType.AUDIO || this.rootDoc.type === DocumentType.VID) { durationInS = NumCast(this.rootDoc.presEndTime) - NumCast(this.rootDoc.presStartTime); durationInS = Math.round(durationInS * 10) / 10; }
+            else if (this.rootDoc.presDuration) durationInS = NumCast(this.rootDoc.presDuration) / 1000;
+            else durationInS = 2;
+            return "D: " + durationInS + "s";
+      }
+
+      @computed get transition() {
+            let transitionInS: number;
+            if (this.rootDoc.presTransition) transitionInS = NumCast(this.rootDoc.presTransition) / 1000;
+            else transitionInS = 0.5;
+            return this.rootDoc.presMovement === PresMovement.Jump || this.rootDoc.presMovement === PresMovement.None ? (null) : "M: " + transitionInS + "s";
+      }
+
+      private _itemRef: React.RefObject<HTMLDivElement> = React.createRef();
+      private _dragRef: React.RefObject<HTMLDivElement> = React.createRef();
+      private _titleRef: React.RefObject<EditableView> = React.createRef();
+
+
+      @action
+      headerDown = (e: React.PointerEvent<HTMLDivElement>) => {
+            const element = e.target as any;
+            e.stopPropagation();
+            e.preventDefault();
+            if (element && !(e.ctrlKey || e.metaKey)) {
+                  if (PresBox.Instance._selectedArray.has(this.rootDoc)) {
+                        PresBox.Instance._selectedArray.size === 1 && PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, false);
+                        setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction);
+                  } else {
+                        setupMoveUpEvents(this, e, ((e: PointerEvent) => {
+                              PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, false);
+                              return this.startDrag(e);
+                        }), emptyFunction, emptyFunction);
+                  }
+            }
+      }
+
+      headerUp = (e: React.PointerEvent<HTMLDivElement>) => {
+            e.stopPropagation();
+            e.preventDefault();
+      }
+
+      /**
+       * Function to drag and drop the pres element to a diferent location
+       */
+      startDrag = (e: PointerEvent) => {
+            const miniView: boolean = this.toolbarWidth <= 100;
+            const activeItem = this.rootDoc;
+            const dragArray = PresBox.Instance._dragArray;
+            const dragData = new DragManager.DocumentDragData(PresBox.Instance.sortArray());
+            if (!dragData.draggedDocuments.length) dragData.draggedDocuments.push(this.rootDoc);
+            dragData.dropAction = "move";
+            dragData.treeViewDoc = this.props.docViewPath().lastElement()?.props.treeViewDoc;
+            dragData.moveDocument = this.props.docViewPath().lastElement()?.props.moveDocument;
+            const dragItem: HTMLElement[] = [];
+            if (dragArray.length === 1) {
+                  const doc = dragArray[0];
+                  doc.className = miniView ? "presItem-miniSlide" : "presItem-slide";
+                  dragItem.push(doc);
+            } else if (dragArray.length >= 1) {
+                  const doc = document.createElement('div');
+                  doc.className = "presItem-multiDrag";
+                  doc.innerText = "Move " + PresBox.Instance._selectedArray.size + " slides";
+                  doc.style.position = 'absolute';
+                  doc.style.top = (e.clientY) + 'px';
+                  doc.style.left = (e.clientX - 50) + 'px';
+                  dragItem.push(doc);
+            }
+
+            // const dropEvent = () => runInAction(() => this._dragging = false);
+            if (activeItem) {
+                  DragManager.StartDocumentDrag(dragItem.map(ele => ele), dragData, e.clientX, e.clientY, undefined);
+                  // runInAction(() => this._dragging = true);
+                  return true;
+            }
+            return false;
+      }
+
+      onPointerOver = (e: any) => {
+            document.removeEventListener("pointermove", this.onPointerMove);
+            document.addEventListener("pointermove", this.onPointerMove);
+      }
+
+      onPointerMove = (e: PointerEvent) => {
+            const slide = this._itemRef.current!;
+            let dragIsPresItem: boolean = DragManager.docsBeingDragged.length > 0 ? true : false;
+            for (const doc of DragManager.docsBeingDragged) {
+                  if (!doc.presentationTargetDoc) dragIsPresItem = false;
+            }
+            if (slide && dragIsPresItem) {
+                  const rect = slide.getBoundingClientRect();
+                  const y = e.clientY - rect.top;  //y position within the element.
+                  const height = slide.clientHeight;
+                  const halfLine = height / 2;
+                  if (y <= halfLine) {
+                        slide.style.borderTop = `solid 2px ${Colors.MEDIUM_BLUE}`;
+                        slide.style.borderBottom = "0px";
+                  } else if (y > halfLine) {
+                        slide.style.borderTop = "0px";
+                        slide.style.borderBottom = `solid 2px ${Colors.MEDIUM_BLUE}`;
+                  }
+            }
+            document.removeEventListener("pointermove", this.onPointerMove);
+      }
+
+      onPointerLeave = (e: any) => {
+            this._itemRef.current!.style.borderTop = "0px";
+            this._itemRef.current!.style.borderBottom = "0px";
+            document.removeEventListener("pointermove", this.onPointerMove);
+      }
+
+      @action
+      toggleProperties = () => {
+            if (CurrentUserUtils.propertiesWidth < 5) {
+                  action(() => (CurrentUserUtils.propertiesWidth = 250));
+            }
+      }
+
+      @undoBatch
+      removeItem = action((e: React.MouseEvent) => {
+            this.props.removeDocument?.(this.rootDoc);
             if (PresBox.Instance._selectedArray.has(this.rootDoc)) {
-                PresBox.Instance._selectedArray.size === 1 && PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, false);
-                setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction);
-            } else {
-                setupMoveUpEvents(this, e, ((e: PointerEvent) => {
-                    PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, false);
-                    return this.startDrag(e);
-                }), emptyFunction, emptyFunction);
+                  PresBox.Instance._selectedArray.delete(this.rootDoc);
             }
-        }
-    }
-
-    headerUp = (e: React.PointerEvent<HTMLDivElement>) => {
-        e.stopPropagation();
-        e.preventDefault();
-    }
-
-    /**
-     * Function to drag and drop the pres element to a diferent location
-     */
-    startDrag = (e: PointerEvent) => {
-        const miniView: boolean = this.toolbarWidth <= 100;
-        const activeItem = this.rootDoc;
-        const dragArray = PresBox.Instance._dragArray;
-        const dragData = new DragManager.DocumentDragData(PresBox.Instance.sortArray());
-        if (!dragData.draggedDocuments.length) dragData.draggedDocuments.push(this.rootDoc);
-        dragData.dropAction = "move";
-        dragData.treeViewDoc = this.props.docViewPath().lastElement()?.props.treeViewDoc;
-        dragData.moveDocument = this.props.docViewPath().lastElement()?.props.moveDocument;
-        const dragItem: HTMLElement[] = [];
-        if (dragArray.length === 1) {
-            const doc = dragArray[0];
-            doc.className = miniView ? "presItem-miniSlide" : "presItem-slide";
-            dragItem.push(doc);
-        } else if (dragArray.length >= 1) {
-            const doc = document.createElement('div');
-            doc.className = "presItem-multiDrag";
-            doc.innerText = "Move " + PresBox.Instance._selectedArray.size + " slides";
-            doc.style.position = 'absolute';
-            doc.style.top = (e.clientY) + 'px';
-            doc.style.left = (e.clientX - 50) + 'px';
-            dragItem.push(doc);
-        }
-
-        // const dropEvent = () => runInAction(() => this._dragging = false);
-        if (activeItem) {
-            DragManager.StartDocumentDrag(dragItem.map(ele => ele), dragData, e.clientX, e.clientY, undefined);
-            // runInAction(() => this._dragging = true);
+            this.hideRecording();
+            e.stopPropagation();
+      });
+
+      // set the value/title of the individual pres element
+      @undoBatch
+      @action
+      onSetValue = (value: string) => {
+            this.rootDoc.title = !value.trim().length ? "-untitled-" : value;
             return true;
-        }
-        return false;
-    }
-
-    onPointerOver = (e: any) => {
-        document.removeEventListener("pointermove", this.onPointerMove);
-        document.addEventListener("pointermove", this.onPointerMove);
-    }
-
-    onPointerMove = (e: PointerEvent) => {
-        const slide = this._itemRef.current!;
-        let dragIsPresItem: boolean = DragManager.docsBeingDragged.length > 0 ? true : false;
-        for (const doc of DragManager.docsBeingDragged) {
-            if (!doc.presentationTargetDoc) dragIsPresItem = false;
-        }
-        if (slide && dragIsPresItem) {
-            const rect = slide.getBoundingClientRect();
-            const y = e.clientY - rect.top;  //y position within the element.
-            const height = slide.clientHeight;
-            const halfLine = height / 2;
-            if (y <= halfLine) {
-                slide.style.borderTop = `solid 2px ${Colors.MEDIUM_BLUE}`;
-                slide.style.borderBottom = "0px";
-            } else if (y > halfLine) {
-                slide.style.borderTop = "0px";
-                slide.style.borderBottom = `solid 2px ${Colors.MEDIUM_BLUE}`;
-            }
-        }
-        document.removeEventListener("pointermove", this.onPointerMove);
-    }
-
-    onPointerLeave = (e: any) => {
-        this._itemRef.current!.style.borderTop = "0px";
-        this._itemRef.current!.style.borderBottom = "0px";
-        document.removeEventListener("pointermove", this.onPointerMove);
-    }
-
-    @action
-    toggleProperties = () => {
-        if (CurrentUserUtils.propertiesWidth < 5) {
-            action(() => (CurrentUserUtils.propertiesWidth = 250));
-        }
-    }
-
-    @undoBatch
-    removeItem = action((e: React.MouseEvent) => {
-        this.props.removeDocument?.(this.rootDoc);
-        if (PresBox.Instance._selectedArray.has(this.rootDoc)) {
-            PresBox.Instance._selectedArray.delete(this.rootDoc);
-        }
-        this.hideRecording();
-        e.stopPropagation();
-    });
-
-    // set the value/title of the individual pres element
-    @undoBatch
-    @action
-    onSetValue = (value: string) => {
-        this.rootDoc.title = !value.trim().length ? "-untitled-" : value;
-        return true;
-    }
-
-    /**
-     * Method called for updating the view of the currently selected document
-     * 
-     * @param targetDoc 
-     * @param activeItem 
-     */
-    @undoBatch
-    @action
-    updateView = (targetDoc: Doc, activeItem: Doc) => {
-        if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF) {
-            const scroll = targetDoc._scrollTop;
-            activeItem.presPinViewScroll = scroll;
-        } else if (targetDoc.type === DocumentType.VID) {
-            activeItem.presPinTimecode = targetDoc._currentTimecode;
-        } else if (targetDoc.type === DocumentType.COMPARISON) {
-            const clipWidth = targetDoc._clipWidth;
-            activeItem.presPinClipWidth = clipWidth;
-        } else {
-            const x = targetDoc._panX;
-            const y = targetDoc._panY;
-            const scale = targetDoc._viewScale;
-            activeItem.presPinViewX = x;
-            activeItem.presPinViewY = y;
-            activeItem.presPinViewScale = scale;
-        }
-    }
-
-    @computed get recordingIsInOverlay() {
-        let isInOverlay = false
-        DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => {
-            if (doc.slides === this.rootDoc) {
-                isInOverlay = true
-                return
+      }
+
+      /**
+       * Method called for updating the view of the currently selected document
+       * 
+       * @param targetDoc 
+       * @param activeItem 
+       */
+      @undoBatch
+      @action
+      updateView = (targetDoc: Doc, activeItem: Doc) => {
+            if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF) {
+                  const scroll = targetDoc._scrollTop;
+                  activeItem.presPinViewScroll = scroll;
+            } else if (targetDoc.type === DocumentType.VID) {
+                  activeItem.presPinTimecode = targetDoc._currentTimecode;
+            } else if (targetDoc.type === DocumentType.COMPARISON) {
+                  const clipWidth = targetDoc._clipWidth;
+                  activeItem.presPinClipWidth = clipWidth;
+            } else {
+                  const x = targetDoc._panX;
+                  const y = targetDoc._panY;
+                  const scale = targetDoc._viewScale;
+                  activeItem.presPinViewX = x;
+                  activeItem.presPinViewY = y;
+                  activeItem.presPinViewScale = scale;
             }
-        })
-        return isInOverlay
-    }
-
-    @undoBatch
-    @action
-    hideRecording = () => {
-        console.log("hide recording")
-        DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => {
-            if (doc.slides === this.rootDoc) {
-                Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, doc);
+      }
+
+      @computed get recordingIsInOverlay() {
+            let isInOverlay = false
+            DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => {
+                  if (doc.slides === this.rootDoc) {
+                        isInOverlay = true
+                        return
+                  }
+            })
+            return isInOverlay
+      }
+
+      @undoBatch
+      @action
+      hideRecording = () => {
+            console.log("hide recording")
+            DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => {
+                  if (doc.slides === this.rootDoc) {
+                        Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, doc);
+                  }
+            })
+      }
+
+      @undoBatch
+      @action
+      showRecording = (activeItem: Doc) => {
+            // Remove every recording that already exists in overlay view
+            DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => {
+                  if (doc.slides !== null) {
+                        Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, doc);
+                  }
+            })
+            if (activeItem.recording) {
+                  // if we already have an existing recording
+                  console.log(activeItem.recording)
+                  console.log(Cast(activeItem.recording, Doc, null))
+                  Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, Cast(activeItem.recording, Doc, null));
+
             }
-        })
-    }
-
-    @undoBatch
-    @action
-    startRecording = (targetDoc: Doc, activeItem: Doc) => {
-        // Remove every recording that already exists in overlay view
-        DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => {
-            if (doc.slides !== null) {
-                Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, doc);
+      }
+
+      @undoBatch
+      @action
+      startRecording = (activeItem: Doc) => {
+            // Remove every recording that already exists in overlay view
+            DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => {
+                  if (doc.slides !== null) {
+                        Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, doc);
+                  }
+            })
+
+            if (activeItem.recording) {
+                  // if we already have an existing recording
+                  console.log("recording exists")
+                  console.log(activeItem.recording)
+                  console.log(Cast(activeItem.recording, Doc, null))
+                  Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, Cast(activeItem.recording, Doc, null));
+
+            } else {
+                  console.log("creating new recording")
+                  // if we dont have any recording
+                  const recording = Docs.Create.WebCamDocument("", { _width: 400, _height: 200, title: "recording", cloneFieldFilter: new List<string>(["system"]) });
+
+                  // attach the recording to the slide, and attach the slide to the recording
+                  recording.slides = activeItem
+                  activeItem.recording = recording
+
+                  // TODO: Figure out exactly where we want the video to appear
+                  const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
+                  recording.x = pt[0];
+                  recording.y = pt[1];
+                  console.log(pt)
+                  Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, recording);
             }
-        })
-
-        if (activeItem.recording) {
-            // if we already have an existing recording
-            console.log("recording exists")
-            console.log(activeItem.recording)
-            console.log(Cast(activeItem.recording, Doc, null))
-            Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, Cast(activeItem.recording, Doc, null));
-
-        } else {
-            console.log("creating new recording")
-            // if we dont have any recording
-            const recording = Docs.Create.WebCamDocument("", { _width: 400, _height: 200, title: "recording", cloneFieldFilter: new List<string>(["system"]) });
-
-            // attach the recording to the slide, and attach the slide to the recording
-            recording.slides = activeItem
-            activeItem.recording = recording
-
-            // TODO: Figure out exactly where we want the video to appear
-            const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
-            recording.x = pt[0];
-            recording.y = pt[1];
-            console.log(pt)
-            Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, recording);
-        }
-    }
-
-    @computed
-    get toolbarWidth(): number {
-        const presBoxDocView = DocumentManager.Instance.getDocumentView(this.presBox);
-        let width: number = NumCast(this.presBox._width);
-        if (presBoxDocView) width = presBoxDocView.props.PanelWidth();
-        if (width === 0) width = 300;
-        return width;
-    }
-
-    @computed get mainItem() {
-        const isSelected: boolean = PresBox.Instance?._selectedArray.has(this.rootDoc);
-        const toolbarWidth: number = this.toolbarWidth;
-        const showMore: boolean = this.toolbarWidth >= 300;
-        const miniView: boolean = this.toolbarWidth <= 110;
-        const presBox: Doc = this.presBox; //presBox
-        const presBoxColor: string = StrCast(presBox._backgroundColor);
-        const presColorBool: boolean = presBoxColor ? (presBoxColor !== Colors.WHITE && presBoxColor !== "transparent") : false;
-        const targetDoc: Doc = this.targetDoc;
-        const activeItem: Doc = this.rootDoc;
-        return (
-            <div className={`presItem-container`}
-                key={this.props.Document[Id] + this.indexInPres}
-                ref={this._itemRef}
-                style={{
-                    backgroundColor: presColorBool ? isSelected ? "rgba(250,250,250,0.3)" : "transparent" : isSelected ? Colors.LIGHT_BLUE : "transparent",
-                    opacity: this._dragging ? 0.3 : 1
-                }}
-                onClick={e => {
-                    e.stopPropagation();
-                    e.preventDefault();
-                    PresBox.Instance.modifierSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, !e.shiftKey && !e.ctrlKey && !e.metaKey, e.ctrlKey || e.metaKey, e.shiftKey);
-                }}
-                onDoubleClick={action(e => {
-                    this.toggleProperties();
-                    PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, true);
-                })}
-                onPointerOver={this.onPointerOver}
-                onPointerLeave={this.onPointerLeave}
-                onPointerDown={this.headerDown}
-                onPointerUp={this.headerUp}
-            >
-                {miniView ?
-                    // when width is LESS than 110 px 
-                    <div className={`presItem-miniSlide ${isSelected ? "active" : ""}`} ref={miniView ? this._dragRef : null}>
-                        {`${this.indexInPres + 1}.`}
-                    </div>
-                    :
-                    // when width is MORE than 110 px 
-                    <div className="presItem-number">
-                        {`${this.indexInPres + 1}.`}
-                    </div>}
-                {miniView ? (null) : <div ref={miniView ? null : this._dragRef} className={`presItem-slide ${isSelected ? "active" : ""}`}
-                    style={{
-                        backgroundColor: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor),
-                        boxShadow: presBoxColor && presBoxColor !== "white" && presBoxColor !== "transparent" ? isSelected ? "0 0 0px 1.5px" + presBoxColor : undefined : undefined
-                    }}>
-                    <div className="presItem-name" style={{ maxWidth: showMore ? (toolbarWidth - 195) : toolbarWidth - 105, cursor: isSelected ? 'text' : 'grab' }}>
-                        <EditableView
-                            ref={this._titleRef}
-                            editing={!isSelected ? false : undefined}
-                            contents={activeItem.title}
-                            overflow={'ellipsis'}
-                            GetValue={() => StrCast(activeItem.title)}
-                            SetValue={this.onSetValue}
-                        />
-                    </div>
-                    <Tooltip title={<><div className="dash-tooltip">{"Movement speed"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.transition}</div></Tooltip>
-                    <Tooltip title={<><div className="dash-tooltip">{"Duration"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.duration}</div></Tooltip>
-                    <div className={"presItem-slideButtons"}>
-                        <Tooltip title={<><div className="dash-tooltip">{"Update view"}</div></>}>
-                            <div className="slideButton"
-                                onClick={() => this.updateView(targetDoc, activeItem)}
-                                style={{ fontWeight: 700, display: activeItem.presPinView ? "flex" : "none" }}>V</div>
-                        </Tooltip>
-
-                        {this.recordingIsInOverlay ?
-                            <Tooltip title={<><div className="dash-tooltip">{"Hide Recording"}</div></>}>
-                                <div className="slideButton"
-                                    onClick={this.hideRecording}
-                                    style={{ fontWeight: 700 }}>
-                                    <FontAwesomeIcon icon={"video-slash"} onPointerDown={e => e.stopPropagation()} />
-                                </div>
-                            </Tooltip> :
-                            <Tooltip title={<><div className="dash-tooltip">{"Start recording"}</div></>}>
-                                <div className="slideButton"
-                                    onClick={() => this.startRecording(targetDoc, activeItem)}
-                                    style={{ fontWeight: 700 }}>
-                                    <FontAwesomeIcon icon={"video"} onPointerDown={e => e.stopPropagation()} />
-                                </div>
-                            </Tooltip>
-                        }
-
-
-                        {this.indexInPres === 0 ? (null) : <Tooltip title={<><div className="dash-tooltip">{activeItem.groupWithUp ? "Ungroup" : "Group with up"}</div></>}>
-                            <div className="slideButton"
-                                onClick={() => activeItem.groupWithUp = !activeItem.groupWithUp}
-                                style={{
-                                    zIndex: 1000 - this.indexInPres,
-                                    fontWeight: 700,
-                                    backgroundColor: activeItem.groupWithUp ? presColorBool ? presBoxColor : Colors.MEDIUM_BLUE : undefined,
-                                    height: activeItem.groupWithUp ? 53 : 18,
-                                    transform: activeItem.groupWithUp ? "translate(0, -17px)" : undefined
-                                }}>
-                                <div style={{ transform: activeItem.groupWithUp ? "rotate(180deg) translate(0, -17.5px)" : "rotate(0deg)" }}>
-                                    <FontAwesomeIcon icon={"arrow-up"} onPointerDown={e => e.stopPropagation()} />
-                                </div>
-                            </div>
-                        </Tooltip>}
-                        {/* <Tooltip title={<><div className="dash-tooltip">{this.rootDoc.presExpandInlineButton ? "Minimize" : "Expand"}</div></>}><div className={"slideButton"} onClick={e => { e.stopPropagation(); this.presExpandDocumentClick(); }}>
+      }
+
+      @computed
+      get toolbarWidth(): number {
+            const presBoxDocView = DocumentManager.Instance.getDocumentView(this.presBox);
+            let width: number = NumCast(this.presBox._width);
+            if (presBoxDocView) width = presBoxDocView.props.PanelWidth();
+            if (width === 0) width = 300;
+            return width;
+      }
+
+      @computed get mainItem() {
+            const isSelected: boolean = PresBox.Instance?._selectedArray.has(this.rootDoc);
+            const toolbarWidth: number = this.toolbarWidth;
+            const showMore: boolean = this.toolbarWidth >= 300;
+            const miniView: boolean = this.toolbarWidth <= 110;
+            const presBox: Doc = this.presBox; //presBox
+            const presBoxColor: string = StrCast(presBox._backgroundColor);
+            const presColorBool: boolean = presBoxColor ? (presBoxColor !== Colors.WHITE && presBoxColor !== "transparent") : false;
+            const targetDoc: Doc = this.targetDoc;
+            const activeItem: Doc = this.rootDoc;
+            return (
+                  <div className={`presItem-container`}
+                        key={this.props.Document[Id] + this.indexInPres}
+                        ref={this._itemRef}
+                        style={{
+                              backgroundColor: presColorBool ? isSelected ? "rgba(250,250,250,0.3)" : "transparent" : isSelected ? Colors.LIGHT_BLUE : "transparent",
+                              opacity: this._dragging ? 0.3 : 1
+                        }}
+                        onClick={e => {
+                              e.stopPropagation();
+                              e.preventDefault();
+                              PresBox.Instance.modifierSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, !e.shiftKey && !e.ctrlKey && !e.metaKey, e.ctrlKey || e.metaKey, e.shiftKey);
+                              this.showRecording(activeItem);
+                        }}
+                        onDoubleClick={action(e => {
+                              this.toggleProperties();
+                              PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, true);
+                        })}
+                        onPointerOver={this.onPointerOver}
+                        onPointerLeave={this.onPointerLeave}
+                        onPointerDown={this.headerDown}
+                        onPointerUp={this.headerUp}
+                  >
+                        {miniView ?
+                              // when width is LESS than 110 px 
+                              <div className={`presItem-miniSlide ${isSelected ? "active" : ""}`} ref={miniView ? this._dragRef : null}>
+                                    {`${this.indexInPres + 1}.`}
+                              </div>
+                              :
+                              // when width is MORE than 110 px 
+                              <div className="presItem-number">
+                                    {`${this.indexInPres + 1}.`}
+                              </div>}
+                        {miniView ? (null) : <div ref={miniView ? null : this._dragRef} className={`presItem-slide ${isSelected ? "active" : ""}`}
+                              style={{
+                                    backgroundColor: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor),
+                                    boxShadow: presBoxColor && presBoxColor !== "white" && presBoxColor !== "transparent" ? isSelected ? "0 0 0px 1.5px" + presBoxColor : undefined : undefined
+                              }}>
+                              <div className="presItem-name" style={{ maxWidth: showMore ? (toolbarWidth - 195) : toolbarWidth - 105, cursor: isSelected ? 'text' : 'grab' }}>
+                                    <EditableView
+                                          ref={this._titleRef}
+                                          editing={!isSelected ? false : undefined}
+                                          contents={activeItem.title}
+                                          overflow={'ellipsis'}
+                                          GetValue={() => StrCast(activeItem.title)}
+                                          SetValue={this.onSetValue}
+                                    />
+                              </div>
+                              <Tooltip title={<><div className="dash-tooltip">{"Movement speed"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.transition}</div></Tooltip>
+                              <Tooltip title={<><div className="dash-tooltip">{"Duration"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.duration}</div></Tooltip>
+                              <div className={"presItem-slideButtons"}>
+                                    <Tooltip title={<><div className="dash-tooltip">{"Update view"}</div></>}>
+                                          <div className="slideButton"
+                                                onClick={() => this.updateView(targetDoc, activeItem)}
+                                                style={{ fontWeight: 700, display: activeItem.presPinView ? "flex" : "none" }}>V</div>
+                                    </Tooltip>
+
+                                    {this.recordingIsInOverlay ?
+                                          <Tooltip title={<><div className="dash-tooltip">{"Hide Recording"}</div></>}>
+                                                <div className="slideButton"
+                                                      onClick={this.hideRecording}
+                                                      style={{ fontWeight: 700 }}>
+                                                      <FontAwesomeIcon icon={"video-slash"} onPointerDown={e => e.stopPropagation()} />
+                                                </div>
+                                          </Tooltip> :
+                                          <Tooltip title={<><div className="dash-tooltip">{"Start recording"}</div></>}>
+                                                <div className="slideButton"
+                                                      onClick={() => this.startRecording(activeItem)}
+                                                      style={{ fontWeight: 700 }}>
+                                                      <FontAwesomeIcon icon={"video"} onPointerDown={e => e.stopPropagation()} />
+                                                </div>
+                                          </Tooltip>
+                                    }
+
+
+                                    {this.indexInPres === 0 ? (null) : <Tooltip title={<><div className="dash-tooltip">{activeItem.groupWithUp ? "Ungroup" : "Group with up"}</div></>}>
+                                          <div className="slideButton"
+                                                onClick={() => activeItem.groupWithUp = !activeItem.groupWithUp}
+                                                style={{
+                                                      zIndex: 1000 - this.indexInPres,
+                                                      fontWeight: 700,
+                                                      backgroundColor: activeItem.groupWithUp ? presColorBool ? presBoxColor : Colors.MEDIUM_BLUE : undefined,
+                                                      height: activeItem.groupWithUp ? 53 : 18,
+                                                      transform: activeItem.groupWithUp ? "translate(0, -17px)" : undefined
+                                                }}>
+                                                <div style={{ transform: activeItem.groupWithUp ? "rotate(180deg) translate(0, -17.5px)" : "rotate(0deg)" }}>
+                                                      <FontAwesomeIcon icon={"arrow-up"} onPointerDown={e => e.stopPropagation()} />
+                                                </div>
+                                          </div>
+                                    </Tooltip>}
+                                    {/* <Tooltip title={<><div className="dash-tooltip">{this.rootDoc.presExpandInlineButton ? "Minimize" : "Expand"}</div></>}><div className={"slideButton"} onClick={e => { e.stopPropagation(); this.presExpandDocumentClick(); }}>
                                           <FontAwesomeIcon icon={this.rootDoc.presExpandInlineButton ? "eye-slash" : "eye"} onPointerDown={e => e.stopPropagation()} />
                                     </div></Tooltip> */}
-                        <Tooltip title={<><div className="dash-tooltip">{"Remove from presentation"}</div></>}><div
-                            className={"slideButton"}
-                            onClick={this.removeItem}>
-                            <FontAwesomeIcon icon={"trash"} onPointerDown={e => e.stopPropagation()} />
-                        </div></Tooltip>
-                    </div>
-                    <div className="presItem-docName" style={{ maxWidth: showMore ? (toolbarWidth - 195) : toolbarWidth - 105 }}>{activeItem.presPinView ? (<><i>View of </i> {targetDoc.title}</>) : targetDoc.title}</div>
-                    {this.renderEmbeddedInline}
-                </div>}
-            </div >);
-    }
-
-    render() {
-        return !(this.rootDoc instanceof Doc) || this.targetDoc instanceof Promise ? (null) : this.mainItem;
-    }
+                                    <Tooltip title={<><div className="dash-tooltip">{"Remove from presentation"}</div></>}><div
+                                          className={"slideButton"}
+                                          onClick={this.removeItem}>
+                                          <FontAwesomeIcon icon={"trash"} onPointerDown={e => e.stopPropagation()} />
+                                    </div></Tooltip>
+                              </div>
+                              <div className="presItem-docName" style={{ maxWidth: showMore ? (toolbarWidth - 195) : toolbarWidth - 105 }}>{activeItem.presPinView ? (<><i>View of </i> {targetDoc.title}</>) : targetDoc.title}</div>
+                              {this.renderEmbeddedInline}
+                        </div>}
+                  </div >);
+      }
+
+      render() {
+            return !(this.rootDoc instanceof Doc) || this.targetDoc instanceof Promise ? (null) : this.mainItem;
+      }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 19f0eca0f5f1b0d12ac369f149caf787f88dd9d6 Mon Sep 17 00:00:00 2001
From: Jenny Yu <jennyyu212@outlook.com>
Date: Thu, 12 May 2022 01:39:26 -0400
Subject: feat: added checkbox for optional screen tracking

---
 .../views/nodes/RecordingBox/RecordingBox.tsx      | 11 ++-
 .../views/nodes/RecordingBox/RecordingView.scss    | 30 +++++---
 .../views/nodes/RecordingBox/RecordingView.tsx     | 83 +++++++---------------
 src/client/views/nodes/VideoBox.tsx                |  5 +-
 4 files changed, 54 insertions(+), 75 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 807624394..e5b71c183 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -38,26 +38,23 @@ export class RecordingBox extends ViewBoxBaseComponent() {
       }
 
       @action
-      setResult = (info: Upload.FileInformation) => {
-            // console.log("Setting result to " + info)
+      setResult = (info: Upload.FileInformation, trackScreen: boolean) => {
             this.result = info
-            // console.log(this.result.accessPaths.agnostic.client)
             this.dataDoc.type = DocumentType.VID;
-            // console.log(this.videoDuration)
             this.dataDoc[this.fieldKey + "-duration"] = this.videoDuration;
 
             this.dataDoc.layout = VideoBox.LayoutString(this.fieldKey);
             this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.agnostic.client);
             this.dataDoc[this.fieldKey + "-recorded"] = true;
             // stringify the presenation and store it
-            this.dataDoc[this.fieldKey + "-presentation"] = JSON.stringify(RecordingApi.Instance.clear());
+            if (trackScreen) {
+                  this.dataDoc[this.fieldKey + "-presentation"] = JSON.stringify(RecordingApi.Instance.clear());
+            }
       }
 
       render() {
             return <div className="recordingBox" ref={this._ref}>
                   {!this.result && <RecordingView setResult={this.setResult} setDuration={this.setVideoDuration} />}
-                  {/* {!this.result ? <RecordingView setResult={this.setResult} /> :
-                        <p>video box</p>} */}
             </div>;
       }
 }
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.scss b/src/client/views/nodes/RecordingBox/RecordingView.scss
index c55af5952..9b2f6d070 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.scss
+++ b/src/client/views/nodes/RecordingBox/RecordingView.scss
@@ -1,5 +1,5 @@
 video {
-    // flex: 100%;
+      // flex: 100%;
       width: 100%;
       // min-height: 400px;
       //height: auto;
@@ -22,12 +22,12 @@ button {
 }
 
 .video-wrapper {
-    //   max-width: 600px;
-    //   max-width: 700px;
+      //   max-width: 600px;
+      //   max-width: 700px;
       position: relative;
       display: flex;
       justify-content: center;
-    //   overflow: hidden;
+      //   overflow: hidden;
       border-radius: 10px;
       margin: 0;
 }
@@ -176,7 +176,7 @@ button {
 
 }
 
-.video-edit-wrapper {
+.options-wrapper {
       height: 100%;
       display: flex;
       flex-direction: row;
@@ -184,10 +184,24 @@ button {
       position: absolute;
       top: 0;
       bottom: 0;
-      right: 50% - 15;
 
-      .video-edit-buttons {
-            margin: 0 5px;
+      &.video-edit-wrapper {
+
+            right: 50% - 15;
+
+            .track-screen {
+                  font-weight: 200;
+            }
+
       }
 
+      &.track-screen-wrapper {
+
+            right: 50% - 30;
+
+            .track-screen {
+                  font-weight: 200;
+            }
+
+      }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index efacf7735..e9450a5dd 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -10,20 +10,13 @@ import { Upload } from '../../../../server/SharedMediaTypes';
 
 import { RecordingApi } from '../../../util/RecordingApi';
 
-
-enum RecordingStatus {
-      Recording,
-      Stopped,
-      Paused
-}
-
 interface MediaSegment {
       videoChunks: any[],
       endTime: number
 }
 
 interface IRecordingViewProps {
-      setResult: (info: Upload.FileInformation) => void
+      setResult: (info: Upload.FileInformation, trackScreen: boolean) => void
       setDuration: (seconds: number) => void
 }
 
@@ -36,27 +29,21 @@ export function RecordingView(props: IRecordingViewProps) {
       const [recordingTimer, setRecordingTimer] = useState(0); // unit is 0.01 second
       const [playing, setPlaying] = useState(false);
       const [progress, setProgress] = useState(0);
-      const [speed, setSpeed] = useState(1);
-      const [muted, setMuted] = useState(false);
 
       const [videos, setVideos] = useState<MediaSegment[]>([]);
-      const [currentVid, setCurrentVid] = useState<number>(0);
       const videoRecorder = useRef<MediaRecorder | null>(null);
-      const audioRecorder = useRef<MediaRecorder | null>(null);
       const videoElementRef = useRef<HTMLVideoElement | null>(null);
 
-    const [finished, setFinished] = useState<Boolean>(false)
+      const [finished, setFinished] = useState<boolean>(false)
+      const [trackScreen, setTrackScreen] = useState<boolean>(true)
 
 
 
       const DEFAULT_MEDIA_CONSTRAINTS = {
-            // video: true,
-            // audio: true
             video: {
                   width: 1280,
                   height: 720,
             },
-            // audio: true,
             audio: {
                   echoCancellation: true,
                   noiseSuppression: true,
@@ -80,7 +67,7 @@ export function RecordingView(props: IRecordingViewProps) {
                         .then((data) => {
                               const result = data[0].result
                               if (!(result instanceof Error)) { // convert this screenshotBox into normal videoBox
-                                    props.setResult(result)
+                                    props.setResult(result, trackScreen)
                               } else {
                                     alert("video conversion failed");
                               }
@@ -138,11 +125,9 @@ export function RecordingView(props: IRecordingViewProps) {
       const record = async () => {
             const stream = await startShowingStream();
             videoRecorder.current = new MediaRecorder(stream)
-            // audioRecorder.current = new MediaRecorder(await navigator.mediaDevices.getUserMedia({ audio: true }));
 
             // temporary chunks of video
             let videoChunks: any = []
-            // let audioChunks: any = []
 
             videoRecorder.current.ondataavailable = (event: any) => {
                   if (event.data.size > 0) {
@@ -150,16 +135,9 @@ export function RecordingView(props: IRecordingViewProps) {
                   }
             }
 
-            // audioRecorder.current.ondataavailable = (event: any) => {
-            //       if (event.data.size > 0) {
-            //             audioChunks.push(event.data)
-            //       }
-            // }
-
             videoRecorder.current.onstart = (event: any) => {
-                setRecording(true);
-                // RecordingApi.Instance.clear();
-                RecordingApi.Instance.start();
+                  setRecording(true);
+                  trackScreen && RecordingApi.Instance.start();
             }
 
             videoRecorder.current.onstop = () => {
@@ -172,8 +150,8 @@ export function RecordingView(props: IRecordingViewProps) {
                   // reset the temporary chunks
                   videoChunks = []
                   setRecording(false);
-                setFinished(true);
-                RecordingApi.Instance.pause();
+                  setFinished(true);
+                  trackScreen && RecordingApi.Instance.pause();
             }
 
             // recording paused
@@ -183,14 +161,14 @@ export function RecordingView(props: IRecordingViewProps) {
 
                   // reset the temporary chunks
                   videoChunks = []
-                setRecording(false);
-                RecordingApi.Instance.pause();
+                  setRecording(false);
+                  trackScreen && RecordingApi.Instance.pause();
             }
 
             videoRecorder.current.onresume = async (event: any) => {
                   await startShowingStream();
-                setRecording(true);
-                RecordingApi.Instance.resume();
+                  setRecording(true);
+                  trackScreen && RecordingApi.Instance.resume();
             }
 
             videoRecorder.current.start(200)
@@ -229,18 +207,6 @@ export function RecordingView(props: IRecordingViewProps) {
             setVideos(videos.filter((_, idx) => idx !== numVideos - 1));
       }
 
-      // const handleVideoProgress = (event: any) => {
-      //       const manualChange = Number(event.target.value);
-      //       videoElement!.currentTime = (videoElement!.duration / 100) * manualChange;
-      //       setProgress(manualChange)
-      // };
-
-      // const handleVideoSpeed = (event: any) => {
-      //       const newSpeed = Number(event.target.value);
-      //       videoElement!.playbackRate = speed;
-      //       setSpeed(newSpeed)
-      // };
-
       const handleOnTimeUpdate = () => {
             if (playing) {
                   setVideoProgressHelper(videoElementRef.current!.currentTime)
@@ -256,7 +222,7 @@ export function RecordingView(props: IRecordingViewProps) {
             return toTwoDigit(minutes) + " : " + toTwoDigit(seconds);
       }
 
-    return (
+      return (
             <div className="recording-container">
                   <div className="video-wrapper">
                         <video id="video"
@@ -277,9 +243,10 @@ export function RecordingView(props: IRecordingViewProps) {
                                                 <button className="record-button" onClick={startOrResume} />
                                           }
                                     </div>
-                                    {!recording && videos.length > 0 ?
 
-                                          <div className="video-edit-wrapper">
+                                    {!recording && (videos.length > 0 ?
+
+                                          <div className="options-wrapper video-edit-wrapper">
                                                 {/* <IconContext.Provider value={{ color: "grey", className: "video-edit-buttons" }}>
                                                       <MdBackspace onClick={clearPrevious} />
                                                 </IconContext.Provider> */}
@@ -288,7 +255,13 @@ export function RecordingView(props: IRecordingViewProps) {
                                                 </IconContext.Provider>
                                           </div>
 
-                                          : <></>}
+                                          : <div className="options-wrapper track-screen-wrapper">
+                                                <label className="track-screen">
+                                                      <input type="checkbox" checked={trackScreen} onChange={(e) => { setTrackScreen(e.target.checked) }} />
+                                                      <span className="checkmark"></span>
+                                                      Track Screen
+                                                </label>
+                                          </div>)}
 
                               </div>
 
@@ -297,15 +270,7 @@ export function RecordingView(props: IRecordingViewProps) {
                                     marks={videos.map((elt) => elt.endTime / MAXTIME * 100)}
                               // playSegment={playSegment}
                               />
-
-                              {/* <button className="mute-btn" onClick={() => setMuted(!muted)}>
-                                          {!muted ? (
-                                                <i className="bx bxs-volume-full"></i>
-                                          ) : (
-                                                <i className="bx bxs-volume-mute"></i>
-                                          )}
-                                    </button>  */}
-                  </div>
+                        </div>
                   </div>
             </div>)
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 58e9f390c..902f19716 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -163,8 +163,11 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
 
             // if presentation isn't null, call followmovements on the recording api
             if (this.presentation) {
+                  console.log("presentation isn't null")
                   const err = RecordingApi.Instance.playMovements(this.presentation, this.player?.currentTime || 0, this);
                   err && console.log(err)
+            } else {
+                  console.log("presentation is null")
             }
 
             this._playing = true;
@@ -354,7 +357,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
       // sets video element ref
       @action
       setVideoRef = (vref: HTMLVideoElement | null) => {
-            console.log("SEt video ref " + vref)
+            console.log("Set video ref " + vref)
             this._videoRef = vref;
             if (vref) {
                   this._videoRef!.ontimeupdate = this.updateTimecode;
-- 
cgit v1.2.3-70-g09d2


From 50a16adbcd253ac943d37110e0e3a2a55439984d Mon Sep 17 00:00:00 2001
From: Jenny Yu <jennyyu212@outlook.com>
Date: Thu, 12 May 2022 14:10:13 -0400
Subject: fix: gives recording box unique id to allow multiple streams at the
 same time'

---
 .../views/nodes/RecordingBox/RecordingBox.tsx      |    6 +-
 .../views/nodes/RecordingBox/RecordingView.tsx     |    5 +-
 src/fields/Doc.ts                                  | 2552 ++++++++++----------
 3 files changed, 1283 insertions(+), 1280 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index e5b71c183..159271223 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -9,7 +9,8 @@ import { VideoBox } from "../VideoBox";
 import { RecordingView } from './RecordingView';
 import { DocumentType } from "../../../documents/DocumentTypes";
 import { RecordingApi } from "../../../util/RecordingApi";
-import { Doc } from "../../../../fields/Doc";
+import { Doc, FieldsSym } from "../../../../fields/Doc";
+import { Id } from "../../../../fields/FieldSymbols";
 
 
 @observer
@@ -53,8 +54,9 @@ export class RecordingBox extends ViewBoxBaseComponent() {
       }
 
       render() {
+            // console.log("Proto[Is]: ", this.rootDoc.proto?.[Id])
             return <div className="recordingBox" ref={this._ref}>
-                  {!this.result && <RecordingView setResult={this.setResult} setDuration={this.setVideoDuration} />}
+                  {!this.result && <RecordingView setResult={this.setResult} setDuration={this.setVideoDuration} id={this.rootDoc.proto?.[Id]} />}
             </div>;
       }
 }
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index e9450a5dd..87716e9cc 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -18,6 +18,7 @@ interface MediaSegment {
 interface IRecordingViewProps {
       setResult: (info: Upload.FileInformation, trackScreen: boolean) => void
       setDuration: (seconds: number) => void
+      id: string
 }
 
 const MAXTIME = 100000;
@@ -88,7 +89,7 @@ export function RecordingView(props: IRecordingViewProps) {
 
       useEffect(() => {
             // get access to the video element on every render
-            videoElementRef.current = document.getElementById('video') as HTMLVideoElement;
+            videoElementRef.current = document.getElementById(`video-${props.id}`) as HTMLVideoElement;
       })
 
       useEffect(() => {
@@ -225,7 +226,7 @@ export function RecordingView(props: IRecordingViewProps) {
       return (
             <div className="recording-container">
                   <div className="video-wrapper">
-                        <video id="video"
+                        <video id={`video-${props.id}`}
                               autoPlay
                               muted
                               onTimeUpdate={handleOnTimeUpdate}
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 50e5fcbc4..b07b3a7aa 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -27,37 +27,37 @@ import { deleteProperty, GetEffectiveAcl, getField, getter, inheritParentAcls, m
 import JSZip = require("jszip");
 
 export namespace Field {
-    export function toKeyValueString(doc: Doc, key: string): string {
-        const onDelegate = Object.keys(doc).includes(key);
-        const field = ComputedField.WithoutComputed(() => FieldValue(doc[key]));
-        return !Field.IsField(field) ? "" : (onDelegate ? "=" : "") + (field instanceof ComputedField ? `:=${field.script.originalScript}` : Field.toScriptString(field));
-    }
-    export function toScriptString(field: Field): string {
-        if (typeof field === "string") return `"${field}"`;
-        if (typeof field === "number" || typeof field === "boolean") return String(field);
-        if (field === undefined || field === null) return "null";
-        return field[ToScriptString]();
-    }
-    export function toString(field: Field): string {
-        if (typeof field === "string") return field;
-        if (typeof field === "number" || typeof field === "boolean") return String(field);
-        if (field instanceof ObjectField) return field[ToString]();
-        if (field instanceof RefField) return field[ToString]();
-        return "";
-    }
-    export function IsField(field: any): field is Field;
-    export function IsField(field: any, includeUndefined: true): field is Field | undefined;
-    export function IsField(field: any, includeUndefined: boolean = false): field is Field | undefined {
-        return (typeof field === "string")
-            || (typeof field === "number")
-            || (typeof field === "boolean")
-            || (field instanceof ObjectField)
-            || (field instanceof RefField)
-            || (includeUndefined && field === undefined);
-    }
-    export function Copy(field: any) {
-        return field instanceof ObjectField ? ObjectField.MakeCopy(field) : field;
-    }
+      export function toKeyValueString(doc: Doc, key: string): string {
+            const onDelegate = Object.keys(doc).includes(key);
+            const field = ComputedField.WithoutComputed(() => FieldValue(doc[key]));
+            return !Field.IsField(field) ? "" : (onDelegate ? "=" : "") + (field instanceof ComputedField ? `:=${field.script.originalScript}` : Field.toScriptString(field));
+      }
+      export function toScriptString(field: Field): string {
+            if (typeof field === "string") return `"${field}"`;
+            if (typeof field === "number" || typeof field === "boolean") return String(field);
+            if (field === undefined || field === null) return "null";
+            return field[ToScriptString]();
+      }
+      export function toString(field: Field): string {
+            if (typeof field === "string") return field;
+            if (typeof field === "number" || typeof field === "boolean") return String(field);
+            if (field instanceof ObjectField) return field[ToString]();
+            if (field instanceof RefField) return field[ToString]();
+            return "";
+      }
+      export function IsField(field: any): field is Field;
+      export function IsField(field: any, includeUndefined: true): field is Field | undefined;
+      export function IsField(field: any, includeUndefined: boolean = false): field is Field | undefined {
+            return (typeof field === "string")
+                  || (typeof field === "number")
+                  || (typeof field === "boolean")
+                  || (field instanceof ObjectField)
+                  || (field instanceof RefField)
+                  || (includeUndefined && field === undefined);
+      }
+      export function Copy(field: any) {
+            return field instanceof ObjectField ? ObjectField.MakeCopy(field) : field;
+      }
 }
 export type Field = number | string | boolean | ObjectField | RefField;
 export type Opt<T> = T | undefined;
@@ -73,8 +73,8 @@ export type FieldResult<T extends Field = Field> = Opt<T> | FieldWaiting<Extract
 export function DocListCastAsync(field: FieldResult): Promise<Doc[] | undefined>;
 export function DocListCastAsync(field: FieldResult, defaultValue: Doc[]): Promise<Doc[]>;
 export function DocListCastAsync(field: FieldResult, defaultValue?: Doc[]) {
-    const list = Cast(field, listSpec(Doc));
-    return list ? Promise.all(list).then(() => list) : Promise.resolve(defaultValue);
+      const list = Cast(field, listSpec(Doc));
+      return list ? Promise.all(list).then(() => list) : Promise.resolve(defaultValue);
 }
 
 export async function DocCastAsync(field: FieldResult): Promise<Opt<Doc>> { return Cast(field, Doc); }
@@ -104,1304 +104,1304 @@ export const ForceServerWrite = Symbol("ForceServerWrite");
 export const CachedUpdates = Symbol("Cached updates");
 
 const AclMap = new Map<string, symbol>([
-    ["None", AclUnset],
-    [SharingPermissions.None, AclPrivate],
-    [SharingPermissions.View, AclReadonly],
-    [SharingPermissions.Augment, AclAugment],
-    [SharingPermissions.SelfEdit, AclSelfEdit],
-    [SharingPermissions.Edit, AclEdit],
-    [SharingPermissions.Admin, AclAdmin]
+      ["None", AclUnset],
+      [SharingPermissions.None, AclPrivate],
+      [SharingPermissions.View, AclReadonly],
+      [SharingPermissions.Augment, AclAugment],
+      [SharingPermissions.SelfEdit, AclSelfEdit],
+      [SharingPermissions.Edit, AclEdit],
+      [SharingPermissions.Admin, AclAdmin]
 ]);
 
 // caches the document access permissions for the current user.
 // this recursively updates all protos as well.
 export function updateCachedAcls(doc: Doc) {
-    if (!doc) return;
-    const permissions: { [key: string]: symbol } = {};
+      if (!doc) return;
+      const permissions: { [key: string]: symbol } = {};
 
-    doc[UpdatingFromServer] = true;
-    Object.keys(doc).filter(key => key.startsWith("acl") && (permissions[key] = AclMap.get(StrCast(doc[key]))!));
-    doc[UpdatingFromServer] = false;
+      doc[UpdatingFromServer] = true;
+      Object.keys(doc).filter(key => key.startsWith("acl") && (permissions[key] = AclMap.get(StrCast(doc[key]))!));
+      doc[UpdatingFromServer] = false;
 
-    if (Object.keys(permissions).length) {
-        doc[AclSym] = permissions;
-    }
+      if (Object.keys(permissions).length) {
+            doc[AclSym] = permissions;
+      }
 
-    if (doc.proto instanceof Promise) {
-        doc.proto.then(updateCachedAcls);
-        return doc.proto;
-    }
+      if (doc.proto instanceof Promise) {
+            doc.proto.then(updateCachedAcls);
+            return doc.proto;
+      }
 }
 
 @scriptingGlobal
 @Deserializable("Doc", updateCachedAcls).withFields(["id"])
 export class Doc extends RefField {
-    constructor(id?: FieldId, forceSave?: boolean) {
-        super(id);
-        const doc = new Proxy<this>(this, {
-            set: setter,
-            get: getter,
-            // getPrototypeOf: (target) => Cast(target[SelfProxy].proto, Doc) || null, // TODO this might be able to replace the proto logic in getter
-            has: (target, key) => GetEffectiveAcl(target) !== AclPrivate && key in target.__fields,
-            ownKeys: target => {
-                const obj = {} as any;
-                if (GetEffectiveAcl(target) !== AclPrivate) Object.assign(obj, target.___fieldKeys);
-                runInAction(() => obj.__LAYOUT__ = target.__LAYOUT__);
-                return Object.keys(obj);
-            },
-            getOwnPropertyDescriptor: (target, prop) => {
-                if (prop.toString() === "__LAYOUT__") {
-                    return Reflect.getOwnPropertyDescriptor(target, prop);
-                }
-                if (prop in target.__fieldKeys) {
-                    return {
-                        configurable: true,//TODO Should configurable be true?
-                        enumerable: true,
-                        value: 0//() => target.__fields[prop])
-                    };
-                }
-                return Reflect.getOwnPropertyDescriptor(target, prop);
-            },
-            deleteProperty: deleteProperty,
-            defineProperty: () => { throw new Error("Currently properties can't be defined on documents using Object.defineProperty"); },
-        });
-        this[SelfProxy] = doc;
-        if (!id || forceSave) {
-            DocServer.CreateField(doc);
-        }
-        return doc;
-    }
-
-    proto: Opt<Doc>;
-    [key: string]: FieldResult;
-
-    @serializable(alias("fields", map(autoObject(), { afterDeserialize: afterDocDeserialize })))
-    private get __fields() { return this.___fields; }
-    private set __fields(value) {
-        this.___fields = value;
-        for (const key in value) {
-            const field = value[key];
-            (field !== undefined) && (this.__fieldKeys[key] = true);
-            if (!(field instanceof ObjectField)) continue;
-            field[Parent] = this[Self];
-            field[OnUpdate] = updateFunction(this[Self], key, field, this[SelfProxy]);
-        }
-    }
-    private get __fieldKeys() { return this.___fieldKeys; }
-    private set __fieldKeys(value) { this.___fieldKeys = value; }
-
-    @observable private ___fields: any = {};
-    @observable private ___fieldKeys: any = {};
-    @observable public [AclSym]: { [key: string]: symbol };
-    @observable public [DirectLinksSym]: Set<Doc> = new Set();
-
-    private [UpdatingFromServer]: boolean = false;
-    private [ForceServerWrite]: boolean = false;
-    public [Initializing]: boolean = false;
-
-    private [Update] = (diff: any) => {
-        (!this[UpdatingFromServer] || this[ForceServerWrite]) && DocServer.UpdateField(this[Id], diff);
-    }
-
-    private [Self] = this;
-    private [SelfProxy]: any;
-    public [FieldsSym] = () => this[Self].___fields; // Object.keys(this).reduce((fields, key) => { fields[key] = this[key]; return fields; }, {} as any);
-    public [WidthSym] = () => NumCast(this[SelfProxy]._width);
-    public [HeightSym] = () => NumCast(this[SelfProxy]._height);
-    public [ToScriptString] = () => `idToDoc("${this[Self][Id]}")`;
-    public [ToString] = () => `Doc(${GetEffectiveAcl(this[SelfProxy]) === AclPrivate ? "-inaccessible-" : this[SelfProxy].title})`;
-    public get [LayoutSym]() { return this[SelfProxy].__LAYOUT__; }
-    public get [DataSym]() {
-        const self = this[SelfProxy];
-        return self.resolvedDataDoc && !self.isTemplateForField ? self :
-            Doc.GetProto(Cast(Doc.Layout(self).resolvedDataDoc, Doc, null) || self);
-    }
-    @computed get __LAYOUT__(): Doc | undefined {
-        const templateLayoutDoc = Cast(Doc.LayoutField(this[SelfProxy]), Doc, null);
-        if (templateLayoutDoc) {
-            let renderFieldKey: any;
-            const layoutField = templateLayoutDoc[StrCast(templateLayoutDoc.layoutKey, "layout")];
-            if (typeof layoutField === "string") {
-                renderFieldKey = layoutField.split("fieldKey={'")[1].split("'")[0];//layoutField.split("'")[1];
-            } else {
-                return Cast(layoutField, Doc, null);
+      constructor(id?: FieldId, forceSave?: boolean) {
+            super(id);
+            const doc = new Proxy<this>(this, {
+                  set: setter,
+                  get: getter,
+                  // getPrototypeOf: (target) => Cast(target[SelfProxy].proto, Doc) || null, // TODO this might be able to replace the proto logic in getter
+                  has: (target, key) => GetEffectiveAcl(target) !== AclPrivate && key in target.__fields,
+                  ownKeys: target => {
+                        const obj = {} as any;
+                        if (GetEffectiveAcl(target) !== AclPrivate) Object.assign(obj, target.___fieldKeys);
+                        runInAction(() => obj.__LAYOUT__ = target.__LAYOUT__);
+                        return Object.keys(obj);
+                  },
+                  getOwnPropertyDescriptor: (target, prop) => {
+                        if (prop.toString() === "__LAYOUT__") {
+                              return Reflect.getOwnPropertyDescriptor(target, prop);
+                        }
+                        if (prop in target.__fieldKeys) {
+                              return {
+                                    configurable: true,//TODO Should configurable be true?
+                                    enumerable: true,
+                                    value: 0//() => target.__fields[prop])
+                              };
+                        }
+                        return Reflect.getOwnPropertyDescriptor(target, prop);
+                  },
+                  deleteProperty: deleteProperty,
+                  defineProperty: () => { throw new Error("Currently properties can't be defined on documents using Object.defineProperty"); },
+            });
+            this[SelfProxy] = doc;
+            if (!id || forceSave) {
+                  DocServer.CreateField(doc);
+            }
+            return doc;
+      }
+
+      proto: Opt<Doc>;
+      [key: string]: FieldResult;
+
+      @serializable(alias("fields", map(autoObject(), { afterDeserialize: afterDocDeserialize })))
+      private get __fields() { return this.___fields; }
+      private set __fields(value) {
+            this.___fields = value;
+            for (const key in value) {
+                  const field = value[key];
+                  (field !== undefined) && (this.__fieldKeys[key] = true);
+                  if (!(field instanceof ObjectField)) continue;
+                  field[Parent] = this[Self];
+                  field[OnUpdate] = updateFunction(this[Self], key, field, this[SelfProxy]);
             }
-            return Cast(this[SelfProxy][renderFieldKey + "-layout[" + templateLayoutDoc[Id] + "]"], Doc, null) || templateLayoutDoc;
-        }
-        return undefined;
-
-    }
-
-    private [CachedUpdates]: { [key: string]: () => void | Promise<any> } = {};
-    public static CurrentUserEmail: string = "";
-    public static get CurrentUserEmailNormalized() { return normalizeEmail(Doc.CurrentUserEmail); }
-    public async [HandleUpdate](diff: any) {
-        const set = diff.$set;
-        const sameAuthor = this.author === Doc.CurrentUserEmail;
-        if (set) {
-            for (const key in set) {
-                const fprefix = "fields.";
-                if (!key.startsWith(fprefix)) {
-                    continue;
-                }
-                const fKey = key.substring(fprefix.length);
-                const fn = async () => {
-                    const value = await SerializationHelper.Deserialize(set[key]);
-                    const prev = GetEffectiveAcl(this);
-                    this[UpdatingFromServer] = true;
-                    this[fKey] = value;
-                    this[UpdatingFromServer] = false;
-                    if (fKey.startsWith("acl")) {
-                        updateCachedAcls(this);
-                    }
-                    if (prev === AclPrivate && GetEffectiveAcl(this) !== AclPrivate) {
-                        DocServer.GetRefField(this[Id], true);
-                    }
-                };
-                const writeMode = DocServer.getFieldWriteMode(fKey);
-                if (fKey.startsWith("acl") || writeMode !== DocServer.WriteMode.Playground) {
-                    delete this[CachedUpdates][fKey];
-                    await fn();
-                } else {
-                    this[CachedUpdates][fKey] = fn;
-                }
+      }
+      private get __fieldKeys() { return this.___fieldKeys; }
+      private set __fieldKeys(value) { this.___fieldKeys = value; }
+
+      @observable private ___fields: any = {};
+      @observable private ___fieldKeys: any = {};
+      @observable public [AclSym]: { [key: string]: symbol };
+      @observable public [DirectLinksSym]: Set<Doc> = new Set();
+
+      private [UpdatingFromServer]: boolean = false;
+      private [ForceServerWrite]: boolean = false;
+      public [Initializing]: boolean = false;
+
+      private [Update] = (diff: any) => {
+            (!this[UpdatingFromServer] || this[ForceServerWrite]) && DocServer.UpdateField(this[Id], diff);
+      }
+
+      private [Self] = this;
+      private [SelfProxy]: any;
+      public [FieldsSym] = () => this[Self].___fields; // Object.keys(this).reduce((fields, key) => { fields[key] = this[key]; return fields; }, {} as any);
+      public [WidthSym] = () => NumCast(this[SelfProxy]._width);
+      public [HeightSym] = () => NumCast(this[SelfProxy]._height);
+      public [ToScriptString] = () => `idToDoc("${this[Self][Id]}")`;
+      public [ToString] = () => `Doc(${GetEffectiveAcl(this[SelfProxy]) === AclPrivate ? "-inaccessible-" : this[SelfProxy].title})`;
+      public get [LayoutSym]() { return this[SelfProxy].__LAYOUT__; }
+      public get [DataSym]() {
+            const self = this[SelfProxy];
+            return self.resolvedDataDoc && !self.isTemplateForField ? self :
+                  Doc.GetProto(Cast(Doc.Layout(self).resolvedDataDoc, Doc, null) || self);
+      }
+      @computed get __LAYOUT__(): Doc | undefined {
+            const templateLayoutDoc = Cast(Doc.LayoutField(this[SelfProxy]), Doc, null);
+            if (templateLayoutDoc) {
+                  let renderFieldKey: any;
+                  const layoutField = templateLayoutDoc[StrCast(templateLayoutDoc.layoutKey, "layout")];
+                  if (typeof layoutField === "string") {
+                        renderFieldKey = layoutField.split("fieldKey={'")[1].split("'")[0];//layoutField.split("'")[1];
+                  } else {
+                        return Cast(layoutField, Doc, null);
+                  }
+                  return Cast(this[SelfProxy][renderFieldKey + "-layout[" + templateLayoutDoc[Id] + "]"], Doc, null) || templateLayoutDoc;
             }
-        }
-        const unset = diff.$unset;
-        if (unset) {
-            for (const key in unset) {
-                if (!key.startsWith("fields.")) {
-                    continue;
-                }
-                const fKey = key.substring(7);
-                const fn = () => {
-                    this[UpdatingFromServer] = true;
-                    delete this[fKey];
-                    this[UpdatingFromServer] = false;
-                };
-                if (sameAuthor || DocServer.getFieldWriteMode(fKey) !== DocServer.WriteMode.Playground) {
-                    delete this[CachedUpdates][fKey];
-                    await fn();
-                } else {
-                    this[CachedUpdates][fKey] = fn;
-                }
+            return undefined;
+
+      }
+
+      private [CachedUpdates]: { [key: string]: () => void | Promise<any> } = {};
+      public static CurrentUserEmail: string = "";
+      public static get CurrentUserEmailNormalized() { return normalizeEmail(Doc.CurrentUserEmail); }
+      public async [HandleUpdate](diff: any) {
+            const set = diff.$set;
+            const sameAuthor = this.author === Doc.CurrentUserEmail;
+            if (set) {
+                  for (const key in set) {
+                        const fprefix = "fields.";
+                        if (!key.startsWith(fprefix)) {
+                              continue;
+                        }
+                        const fKey = key.substring(fprefix.length);
+                        const fn = async () => {
+                              const value = await SerializationHelper.Deserialize(set[key]);
+                              const prev = GetEffectiveAcl(this);
+                              this[UpdatingFromServer] = true;
+                              this[fKey] = value;
+                              this[UpdatingFromServer] = false;
+                              if (fKey.startsWith("acl")) {
+                                    updateCachedAcls(this);
+                              }
+                              if (prev === AclPrivate && GetEffectiveAcl(this) !== AclPrivate) {
+                                    DocServer.GetRefField(this[Id], true);
+                              }
+                        };
+                        const writeMode = DocServer.getFieldWriteMode(fKey);
+                        if (fKey.startsWith("acl") || writeMode !== DocServer.WriteMode.Playground) {
+                              delete this[CachedUpdates][fKey];
+                              await fn();
+                        } else {
+                              this[CachedUpdates][fKey] = fn;
+                        }
+                  }
+            }
+            const unset = diff.$unset;
+            if (unset) {
+                  for (const key in unset) {
+                        if (!key.startsWith("fields.")) {
+                              continue;
+                        }
+                        const fKey = key.substring(7);
+                        const fn = () => {
+                              this[UpdatingFromServer] = true;
+                              delete this[fKey];
+                              this[UpdatingFromServer] = false;
+                        };
+                        if (sameAuthor || DocServer.getFieldWriteMode(fKey) !== DocServer.WriteMode.Playground) {
+                              delete this[CachedUpdates][fKey];
+                              await fn();
+                        } else {
+                              this[CachedUpdates][fKey] = fn;
+                        }
+                  }
             }
-        }
-    }
+      }
 }
 
 export namespace Doc {
-    // export function GetAsync(doc: Doc, key: string, ignoreProto: boolean = false): Promise<Field | undefined> {
-    //     const self = doc[Self];
-    //     return new Promise(res => getField(self, key, ignoreProto, res));
-    // }
-    // export function GetTAsync<T extends Field>(doc: Doc, key: string, ctor: ToConstructor<T>, ignoreProto: boolean = false): Promise<T | undefined> {
-    //     return new Promise(async res => {
-    //         const field = await GetAsync(doc, key, ignoreProto);
-    //         return Cast(field, ctor);
-    //     });
-    // }
-
-    export function RunCachedUpdate(doc: Doc, field: string) {
-        const update = doc[CachedUpdates][field];
-        if (update) {
-            update();
-            delete doc[CachedUpdates][field];
-        }
-    }
-    export function AddCachedUpdate(doc: Doc, field: string, oldValue: any) {
-        const val = oldValue;
-        doc[CachedUpdates][field] = () => {
-            doc[UpdatingFromServer] = true;
-            doc[field] = val;
-            doc[UpdatingFromServer] = false;
-        };
-    }
-    export function MakeReadOnly(): { end(): void } {
-        makeReadOnly();
-        return {
-            end() {
-                makeEditable();
+      // export function GetAsync(doc: Doc, key: string, ignoreProto: boolean = false): Promise<Field | undefined> {
+      //     const self = doc[Self];
+      //     return new Promise(res => getField(self, key, ignoreProto, res));
+      // }
+      // export function GetTAsync<T extends Field>(doc: Doc, key: string, ctor: ToConstructor<T>, ignoreProto: boolean = false): Promise<T | undefined> {
+      //     return new Promise(async res => {
+      //         const field = await GetAsync(doc, key, ignoreProto);
+      //         return Cast(field, ctor);
+      //     });
+      // }
+
+      export function RunCachedUpdate(doc: Doc, field: string) {
+            const update = doc[CachedUpdates][field];
+            if (update) {
+                  update();
+                  delete doc[CachedUpdates][field];
             }
-        };
-    }
+      }
+      export function AddCachedUpdate(doc: Doc, field: string, oldValue: any) {
+            const val = oldValue;
+            doc[CachedUpdates][field] = () => {
+                  doc[UpdatingFromServer] = true;
+                  doc[field] = val;
+                  doc[UpdatingFromServer] = false;
+            };
+      }
+      export function MakeReadOnly(): { end(): void } {
+            makeReadOnly();
+            return {
+                  end() {
+                        makeEditable();
+                  }
+            };
+      }
 
-    export function Get(doc: Doc, key: string, ignoreProto: boolean = false): FieldResult {
-        try {
-            return getField(doc[Self], key, ignoreProto);
-        } catch {
+      export function Get(doc: Doc, key: string, ignoreProto: boolean = false): FieldResult {
+            try {
+                  return getField(doc[Self], key, ignoreProto);
+            } catch {
+                  return doc;
+            }
+      }
+      export function GetT<T extends Field>(doc: Doc, key: string, ctor: ToConstructor<T>, ignoreProto: boolean = false): FieldResult<T> {
+            return Cast(Get(doc, key, ignoreProto), ctor) as FieldResult<T>;
+      }
+      export function IsPrototype(doc: Doc) {
+            return GetT(doc, "isPrototype", "boolean", true);
+      }
+      export function IsBaseProto(doc: Doc) {
+            return GetT(doc, "baseProto", "boolean", true);
+      }
+      export function IsSystem(doc: Doc) {
+            return GetT(doc, "system", "boolean", true);
+      }
+      export async function SetInPlace(doc: Doc, key: string, value: Field | undefined, defaultProto: boolean) {
+            if (key.startsWith("_")) key = key.substring(1);
+            const hasProto = doc.proto instanceof Doc;
+            const onDeleg = Object.getOwnPropertyNames(doc).indexOf(key) !== -1;
+            const onProto = hasProto && Object.getOwnPropertyNames(doc.proto).indexOf(key) !== -1;
+            if (onDeleg || !hasProto || (!onProto && !defaultProto)) {
+                  doc[key] = value;
+            } else doc.proto![key] = value;
+      }
+      export async function SetOnPrototype(doc: Doc, key: string, value: Field) {
+            const proto = Object.getOwnPropertyNames(doc).indexOf("isPrototype") === -1 ? doc.proto : doc;
+
+            if (proto) {
+                  proto[key] = value;
+            }
+      }
+      export function GetAllPrototypes(doc: Doc): Doc[] {
+            const protos: Doc[] = [];
+            let d: Opt<Doc> = doc;
+            while (d) {
+                  protos.push(d);
+                  d = FieldValue(d.proto);
+            }
+            return protos;
+      }
+
+      /**
+       * This function is intended to model Object.assign({}, {}) [https://mzl.la/1Mo3l21], which copies
+       * the values of the properties of a source object into the target.
+       *
+       * This is just a specific, Dash-authored version that serves the same role for our
+       * Doc class.
+       *
+       * @param doc the target document into which you'd like to insert the new fields
+       * @param fields the fields to project onto the target. Its type signature defines a mapping from some string key
+       * to a potentially undefined field, where each entry in this mapping is optional.
+       */
+      export function assign<K extends string>(doc: Doc, fields: Partial<Record<K, Opt<Field>>>, skipUndefineds: boolean = false, isInitializing = false) {
+            isInitializing && (doc[Initializing] = true);
+            for (const key in fields) {
+                  if (fields.hasOwnProperty(key)) {
+                        const value = fields[key];
+                        if (!skipUndefineds || value !== undefined) { // Do we want to filter out undefineds?
+                              doc[key] = value;
+                        }
+                  }
+            }
+            isInitializing && (doc[Initializing] = false);
             return doc;
-        }
-    }
-    export function GetT<T extends Field>(doc: Doc, key: string, ctor: ToConstructor<T>, ignoreProto: boolean = false): FieldResult<T> {
-        return Cast(Get(doc, key, ignoreProto), ctor) as FieldResult<T>;
-    }
-    export function IsPrototype(doc: Doc) {
-        return GetT(doc, "isPrototype", "boolean", true);
-    }
-    export function IsBaseProto(doc: Doc) {
-        return GetT(doc, "baseProto", "boolean", true);
-    }
-    export function IsSystem(doc: Doc) {
-        return GetT(doc, "system", "boolean", true);
-    }
-    export async function SetInPlace(doc: Doc, key: string, value: Field | undefined, defaultProto: boolean) {
-        if (key.startsWith("_")) key = key.substring(1);
-        const hasProto = doc.proto instanceof Doc;
-        const onDeleg = Object.getOwnPropertyNames(doc).indexOf(key) !== -1;
-        const onProto = hasProto && Object.getOwnPropertyNames(doc.proto).indexOf(key) !== -1;
-        if (onDeleg || !hasProto || (!onProto && !defaultProto)) {
-            doc[key] = value;
-        } else doc.proto![key] = value;
-    }
-    export async function SetOnPrototype(doc: Doc, key: string, value: Field) {
-        const proto = Object.getOwnPropertyNames(doc).indexOf("isPrototype") === -1 ? doc.proto : doc;
-
-        if (proto) {
-            proto[key] = value;
-        }
-    }
-    export function GetAllPrototypes(doc: Doc): Doc[] {
-        const protos: Doc[] = [];
-        let d: Opt<Doc> = doc;
-        while (d) {
-            protos.push(d);
-            d = FieldValue(d.proto);
-        }
-        return protos;
-    }
-
-    /**
-     * This function is intended to model Object.assign({}, {}) [https://mzl.la/1Mo3l21], which copies
-     * the values of the properties of a source object into the target.
-     *
-     * This is just a specific, Dash-authored version that serves the same role for our
-     * Doc class.
-     *
-     * @param doc the target document into which you'd like to insert the new fields
-     * @param fields the fields to project onto the target. Its type signature defines a mapping from some string key
-     * to a potentially undefined field, where each entry in this mapping is optional.
-     */
-    export function assign<K extends string>(doc: Doc, fields: Partial<Record<K, Opt<Field>>>, skipUndefineds: boolean = false, isInitializing = false) {
-        isInitializing && (doc[Initializing] = true);
-        for (const key in fields) {
-            if (fields.hasOwnProperty(key)) {
-                const value = fields[key];
-                if (!skipUndefineds || value !== undefined) { // Do we want to filter out undefineds?
-                    doc[key] = value;
-                }
+      }
+
+      // compare whether documents or their protos match
+      export function AreProtosEqual(doc?: Doc, other?: Doc) {
+            if (!doc || !other) return false;
+            const r = (doc === other);
+            const r2 = (Doc.GetProto(doc) === other);
+            const r3 = (Doc.GetProto(other) === doc);
+            const r4 = (Doc.GetProto(doc) === Doc.GetProto(other) && Doc.GetProto(other) !== undefined);
+            return r || r2 || r3 || r4;
+      }
+
+      // Gets the data document for the document.  Note: this is mis-named -- it does not specifically
+      // return the doc's proto, but rather recursively searches through the proto inheritance chain
+      // and returns the document who's proto is undefined or whose proto is marked as a base prototype ('isPrototype').
+      export function GetProto(doc: Doc): Doc {
+            if (doc instanceof Promise) {
+                  // console.log("GetProto: warning: got Promise insead of Doc");
             }
-        }
-        isInitializing && (doc[Initializing] = false);
-        return doc;
-    }
-
-    // compare whether documents or their protos match
-    export function AreProtosEqual(doc?: Doc, other?: Doc) {
-        if (!doc || !other) return false;
-        const r = (doc === other);
-        const r2 = (Doc.GetProto(doc) === other);
-        const r3 = (Doc.GetProto(other) === doc);
-        const r4 = (Doc.GetProto(doc) === Doc.GetProto(other) && Doc.GetProto(other) !== undefined);
-        return r || r2 || r3 || r4;
-    }
-
-    // Gets the data document for the document.  Note: this is mis-named -- it does not specifically
-    // return the doc's proto, but rather recursively searches through the proto inheritance chain
-    // and returns the document who's proto is undefined or whose proto is marked as a base prototype ('isPrototype').
-    export function GetProto(doc: Doc): Doc {
-        if (doc instanceof Promise) {
-            // console.log("GetProto: warning: got Promise insead of Doc");
-        }
-        const proto = doc && (Doc.GetT(doc, "isPrototype", "boolean", true) ? doc : (doc.proto || doc));
-        return proto === doc ? proto : Doc.GetProto(proto);
-    }
-    export function GetDataDoc(doc: Doc): Doc {
-        const proto = Doc.GetProto(doc);
-        return proto === doc ? proto : Doc.GetDataDoc(proto);
-    }
-
-    export function allKeys(doc: Doc): string[] {
-        const results: Set<string> = new Set;
-
-        let proto: Doc | undefined = doc;
-        while (proto) {
-            Object.keys(proto).forEach(key => results.add(key));
-            proto = proto.proto;
-        }
-
-        return Array.from(results);
-    }
-
-    /**
-     * @returns the index of doc toFind in list of docs, -1 otherwise
-     */
-    export function IndexOf(toFind: Doc, list: Doc[], allowProtos: boolean = true) {
-        let index = list.reduce((p, v, i) => (v instanceof Doc && v === toFind) ? i : p, -1);
-        index = allowProtos && index !== -1 ? index : list.reduce((p, v, i) => (v instanceof Doc && Doc.AreProtosEqual(v, toFind)) ? i : p, -1);
-        return index; // list.findIndex(doc => doc === toFind || Doc.AreProtosEqual(doc, toFind));
-    }
-
-    /**
-     * Removes doc from the list of Docs at listDoc[fieldKey]
-     * @returns true if successful, false otherwise.
-     */
-    export function RemoveDocFromList(listDoc: Doc, fieldKey: string | undefined, doc: Doc) {
-        const key = fieldKey ? fieldKey : Doc.LayoutFieldKey(listDoc);
-        if (listDoc[key] === undefined) {
-            Doc.GetProto(listDoc)[key] = new List<Doc>();
-        }
-        const list = Cast(listDoc[key], listSpec(Doc));
-        if (list) {
-            const ind = list.indexOf(doc);
-            if (ind !== -1) {
-                list.splice(ind, 1);
-                return true;
+            const proto = doc && (Doc.GetT(doc, "isPrototype", "boolean", true) ? doc : (doc.proto || doc));
+            return proto === doc ? proto : Doc.GetProto(proto);
+      }
+      export function GetDataDoc(doc: Doc): Doc {
+            const proto = Doc.GetProto(doc);
+            return proto === doc ? proto : Doc.GetDataDoc(proto);
+      }
+
+      export function allKeys(doc: Doc): string[] {
+            const results: Set<string> = new Set;
+
+            let proto: Doc | undefined = doc;
+            while (proto) {
+                  Object.keys(proto).forEach(key => results.add(key));
+                  proto = proto.proto;
             }
-        }
-        return false;
-    }
-
-    /**
-     * Adds doc to the list of Docs stored at listDoc[fieldKey].
-     * @returns true if successful, false otherwise.
-     */
-    export function AddDocToList(listDoc: Doc, fieldKey: string | undefined, doc: Doc, relativeTo?: Doc, before?: boolean, first?: boolean, allowDuplicates?: boolean, reversed?: boolean) {
-        const key = fieldKey ? fieldKey : Doc.LayoutFieldKey(listDoc);
-        if (listDoc[key] === undefined) {
-            Doc.GetProto(listDoc)[key] = new List<Doc>();
-        }
-        const list = Cast(listDoc[key], listSpec(Doc));
-        if (list) {
-            if (allowDuplicates !== true) {
-                const pind = list.reduce((l, d, i) => d instanceof Doc && d[Id] === doc[Id] ? i : l, -1);
-                if (pind !== -1) {
-                    return true;
-                    //list.splice(pind, 1);  // bcz: this causes schemaView docs in the Catalog to move to the bottom of the schema view when they are dragged even though they haven't left the collection
-                }
+
+            return Array.from(results);
+      }
+
+      /**
+       * @returns the index of doc toFind in list of docs, -1 otherwise
+       */
+      export function IndexOf(toFind: Doc, list: Doc[], allowProtos: boolean = true) {
+            let index = list.reduce((p, v, i) => (v instanceof Doc && v === toFind) ? i : p, -1);
+            index = allowProtos && index !== -1 ? index : list.reduce((p, v, i) => (v instanceof Doc && Doc.AreProtosEqual(v, toFind)) ? i : p, -1);
+            return index; // list.findIndex(doc => doc === toFind || Doc.AreProtosEqual(doc, toFind));
+      }
+
+      /**
+       * Removes doc from the list of Docs at listDoc[fieldKey]
+       * @returns true if successful, false otherwise.
+       */
+      export function RemoveDocFromList(listDoc: Doc, fieldKey: string | undefined, doc: Doc) {
+            const key = fieldKey ? fieldKey : Doc.LayoutFieldKey(listDoc);
+            if (listDoc[key] === undefined) {
+                  Doc.GetProto(listDoc)[key] = new List<Doc>();
             }
-            if (first) {
-                list.splice(0, 0, doc);
+            const list = Cast(listDoc[key], listSpec(Doc));
+            if (list) {
+                  const ind = list.indexOf(doc);
+                  if (ind !== -1) {
+                        list.splice(ind, 1);
+                        return true;
+                  }
             }
-            else {
-                const ind = relativeTo ? list.indexOf(relativeTo) : -1;
-                if (ind === -1) {
-                    if (reversed) list.splice(0, 0, doc);
-                    else list.push(doc);
-                }
-                else {
-                    if (reversed) list.splice(before ? (list.length - ind) + 1 : list.length - ind, 0, doc);
-                    else list.splice(before ? ind : ind + 1, 0, doc);
-                }
+            return false;
+      }
+
+      /**
+       * Adds doc to the list of Docs stored at listDoc[fieldKey].
+       * @returns true if successful, false otherwise.
+       */
+      export function AddDocToList(listDoc: Doc, fieldKey: string | undefined, doc: Doc, relativeTo?: Doc, before?: boolean, first?: boolean, allowDuplicates?: boolean, reversed?: boolean) {
+            const key = fieldKey ? fieldKey : Doc.LayoutFieldKey(listDoc);
+            if (listDoc[key] === undefined) {
+                  Doc.GetProto(listDoc)[key] = new List<Doc>();
             }
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Computes the bounds of the contents of a set of documents.
-     */
-    export function ComputeContentBounds(docList: Doc[]) {
-        const bounds = docList.reduce((bounds, doc) => {
-            const [sptX, sptY] = [NumCast(doc.x), NumCast(doc.y)];
-            const [bptX, bptY] = [sptX + doc[WidthSym](), sptY + doc[HeightSym]()];
-            return {
-                x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y),
-                r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b)
-            };
-        }, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: -Number.MAX_VALUE, b: -Number.MAX_VALUE });
-        return bounds;
-    }
-
-    export function MakeAlias(doc: Doc, id?: string) {
-        const alias = !GetT(doc, "isPrototype", "boolean", true) && doc.proto ? Doc.MakeCopy(doc, undefined, id) : Doc.MakeDelegate(doc, id);
-        const layout = Doc.LayoutField(alias);
-        if (layout instanceof Doc && layout !== alias && layout === Doc.Layout(alias)) {
-            Doc.SetLayout(alias, Doc.MakeAlias(layout));
-        }
-        alias.aliasOf = doc;
-        alias.aliasNumber = Doc.GetProto(doc).aliasNumber = NumCast(Doc.GetProto(doc).aliasNumber) + 1;
-        alias.title = ComputedField.MakeFunction(`renameAlias(this)`);
-        alias.author = Doc.CurrentUserEmail;
-
-        Doc.AddDocToList(Doc.GetProto(doc)[DataSym], "aliases", alias);
-
-        return alias;
-    }
-
-    export async function makeClone(doc: Doc, cloneMap: Map<string, Doc>, linkMap: Map<Doc, Doc>, rtfs: { copy: Doc, key: string, field: RichTextField }[], exclusions: string[], dontCreate: boolean, asBranch: boolean): Promise<Doc> {
-        if (Doc.IsBaseProto(doc)) return doc;
-        if (cloneMap.get(doc[Id])) return cloneMap.get(doc[Id])!;
-        const copy = dontCreate ? asBranch ? (Cast(doc.branchMaster, Doc, null) || doc) : doc : new Doc(undefined, true);
-        cloneMap.set(doc[Id], copy);
-        const fieldExclusions = doc.type === DocumentType.MARKER ? exclusions.filter(ex => ex !== "annotationOn") : exclusions;
-        const filter = [...fieldExclusions, ...Cast(doc.cloneFieldFilter, listSpec("string"), [])];
-        await Promise.all(Object.keys(doc).map(async key => {
-            if (filter.includes(key)) return;
-            const assignKey = (val: any) => !dontCreate && (copy[key] = val);
-            const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key]));
-            const field = ProxyField.WithoutProxy(() => doc[key]);
-            const copyObjectField = async (field: ObjectField) => {
-                const list = await Cast(doc[key], listSpec(Doc));
-                const docs = list && (await DocListCastAsync(list))?.filter(d => d instanceof Doc);
-                if (docs !== undefined && docs.length) {
-                    const clones = await Promise.all(docs.map(async d => Doc.makeClone(d, cloneMap, linkMap, rtfs, exclusions, dontCreate, asBranch)));
-                    !dontCreate && assignKey(new List<Doc>(clones));
-                } else if (doc[key] instanceof Doc) {
-                    assignKey(key.includes("layout[") ? undefined : key.startsWith("layout") ? doc[key] as Doc : await Doc.makeClone(doc[key] as Doc, cloneMap, linkMap, rtfs, exclusions, dontCreate, asBranch)); // reference documents except copy documents that are expanded template fields
-                } else {
-                    !dontCreate && assignKey(ObjectField.MakeCopy(field));
-                    if (field instanceof RichTextField) {
-                        if (field.Data.includes('"audioId":') || field.Data.includes('"textId":') || field.Data.includes('"anchorId":')) {
-                            rtfs.push({ copy, key, field });
+            const list = Cast(listDoc[key], listSpec(Doc));
+            if (list) {
+                  if (allowDuplicates !== true) {
+                        const pind = list.reduce((l, d, i) => d instanceof Doc && d[Id] === doc[Id] ? i : l, -1);
+                        if (pind !== -1) {
+                              return true;
+                              //list.splice(pind, 1);  // bcz: this causes schemaView docs in the Catalog to move to the bottom of the schema view when they are dragged even though they haven't left the collection
                         }
-                    }
-                }
-            };
-            if (key === "proto") {
-                if (doc[key] instanceof Doc) {
-                    assignKey(await Doc.makeClone(doc[key] as Doc, cloneMap, linkMap, rtfs, exclusions, dontCreate, asBranch));
-                }
-            } else if (key === "anchor1" || key === "anchor2") {
-                if (doc[key] instanceof Doc) {
-                    assignKey(await Doc.makeClone(doc[key] as Doc, cloneMap, linkMap, rtfs, exclusions, true, asBranch));
-                }
-            } else {
-                if (field instanceof RefField) {
-                    assignKey(field);
-                } else if (cfield instanceof ComputedField) {
-                    !dontCreate && assignKey(ComputedField.MakeFunction(cfield.script.originalScript));
-                } else if (field instanceof ObjectField) {
-                    await copyObjectField(field);
-                } else if (field instanceof Promise) {
-                    debugger; //This shouldn't happen...
-                } else {
-                    assignKey(field);
-                }
+                  }
+                  if (first) {
+                        list.splice(0, 0, doc);
+                  }
+                  else {
+                        const ind = relativeTo ? list.indexOf(relativeTo) : -1;
+                        if (ind === -1) {
+                              if (reversed) list.splice(0, 0, doc);
+                              else list.push(doc);
+                        }
+                        else {
+                              if (reversed) list.splice(before ? (list.length - ind) + 1 : list.length - ind, 0, doc);
+                              else list.splice(before ? ind : ind + 1, 0, doc);
+                        }
+                  }
+                  return true;
             }
-        }));
-        for (const link of Array.from(doc[DirectLinksSym])) {
-            const linkClone = await Doc.makeClone(link, cloneMap, linkMap, rtfs, exclusions, dontCreate, asBranch);
-            linkMap.set(link, linkClone);
-        }
-        if (!dontCreate) {
-            Doc.SetInPlace(copy, "title", (asBranch ? "BRANCH: " : "CLONE: ") + doc.title, true);
-            asBranch ? (copy.branchOf = doc) : (copy.cloneOf = doc);
-            if (!Doc.IsPrototype(copy)) {
-                Doc.AddDocToList(doc, "branches", Doc.GetProto(copy));
+            return false;
+      }
+
+      /**
+       * Computes the bounds of the contents of a set of documents.
+       */
+      export function ComputeContentBounds(docList: Doc[]) {
+            const bounds = docList.reduce((bounds, doc) => {
+                  const [sptX, sptY] = [NumCast(doc.x), NumCast(doc.y)];
+                  const [bptX, bptY] = [sptX + doc[WidthSym](), sptY + doc[HeightSym]()];
+                  return {
+                        x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y),
+                        r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b)
+                  };
+            }, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: -Number.MAX_VALUE, b: -Number.MAX_VALUE });
+            return bounds;
+      }
+
+      export function MakeAlias(doc: Doc, id?: string) {
+            const alias = !GetT(doc, "isPrototype", "boolean", true) && doc.proto ? Doc.MakeCopy(doc, undefined, id) : Doc.MakeDelegate(doc, id);
+            const layout = Doc.LayoutField(alias);
+            if (layout instanceof Doc && layout !== alias && layout === Doc.Layout(alias)) {
+                  Doc.SetLayout(alias, Doc.MakeAlias(layout));
             }
+            alias.aliasOf = doc;
+            alias.aliasNumber = Doc.GetProto(doc).aliasNumber = NumCast(Doc.GetProto(doc).aliasNumber) + 1;
+            alias.title = ComputedField.MakeFunction(`renameAlias(this)`);
+            alias.author = Doc.CurrentUserEmail;
+
+            Doc.AddDocToList(Doc.GetProto(doc)[DataSym], "aliases", alias);
+
+            return alias;
+      }
+
+      export async function makeClone(doc: Doc, cloneMap: Map<string, Doc>, linkMap: Map<Doc, Doc>, rtfs: { copy: Doc, key: string, field: RichTextField }[], exclusions: string[], dontCreate: boolean, asBranch: boolean): Promise<Doc> {
+            if (Doc.IsBaseProto(doc)) return doc;
+            if (cloneMap.get(doc[Id])) return cloneMap.get(doc[Id])!;
+            const copy = dontCreate ? asBranch ? (Cast(doc.branchMaster, Doc, null) || doc) : doc : new Doc(undefined, true);
             cloneMap.set(doc[Id], copy);
-        }
-        return copy;
-    }
-    export async function MakeClone(doc: Doc, dontCreate: boolean = false, asBranch = false, cloneMap: Map<string, Doc> = new Map()) {
-        const linkMap = new Map<Doc, Doc>();
-        const rtfMap: { copy: Doc, key: string, field: RichTextField }[] = [];
-        const copy = await Doc.makeClone(doc, cloneMap, linkMap, rtfMap, ["cloneOf", "branches", "branchOf"], dontCreate, asBranch);
-        Array.from(linkMap.entries()).map((links: Doc[]) => LinkManager.Instance.addLink(links[1], true));
-        rtfMap.map(({ copy, key, field }) => {
-            const replacer = (match: any, attr: string, id: string, offset: any, string: any) => {
-                const mapped = cloneMap.get(id);
-                return attr + "\"" + (mapped ? mapped[Id] : id) + "\"";
-            };
-            const replacer2 = (match: any, href: string, id: string, offset: any, string: any) => {
-                const mapped = cloneMap.get(id);
-                return href + (mapped ? mapped[Id] : id);
-            };
-            const regex = `(${Doc.localServerPath()})([^"]*)`;
-            const re = new RegExp(regex, "g");
-            copy[key] = new RichTextField(field.Data.replace(/("textId":|"audioId":|"anchorId":)"([^"]+)"/g, replacer).replace(re, replacer2), field.Text);
-        });
-        return { clone: copy, map: cloneMap };
-    }
-
-    export async function Zip(doc: Doc) {
-        // const a = document.createElement("a");
-        // const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`);
-        // a.href = url;
-        // a.download = `DocExport-${this.props.Document[Id]}.zip`;
-        // a.click();
-        const { clone, map } = await Doc.MakeClone(doc, true);
-        function replacer(key: any, value: any) {
-            if (["branchOf", "cloneOf", "context", "cursors"].includes(key)) return undefined;
-            else if (value instanceof Doc) {
-                if (key !== "field" && Number.isNaN(Number(key))) {
-                    const __fields = value[FieldsSym]();
-                    return { id: value[Id], __type: "Doc", fields: __fields };
-                } else {
-                    return { fieldId: value[Id], __type: "proxy" };
-                }
+            const fieldExclusions = doc.type === DocumentType.MARKER ? exclusions.filter(ex => ex !== "annotationOn") : exclusions;
+            const filter = [...fieldExclusions, ...Cast(doc.cloneFieldFilter, listSpec("string"), [])];
+            await Promise.all(Object.keys(doc).map(async key => {
+                  if (filter.includes(key)) return;
+                  const assignKey = (val: any) => !dontCreate && (copy[key] = val);
+                  const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key]));
+                  const field = ProxyField.WithoutProxy(() => doc[key]);
+                  const copyObjectField = async (field: ObjectField) => {
+                        const list = await Cast(doc[key], listSpec(Doc));
+                        const docs = list && (await DocListCastAsync(list))?.filter(d => d instanceof Doc);
+                        if (docs !== undefined && docs.length) {
+                              const clones = await Promise.all(docs.map(async d => Doc.makeClone(d, cloneMap, linkMap, rtfs, exclusions, dontCreate, asBranch)));
+                              !dontCreate && assignKey(new List<Doc>(clones));
+                        } else if (doc[key] instanceof Doc) {
+                              assignKey(key.includes("layout[") ? undefined : key.startsWith("layout") ? doc[key] as Doc : await Doc.makeClone(doc[key] as Doc, cloneMap, linkMap, rtfs, exclusions, dontCreate, asBranch)); // reference documents except copy documents that are expanded template fields
+                        } else {
+                              !dontCreate && assignKey(ObjectField.MakeCopy(field));
+                              if (field instanceof RichTextField) {
+                                    if (field.Data.includes('"audioId":') || field.Data.includes('"textId":') || field.Data.includes('"anchorId":')) {
+                                          rtfs.push({ copy, key, field });
+                                    }
+                              }
+                        }
+                  };
+                  if (key === "proto") {
+                        if (doc[key] instanceof Doc) {
+                              assignKey(await Doc.makeClone(doc[key] as Doc, cloneMap, linkMap, rtfs, exclusions, dontCreate, asBranch));
+                        }
+                  } else if (key === "anchor1" || key === "anchor2") {
+                        if (doc[key] instanceof Doc) {
+                              assignKey(await Doc.makeClone(doc[key] as Doc, cloneMap, linkMap, rtfs, exclusions, true, asBranch));
+                        }
+                  } else {
+                        if (field instanceof RefField) {
+                              assignKey(field);
+                        } else if (cfield instanceof ComputedField) {
+                              !dontCreate && assignKey(ComputedField.MakeFunction(cfield.script.originalScript));
+                        } else if (field instanceof ObjectField) {
+                              await copyObjectField(field);
+                        } else if (field instanceof Promise) {
+                              debugger; //This shouldn't happen...
+                        } else {
+                              assignKey(field);
+                        }
+                  }
+            }));
+            for (const link of Array.from(doc[DirectLinksSym])) {
+                  const linkClone = await Doc.makeClone(link, cloneMap, linkMap, rtfs, exclusions, dontCreate, asBranch);
+                  linkMap.set(link, linkClone);
+            }
+            if (!dontCreate) {
+                  Doc.SetInPlace(copy, "title", (asBranch ? "BRANCH: " : "CLONE: ") + doc.title, true);
+                  asBranch ? (copy.branchOf = doc) : (copy.cloneOf = doc);
+                  if (!Doc.IsPrototype(copy)) {
+                        Doc.AddDocToList(doc, "branches", Doc.GetProto(copy));
+                  }
+                  cloneMap.set(doc[Id], copy);
             }
-            else if (value instanceof ScriptField) return { script: value.script, __type: "script" };
-            else if (value instanceof RichTextField) return { Data: value.Data, Text: value.Text, __type: "RichTextField" };
-            else if (value instanceof ImageField) return { url: value.url.href, __type: "image" };
-            else if (value instanceof PdfField) return { url: value.url.href, __type: "pdf" };
-            else if (value instanceof AudioField) return { url: value.url.href, __type: "audio" };
-            else if (value instanceof VideoField) return { url: value.url.href, __type: "video" };
-            else if (value instanceof WebField) return { url: value.url.href, __type: "web" };
-            else if (value instanceof MapField) return { url: value.url.href, __type: "map" };
-            else if (value instanceof DateField) return { date: value.toString(), __type: "date" };
-            else if (value instanceof ProxyField) return { fieldId: value.fieldId, __type: "proxy" };
-            else if (value instanceof Array && key !== "fields") return { fields: value, __type: "list" };
-            else if (value instanceof ComputedField) return { script: value.script, __type: "computed" };
-            else return value;
-        }
-
-        const docs: { [id: string]: any } = {};
-        Array.from(map.entries()).forEach(f => docs[f[0]] = f[1]);
-        const docString = JSON.stringify({ id: doc[Id], docs }, replacer);
-
-        const zip = new JSZip();
-
-        zip.file(doc.title + ".json", docString);
-
-        // // Generate a directory within the Zip file structure
-        // var img = zip.folder("images");
-
-        // // Add a file to the directory, in this case an image with data URI as contents
-        // img.file("smile.gif", imgData, {base64: true});
-
-        // Generate the zip file asynchronously
-        zip.generateAsync({ type: "blob" })
-            .then((content: any) => {
-                // Force down of the Zip file
-                saveAs(content, doc.title + ".zip"); // glr: Possibly change the name of the document to match the title?
+            return copy;
+      }
+      export async function MakeClone(doc: Doc, dontCreate: boolean = false, asBranch = false, cloneMap: Map<string, Doc> = new Map()) {
+            const linkMap = new Map<Doc, Doc>();
+            const rtfMap: { copy: Doc, key: string, field: RichTextField }[] = [];
+            const copy = await Doc.makeClone(doc, cloneMap, linkMap, rtfMap, ["cloneOf", "branches", "branchOf"], dontCreate, asBranch);
+            Array.from(linkMap.entries()).map((links: Doc[]) => LinkManager.Instance.addLink(links[1], true));
+            rtfMap.map(({ copy, key, field }) => {
+                  const replacer = (match: any, attr: string, id: string, offset: any, string: any) => {
+                        const mapped = cloneMap.get(id);
+                        return attr + "\"" + (mapped ? mapped[Id] : id) + "\"";
+                  };
+                  const replacer2 = (match: any, href: string, id: string, offset: any, string: any) => {
+                        const mapped = cloneMap.get(id);
+                        return href + (mapped ? mapped[Id] : id);
+                  };
+                  const regex = `(${Doc.localServerPath()})([^"]*)`;
+                  const re = new RegExp(regex, "g");
+                  copy[key] = new RichTextField(field.Data.replace(/("textId":|"audioId":|"anchorId":)"([^"]+)"/g, replacer).replace(re, replacer2), field.Text);
             });
-    }
-    //
-    // Determines whether the layout needs to be expanded (as a template).
-    // template expansion is rquired when the layout is a template doc/field and there's a datadoc which isn't equal to the layout template
-    //
-    export function WillExpandTemplateLayout(layoutDoc: Doc, dataDoc?: Doc) {
-        return (layoutDoc.isTemplateForField || layoutDoc.isTemplateDoc) && dataDoc && layoutDoc !== dataDoc;
-    }
-
-    const _pendingMap: Map<string, boolean> = new Map();
-    //
-    // Returns an expanded template layout for a target data document if there is a template relationship
-    // between the two. If so, the layoutDoc is expanded into a new document that inherits the properties
-    // of the original layout while allowing for individual layout properties to be overridden in the expanded layout.
-    // templateArgs should be equivalent to the layout key that generates the template since that's where the template parameters are stored in ()'s at the end of the key.
-    // NOTE:  the template will have references to "@params" -- the template arguments will be assigned to the '@params' field
-    // so that when the @params key is accessed, it will be rewritten as the key that is stored in the 'params' field and
-    // the derefence will then occur on the rootDocument (the original document).
-    // in the future, field references could be written as @<someparam> and then arguments would be passed in the layout key as:
-    //   layout_mytemplate(somparam=somearg).
-    // then any references to @someparam would be rewritten as accesses to 'somearg' on the rootDocument
-    export function expandTemplateLayout(templateLayoutDoc: Doc, targetDoc?: Doc, templateArgs?: string) {
-        const args = templateArgs?.match(/\(([a-zA-Z0-9._\-]*)\)/)?.[1].replace("()", "") || StrCast(templateLayoutDoc.PARAMS);
-        if (!args && !WillExpandTemplateLayout(templateLayoutDoc, targetDoc) || !targetDoc) return templateLayoutDoc;
-
-        const templateField = StrCast(templateLayoutDoc.isTemplateForField);  // the field that the template renders
-        // First it checks if an expanded layout already exists -- if so it will be stored on the dataDoc
-        // using the template layout doc's id as the field key.
-        // If it doesn't find the expanded layout, then it makes a delegate of the template layout and
-        // saves it on the data doc indexed by the template layout's id.
-        //
-        const params = args.split("=").length > 1 ? args.split("=")[0] : "PARAMS";
-        const layoutFielddKey = Doc.LayoutFieldKey(templateLayoutDoc);
-        const expandedLayoutFieldKey = (templateField || layoutFielddKey) + "-layout[" + templateLayoutDoc[Id] + (args ? `(${args})` : "") + "]";
-        let expandedTemplateLayout = targetDoc?.[expandedLayoutFieldKey];
-
-        if (templateLayoutDoc.resolvedDataDoc instanceof Promise) {
-            expandedTemplateLayout = undefined;
-            _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey, true);
-        }
-        else if (expandedTemplateLayout === undefined && !_pendingMap.get(targetDoc[Id] + expandedLayoutFieldKey + args)) {
-            if (templateLayoutDoc.resolvedDataDoc === (targetDoc.rootDocument || Doc.GetProto(targetDoc)) && templateLayoutDoc.PARAMS === StrCast(targetDoc.PARAMS)) {
-                expandedTemplateLayout = templateLayoutDoc; // reuse an existing template layout if its for the same document with the same params
-            } else {
-                templateLayoutDoc.resolvedDataDoc && (templateLayoutDoc = Cast(templateLayoutDoc.proto, Doc, null) || templateLayoutDoc); // if the template has already been applied (ie, a nested template), then use the template's prototype
-                if (!targetDoc[expandedLayoutFieldKey]) {
-                    _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey + args, true);
-                    setTimeout(action(() => {
-                        const newLayoutDoc = Doc.MakeDelegate(templateLayoutDoc, undefined, "[" + templateLayoutDoc.title + "]");
-                        // the template's arguments are stored in params which is derefenced to find
-                        // the actual field key where the parameterized template data is stored.
-                        newLayoutDoc[params] = args !== "..." ? args : ""; // ... signifies the layout has sub template(s) -- so we have to expand the layout for them so that they can get the correct 'rootDocument' field, but we don't need to reassign their params.  it would be better if the 'rootDocument' field could be passed dynamically to avoid have to create instances
-                        newLayoutDoc.rootDocument = targetDoc;
-                        const dataDoc = Doc.GetProto(targetDoc);
-                        newLayoutDoc.resolvedDataDoc = dataDoc;
-                        if (dataDoc[templateField] === undefined && templateLayoutDoc[templateField] instanceof List && (templateLayoutDoc[templateField] as any).length) {
-                            dataDoc[templateField] = ComputedField.MakeFunction(`ObjectField.MakeCopy(templateLayoutDoc["${templateField}"] as List)`, { templateLayoutDoc: Doc.name }, { templateLayoutDoc });
+            return { clone: copy, map: cloneMap };
+      }
+
+      export async function Zip(doc: Doc) {
+            // const a = document.createElement("a");
+            // const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`);
+            // a.href = url;
+            // a.download = `DocExport-${this.props.Document[Id]}.zip`;
+            // a.click();
+            const { clone, map } = await Doc.MakeClone(doc, true);
+            function replacer(key: any, value: any) {
+                  if (["branchOf", "cloneOf", "context", "cursors"].includes(key)) return undefined;
+                  else if (value instanceof Doc) {
+                        if (key !== "field" && Number.isNaN(Number(key))) {
+                              const __fields = value[FieldsSym]();
+                              return { id: value[Id], __type: "Doc", fields: __fields };
+                        } else {
+                              return { fieldId: value[Id], __type: "proxy" };
                         }
-                        targetDoc[expandedLayoutFieldKey] = newLayoutDoc;
+                  }
+                  else if (value instanceof ScriptField) return { script: value.script, __type: "script" };
+                  else if (value instanceof RichTextField) return { Data: value.Data, Text: value.Text, __type: "RichTextField" };
+                  else if (value instanceof ImageField) return { url: value.url.href, __type: "image" };
+                  else if (value instanceof PdfField) return { url: value.url.href, __type: "pdf" };
+                  else if (value instanceof AudioField) return { url: value.url.href, __type: "audio" };
+                  else if (value instanceof VideoField) return { url: value.url.href, __type: "video" };
+                  else if (value instanceof WebField) return { url: value.url.href, __type: "web" };
+                  else if (value instanceof MapField) return { url: value.url.href, __type: "map" };
+                  else if (value instanceof DateField) return { date: value.toString(), __type: "date" };
+                  else if (value instanceof ProxyField) return { fieldId: value.fieldId, __type: "proxy" };
+                  else if (value instanceof Array && key !== "fields") return { fields: value, __type: "list" };
+                  else if (value instanceof ComputedField) return { script: value.script, __type: "computed" };
+                  else return value;
+            }
 
-                        _pendingMap.delete(targetDoc[Id] + expandedLayoutFieldKey + args);
-                    }));
-                }
+            const docs: { [id: string]: any } = {};
+            Array.from(map.entries()).forEach(f => docs[f[0]] = f[1]);
+            const docString = JSON.stringify({ id: doc[Id], docs }, replacer);
+
+            const zip = new JSZip();
+
+            zip.file(doc.title + ".json", docString);
+
+            // // Generate a directory within the Zip file structure
+            // var img = zip.folder("images");
+
+            // // Add a file to the directory, in this case an image with data URI as contents
+            // img.file("smile.gif", imgData, {base64: true});
+
+            // Generate the zip file asynchronously
+            zip.generateAsync({ type: "blob" })
+                  .then((content: any) => {
+                        // Force down of the Zip file
+                        saveAs(content, doc.title + ".zip"); // glr: Possibly change the name of the document to match the title?
+                  });
+      }
+      //
+      // Determines whether the layout needs to be expanded (as a template).
+      // template expansion is rquired when the layout is a template doc/field and there's a datadoc which isn't equal to the layout template
+      //
+      export function WillExpandTemplateLayout(layoutDoc: Doc, dataDoc?: Doc) {
+            return (layoutDoc.isTemplateForField || layoutDoc.isTemplateDoc) && dataDoc && layoutDoc !== dataDoc;
+      }
+
+      const _pendingMap: Map<string, boolean> = new Map();
+      //
+      // Returns an expanded template layout for a target data document if there is a template relationship
+      // between the two. If so, the layoutDoc is expanded into a new document that inherits the properties
+      // of the original layout while allowing for individual layout properties to be overridden in the expanded layout.
+      // templateArgs should be equivalent to the layout key that generates the template since that's where the template parameters are stored in ()'s at the end of the key.
+      // NOTE:  the template will have references to "@params" -- the template arguments will be assigned to the '@params' field
+      // so that when the @params key is accessed, it will be rewritten as the key that is stored in the 'params' field and
+      // the derefence will then occur on the rootDocument (the original document).
+      // in the future, field references could be written as @<someparam> and then arguments would be passed in the layout key as:
+      //   layout_mytemplate(somparam=somearg).
+      // then any references to @someparam would be rewritten as accesses to 'somearg' on the rootDocument
+      export function expandTemplateLayout(templateLayoutDoc: Doc, targetDoc?: Doc, templateArgs?: string) {
+            const args = templateArgs?.match(/\(([a-zA-Z0-9._\-]*)\)/)?.[1].replace("()", "") || StrCast(templateLayoutDoc.PARAMS);
+            if (!args && !WillExpandTemplateLayout(templateLayoutDoc, targetDoc) || !targetDoc) return templateLayoutDoc;
+
+            const templateField = StrCast(templateLayoutDoc.isTemplateForField);  // the field that the template renders
+            // First it checks if an expanded layout already exists -- if so it will be stored on the dataDoc
+            // using the template layout doc's id as the field key.
+            // If it doesn't find the expanded layout, then it makes a delegate of the template layout and
+            // saves it on the data doc indexed by the template layout's id.
+            //
+            const params = args.split("=").length > 1 ? args.split("=")[0] : "PARAMS";
+            const layoutFielddKey = Doc.LayoutFieldKey(templateLayoutDoc);
+            const expandedLayoutFieldKey = (templateField || layoutFielddKey) + "-layout[" + templateLayoutDoc[Id] + (args ? `(${args})` : "") + "]";
+            let expandedTemplateLayout = targetDoc?.[expandedLayoutFieldKey];
+
+            if (templateLayoutDoc.resolvedDataDoc instanceof Promise) {
+                  expandedTemplateLayout = undefined;
+                  _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey, true);
             }
-        }
-        return expandedTemplateLayout instanceof Doc ? expandedTemplateLayout : undefined; // layout is undefined if the expandedTemplateLayout is pending.
-    }
-
-    // if the childDoc is a template for a field, then this will return the expanded layout with its data doc.
-    // otherwise, it just returns the childDoc
-    export function GetLayoutDataDocPair(containerDoc: Doc, containerDataDoc: Opt<Doc>, childDoc: Doc) {
-        if (!childDoc || childDoc instanceof Promise || !Doc.GetProto(childDoc)) {
-            console.log("No, no, no!");
-            return { layout: childDoc, data: childDoc };
-        }
-        const resolvedDataDoc = (Doc.AreProtosEqual(containerDataDoc, containerDoc) || (!childDoc.isTemplateDoc && !childDoc.isTemplateForField && !childDoc.PARAMS) ? undefined : containerDataDoc);
-        return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc, "(" + StrCast(containerDoc.PARAMS) + ")"), data: resolvedDataDoc };
-    }
-
-    export function Overwrite(doc: Doc, overwrite: Doc, copyProto: boolean = false): Doc {
-        Object.keys(doc).forEach(key => {
-            const field = ProxyField.WithoutProxy(() => doc[key]);
-            if (key === "proto" && copyProto) {
-                if (doc.proto instanceof Doc && overwrite.proto instanceof Doc) {
-                    overwrite[key] = Doc.Overwrite(doc[key]!, overwrite.proto);
-                }
-            } else {
-                if (field instanceof RefField) {
-                    overwrite[key] = field;
-                } else if (field instanceof ObjectField) {
-                    overwrite[key] = ObjectField.MakeCopy(field);
-                } else if (field instanceof Promise) {
-                    debugger; //This shouldn't happend...
-                } else {
-                    overwrite[key] = field;
-                }
+            else if (expandedTemplateLayout === undefined && !_pendingMap.get(targetDoc[Id] + expandedLayoutFieldKey + args)) {
+                  if (templateLayoutDoc.resolvedDataDoc === (targetDoc.rootDocument || Doc.GetProto(targetDoc)) && templateLayoutDoc.PARAMS === StrCast(targetDoc.PARAMS)) {
+                        expandedTemplateLayout = templateLayoutDoc; // reuse an existing template layout if its for the same document with the same params
+                  } else {
+                        templateLayoutDoc.resolvedDataDoc && (templateLayoutDoc = Cast(templateLayoutDoc.proto, Doc, null) || templateLayoutDoc); // if the template has already been applied (ie, a nested template), then use the template's prototype
+                        if (!targetDoc[expandedLayoutFieldKey]) {
+                              _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey + args, true);
+                              setTimeout(action(() => {
+                                    const newLayoutDoc = Doc.MakeDelegate(templateLayoutDoc, undefined, "[" + templateLayoutDoc.title + "]");
+                                    // the template's arguments are stored in params which is derefenced to find
+                                    // the actual field key where the parameterized template data is stored.
+                                    newLayoutDoc[params] = args !== "..." ? args : ""; // ... signifies the layout has sub template(s) -- so we have to expand the layout for them so that they can get the correct 'rootDocument' field, but we don't need to reassign their params.  it would be better if the 'rootDocument' field could be passed dynamically to avoid have to create instances
+                                    newLayoutDoc.rootDocument = targetDoc;
+                                    const dataDoc = Doc.GetProto(targetDoc);
+                                    newLayoutDoc.resolvedDataDoc = dataDoc;
+                                    if (dataDoc[templateField] === undefined && templateLayoutDoc[templateField] instanceof List && (templateLayoutDoc[templateField] as any).length) {
+                                          dataDoc[templateField] = ComputedField.MakeFunction(`ObjectField.MakeCopy(templateLayoutDoc["${templateField}"] as List)`, { templateLayoutDoc: Doc.name }, { templateLayoutDoc });
+                                    }
+                                    targetDoc[expandedLayoutFieldKey] = newLayoutDoc;
+
+                                    _pendingMap.delete(targetDoc[Id] + expandedLayoutFieldKey + args);
+                              }));
+                        }
+                  }
+            }
+            return expandedTemplateLayout instanceof Doc ? expandedTemplateLayout : undefined; // layout is undefined if the expandedTemplateLayout is pending.
+      }
+
+      // if the childDoc is a template for a field, then this will return the expanded layout with its data doc.
+      // otherwise, it just returns the childDoc
+      export function GetLayoutDataDocPair(containerDoc: Doc, containerDataDoc: Opt<Doc>, childDoc: Doc) {
+            if (!childDoc || childDoc instanceof Promise || !Doc.GetProto(childDoc)) {
+                  console.log("No, no, no!");
+                  return { layout: childDoc, data: childDoc };
             }
-        });
-
-        return overwrite;
-    }
-
-    export function MakeCopy(doc: Doc, copyProto: boolean = false, copyProtoId?: string, retitle = false): Doc {
-        const copy = new Doc(copyProtoId, true);
-        const exclude = Cast(doc.cloneFieldFilter, listSpec("string"), []);
-        Object.keys(doc).forEach(key => {
-            if (exclude.includes(key)) return;
-            const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key]));
-            const field = ProxyField.WithoutProxy(() => doc[key]);
-            if (key === "proto" && copyProto) {
-                if (doc[key] instanceof Doc) {
-                    copy[key] = Doc.MakeCopy(doc[key]!, false);
-                }
+            const resolvedDataDoc = (Doc.AreProtosEqual(containerDataDoc, containerDoc) || (!childDoc.isTemplateDoc && !childDoc.isTemplateForField && !childDoc.PARAMS) ? undefined : containerDataDoc);
+            return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc, "(" + StrCast(containerDoc.PARAMS) + ")"), data: resolvedDataDoc };
+      }
+
+      export function Overwrite(doc: Doc, overwrite: Doc, copyProto: boolean = false): Doc {
+            Object.keys(doc).forEach(key => {
+                  const field = ProxyField.WithoutProxy(() => doc[key]);
+                  if (key === "proto" && copyProto) {
+                        if (doc.proto instanceof Doc && overwrite.proto instanceof Doc) {
+                              overwrite[key] = Doc.Overwrite(doc[key]!, overwrite.proto);
+                        }
+                  } else {
+                        if (field instanceof RefField) {
+                              overwrite[key] = field;
+                        } else if (field instanceof ObjectField) {
+                              overwrite[key] = ObjectField.MakeCopy(field);
+                        } else if (field instanceof Promise) {
+                              debugger; //This shouldn't happend...
+                        } else {
+                              overwrite[key] = field;
+                        }
+                  }
+            });
+
+            return overwrite;
+      }
+
+      export function MakeCopy(doc: Doc, copyProto: boolean = false, copyProtoId?: string, retitle = false): Doc {
+            const copy = new Doc(copyProtoId, true);
+            const exclude = Cast(doc.cloneFieldFilter, listSpec("string"), []);
+            Object.keys(doc).forEach(key => {
+                  if (exclude.includes(key)) return;
+                  const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key]));
+                  const field = ProxyField.WithoutProxy(() => doc[key]);
+                  if (key === "proto" && copyProto) {
+                        if (doc[key] instanceof Doc) {
+                              copy[key] = Doc.MakeCopy(doc[key]!, false);
+                        }
+                  } else {
+                        if (field instanceof RefField) {
+                              copy[key] = field;
+                        } else if (cfield instanceof ComputedField) {
+                              copy[key] = cfield[Copy]();// ComputedField.MakeFunction(cfield.script.originalScript);
+                        } else if (field instanceof ObjectField) {
+                              copy[key] = doc[key] instanceof Doc ?
+                                    key.includes("layout[") ? undefined : doc[key] : // reference documents except remove documents that are expanded teplate fields
+                                    ObjectField.MakeCopy(field);
+                        } else if (field instanceof Promise) {
+                              debugger; //This shouldn't happend...
+                        } else {
+                              copy[key] = field;
+                        }
+                  }
+            });
+            copy.author = Doc.CurrentUserEmail;
+            if (copyProto) {
+                  Doc.GetProto(copy).context = undefined;
+                  Doc.GetProto(copy).aliases = new List<Doc>([copy]);
             } else {
-                if (field instanceof RefField) {
-                    copy[key] = field;
-                } else if (cfield instanceof ComputedField) {
-                    copy[key] = cfield[Copy]();// ComputedField.MakeFunction(cfield.script.originalScript);
-                } else if (field instanceof ObjectField) {
-                    copy[key] = doc[key] instanceof Doc ?
-                        key.includes("layout[") ? undefined : doc[key] : // reference documents except remove documents that are expanded teplate fields
-                        ObjectField.MakeCopy(field);
-                } else if (field instanceof Promise) {
-                    debugger; //This shouldn't happend...
-                } else {
-                    copy[key] = field;
-                }
+                  Doc.AddDocToList(Doc.GetProto(copy)[DataSym], "aliases", copy);
+            }
+            copy.context = undefined;
+            Doc.UserDoc().defaultAclPrivate && (copy["acl-Public"] = "Not Shared");
+            if (retitle) {
+                  copy.title = incrementTitleCopy(StrCast(copy.title));
+            }
+            return copy;
+      }
+
+
+      export function MakeDelegate(doc: Doc, id?: string, title?: string): Doc;
+      export function MakeDelegate(doc: Opt<Doc>, id?: string, title?: string): Opt<Doc>;
+      export function MakeDelegate(doc: Opt<Doc>, id?: string, title?: string): Opt<Doc> {
+            if (doc) {
+                  const delegate = new Doc(id, true);
+                  delegate[Initializing] = true;
+                  delegate.proto = doc;
+                  delegate.author = Doc.CurrentUserEmail;
+                  if (!Doc.IsSystem(doc)) Doc.AddDocToList(doc[DataSym], "aliases", delegate);
+                  title && (delegate.title = title);
+                  delegate[Initializing] = false;
+                  return delegate;
             }
-        });
-        copy.author = Doc.CurrentUserEmail;
-        if (copyProto) {
-            Doc.GetProto(copy).context = undefined;
-            Doc.GetProto(copy).aliases = new List<Doc>([copy]);
-        } else {
-            Doc.AddDocToList(Doc.GetProto(copy)[DataSym], "aliases", copy);
-        }
-        copy.context = undefined;
-        Doc.UserDoc().defaultAclPrivate && (copy["acl-Public"] = "Not Shared");
-        if (retitle) {
-            copy.title = incrementTitleCopy(StrCast(copy.title));
-        }
-        return copy;
-    }
-
-
-    export function MakeDelegate(doc: Doc, id?: string, title?: string): Doc;
-    export function MakeDelegate(doc: Opt<Doc>, id?: string, title?: string): Opt<Doc>;
-    export function MakeDelegate(doc: Opt<Doc>, id?: string, title?: string): Opt<Doc> {
-        if (doc) {
+            return undefined;
+      }
+
+      // Makes a delegate of a document by first creating a delegate where data should be stored
+      // (ie, the 'data' doc), and then creates another delegate of that (ie, the 'layout' doc).
+      // This is appropriate if you're trying to create a document that behaves like all
+      // regularly created documents (e.g, text docs, pdfs, etc which all have data/layout docs)
+      export function MakeDelegateWithProto(doc: Doc, id?: string, title?: string): Doc {
+            const delegateProto = new Doc();
+            delegateProto[Initializing] = true;
+            delegateProto.proto = doc;
+            delegateProto.author = Doc.CurrentUserEmail;
+            delegateProto.isPrototype = true;
+            title && (delegateProto.title = title);
             const delegate = new Doc(id, true);
             delegate[Initializing] = true;
-            delegate.proto = doc;
+            delegate.proto = delegateProto;
             delegate.author = Doc.CurrentUserEmail;
-            if (!Doc.IsSystem(doc)) Doc.AddDocToList(doc[DataSym], "aliases", delegate);
-            title && (delegate.title = title);
+            Doc.AddDocToList(delegateProto[DataSym], "aliases", delegate);
             delegate[Initializing] = false;
+            delegateProto[Initializing] = false;
             return delegate;
-        }
-        return undefined;
-    }
-
-    // Makes a delegate of a document by first creating a delegate where data should be stored
-    // (ie, the 'data' doc), and then creates another delegate of that (ie, the 'layout' doc).
-    // This is appropriate if you're trying to create a document that behaves like all
-    // regularly created documents (e.g, text docs, pdfs, etc which all have data/layout docs)
-    export function MakeDelegateWithProto(doc: Doc, id?: string, title?: string): Doc {
-        const delegateProto = new Doc();
-        delegateProto[Initializing] = true;
-        delegateProto.proto = doc;
-        delegateProto.author = Doc.CurrentUserEmail;
-        delegateProto.isPrototype = true;
-        title && (delegateProto.title = title);
-        const delegate = new Doc(id, true);
-        delegate[Initializing] = true;
-        delegate.proto = delegateProto;
-        delegate.author = Doc.CurrentUserEmail;
-        Doc.AddDocToList(delegateProto[DataSym], "aliases", delegate);
-        delegate[Initializing] = false;
-        delegateProto[Initializing] = false;
-        return delegate;
-    }
-
-    let _applyCount: number = 0;
-    export function ApplyTemplate(templateDoc: Doc) {
-        if (templateDoc) {
-            const proto = new Doc();
-            proto.author = Doc.CurrentUserEmail;
-            const target = Doc.MakeDelegate(proto);
-            const targetKey = StrCast(templateDoc.layoutKey, "layout");
-            const applied = ApplyTemplateTo(templateDoc, target, targetKey, templateDoc.title + "(..." + _applyCount++ + ")");
-            target.layoutKey = targetKey;
-            applied && (Doc.GetProto(applied).type = templateDoc.type);
-            Doc.UserDoc().defaultAclPrivate && (applied["acl-Public"] = "Not Shared");
-            return applied;
-        }
-        return undefined;
-    }
-    export function ApplyTemplateTo(templateDoc: Doc, target: Doc, targetKey: string, titleTarget: string | undefined) {
-        if (!Doc.AreProtosEqual(target[targetKey] as Doc, templateDoc)) {
-            if (target.resolvedDataDoc) {
-                target[targetKey] = new PrefetchProxy(templateDoc);
-            } else {
-                titleTarget && (Doc.GetProto(target).title = titleTarget);
-                const setDoc = [AclAdmin, AclEdit].includes(GetEffectiveAcl(Doc.GetProto(target))) ? Doc.GetProto(target) : target;
-                setDoc[targetKey] = new PrefetchProxy(templateDoc);
-            }
-        }
-        return target;
-    }
-
-    //
-    //  This function converts a generic field layout display into a field layout that displays a specific
-    // metadata field indicated by the title of the template field (not the default field that it was rendering)
-    //
-    export function MakeMetadataFieldTemplate(templateField: Doc, templateDoc: Opt<Doc>): boolean {
-
-        // find the metadata field key that this template field doc will display (indicated by its title)
-        const metadataFieldKey = StrCast(templateField.isTemplateForField) || StrCast(templateField.title).replace(/^-/, "");
-
-        // update the original template to mark it as a template
-        templateField.isTemplateForField = metadataFieldKey;
-        templateField.title = metadataFieldKey;
-
-        const templateFieldValue = templateField[metadataFieldKey] || templateField[Doc.LayoutFieldKey(templateField)];
-        const templateCaptionValue = templateField.caption;
-        // move any data that the template field had been rendering over to the template doc so that things will still be rendered
-        // when the template field is adjusted to point to the new metadatafield key.
-        // note 1: if the template field contained a list of documents, each of those documents will be converted to templates as well.
-        // note 2: this will not overwrite any field that already exists on the template doc at the field key
-        if (!templateDoc?.[metadataFieldKey] && templateFieldValue instanceof ObjectField) {
-            Cast(templateFieldValue, listSpec(Doc), [])?.map(d => d instanceof Doc && MakeMetadataFieldTemplate(d, templateDoc));
-            (Doc.GetProto(templateField)[metadataFieldKey] = ObjectField.MakeCopy(templateFieldValue));
-        }
-        // get the layout string that the template uses to specify its layout
-        const templateFieldLayoutString = StrCast(Doc.LayoutField(Doc.Layout(templateField)));
-
-        // change it to render the target metadata field instead of what it was rendering before and assign it to the template field layout document.
-        Doc.Layout(templateField).layout = templateFieldLayoutString.replace(/fieldKey={'[^']*'}/, `fieldKey={'${metadataFieldKey}'}`);
-
-        // assign the template field doc a delegate of any extension document that was previously used to render the template field (since extension doc's carry rendering informatino)
-        Doc.Layout(templateField)[metadataFieldKey + "_ext"] = Doc.MakeDelegate(templateField[templateFieldLayoutString?.split("'")[1] + "_ext"] as Doc);
-
-        return true;
-    }
-
-
-    // converts a document id to a url path on the server
-    export function globalServerPath(doc: Doc | string = ""): string {
-        return Utils.prepend("/doc/" + (doc instanceof Doc ? doc[Id] : doc));
-    }
-    // converts a document id to a url path on the server
-    export function localServerPath(doc?: Doc): string {
-        return "/doc/" + (doc ? doc[Id] : "");
-    }
-
-    export function overlapping(doc1: Doc, doc2: Doc, clusterDistance: number) {
-        const doc2Layout = Doc.Layout(doc2);
-        const doc1Layout = Doc.Layout(doc1);
-        const x2 = NumCast(doc2.x) - clusterDistance;
-        const y2 = NumCast(doc2.y) - clusterDistance;
-        const w2 = NumCast(doc2Layout._width) + clusterDistance;
-        const h2 = NumCast(doc2Layout._height) + clusterDistance;
-        const x = NumCast(doc1.x) - clusterDistance;
-        const y = NumCast(doc1.y) - clusterDistance;
-        const w = NumCast(doc1Layout._width) + clusterDistance;
-        const h = NumCast(doc1Layout._height) + clusterDistance;
-        return doc1.z === doc2.z && intersectRect({ left: x, top: y, width: w, height: h }, { left: x2, top: y2, width: w2, height: h2 });
-    }
-
-    export function isBrushedHighlightedDegree(doc: Doc) {
-        return Doc.IsHighlighted(doc) ? DocBrushStatus.highlighted : Doc.IsBrushedDegree(doc);
-    }
-
-    export class DocBrush {
-        BrushedDoc: ObservableMap<Doc, boolean> = new ObservableMap();
-        SearchMatchDoc: ObservableMap<Doc, { searchMatch: number }> = new ObservableMap();
-    }
-    const brushManager = new DocBrush();
-
-    export class DocData {
-        @observable _user_doc: Doc = undefined!;
-        @observable _sharing_doc: Doc = undefined!;
-        @observable _searchQuery: string = "";
-    }
-
-    // the document containing the view layout information - will be the Document itself unless the Document has
-    // a layout field or 'layout' is given.
-    export function Layout(doc: Doc, layout?: Doc): Doc {
-        const overrideLayout = layout && Cast(doc[`${StrCast(layout.isTemplateForField, "data")}-layout[` + layout[Id] + "]"], Doc, null);
-        return overrideLayout || doc[LayoutSym] || doc;
-    }
-    export function SetLayout(doc: Doc, layout: Doc | string) { doc[StrCast(doc.layoutKey, "layout")] = layout; }
-    export function LayoutField(doc: Doc) { return doc[StrCast(doc.layoutKey, "layout")]; }
-    export function LayoutFieldKey(doc: Doc): string { return StrCast(Doc.Layout(doc).layout).split("'")[1]; }
-    export function NativeAspect(doc: Doc, dataDoc?: Doc, useDim?: boolean) {
-        return Doc.NativeWidth(doc, dataDoc, useDim) / (Doc.NativeHeight(doc, dataDoc, useDim) || 1);
-    }
-    export function NativeWidth(doc?: Doc, dataDoc?: Doc, useWidth?: boolean) { return !doc ? 0 : NumCast(doc._nativeWidth, NumCast((dataDoc || doc)[Doc.LayoutFieldKey(doc) + "-nativeWidth"], useWidth ? doc[WidthSym]() : 0)); }
-    export function NativeHeight(doc?: Doc, dataDoc?: Doc, useHeight?: boolean) {
-        const dheight = doc ? NumCast((dataDoc || doc)[Doc.LayoutFieldKey(doc) + "-nativeHeight"], useHeight ? doc[HeightSym]() : 0) : 0;
-        const nheight = doc ? Doc.NativeWidth(doc, dataDoc, useHeight) * doc[HeightSym]() / doc[WidthSym]() : 0;
-        return !doc ? 0 : NumCast(doc._nativeHeight, nheight || dheight);
-    }
-    export function SetNativeWidth(doc: Doc, width: number | undefined, fieldKey?: string) { doc[(fieldKey ?? Doc.LayoutFieldKey(doc)) + "-nativeWidth"] = width; }
-    export function SetNativeHeight(doc: Doc, height: number | undefined, fieldKey?: string) { doc[(fieldKey ?? Doc.LayoutFieldKey(doc)) + "-nativeHeight"] = height; }
-
-
-    const manager = new DocData();
-    export function SearchQuery(): string { return manager._searchQuery; }
-    export function SetSearchQuery(query: string) { runInAction(() => manager._searchQuery = query); }
-    export function UserDoc(): Doc { return manager._user_doc; }
-    export function SharingDoc(): Doc { return Cast(Doc.UserDoc().mySharedDocs, Doc, null); }
-    export function LinkDBDoc(): Doc { return Cast(Doc.UserDoc().myLinkDatabase, Doc, null); }
-    export function SetUserDoc(doc: Doc) { return (manager._user_doc = doc); }
-
-    const isSearchMatchCache = computedFn(function IsSearchMatch(doc: Doc) {
-        return brushManager.SearchMatchDoc.has(doc) ? brushManager.SearchMatchDoc.get(doc) :
-            brushManager.SearchMatchDoc.has(Doc.GetProto(doc)) ? brushManager.SearchMatchDoc.get(Doc.GetProto(doc)) : undefined;
-    });
-    export function IsSearchMatch(doc: Doc) { return isSearchMatchCache(doc); }
-    export function IsSearchMatchUnmemoized(doc: Doc) {
-        return brushManager.SearchMatchDoc.has(doc) ? brushManager.SearchMatchDoc.get(doc) :
-            brushManager.SearchMatchDoc.has(Doc.GetProto(doc)) ? brushManager.SearchMatchDoc.get(Doc.GetProto(doc)) : undefined;
-    }
-    export function SetSearchMatch(doc: Doc, results: { searchMatch: number }) {
-        if (doc && GetEffectiveAcl(doc) !== AclPrivate && GetEffectiveAcl(Doc.GetProto(doc)) !== AclPrivate) {
-            brushManager.SearchMatchDoc.set(doc, results);
-        }
-        return doc;
-    }
-    export function SearchMatchNext(doc: Doc, backward: boolean) {
-        if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc;
-        const result = brushManager.SearchMatchDoc.get(doc);
-        const num = Math.abs(result?.searchMatch || 0) + 1;
-        runInAction(() => result && brushManager.SearchMatchDoc.set(doc, { searchMatch: backward ? -num : num }));
-        return doc;
-    }
-    export function ClearSearchMatches() {
-        brushManager.SearchMatchDoc.clear();
-    }
-
-    const isBrushedCache = computedFn(function IsBrushed(doc: Doc) { return brushManager.BrushedDoc.has(doc) || brushManager.BrushedDoc.has(Doc.GetProto(doc)); });
-    export function IsBrushed(doc: Doc) { return isBrushedCache(doc); }
-
-    export enum DocBrushStatus {
-        unbrushed = 0,
-        protoBrushed = 1,
-        selfBrushed = 2,
-        highlighted = 3
-    }
-    // don't bother memoizing (caching) the result if called from a non-reactive context. (plus this avoids a warning message)
-    export function IsBrushedDegreeUnmemoized(doc: Doc) {
-        if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return DocBrushStatus.unbrushed;
-        return brushManager.BrushedDoc.has(doc) ? DocBrushStatus.selfBrushed : brushManager.BrushedDoc.has(Doc.GetProto(doc)) ? DocBrushStatus.protoBrushed : DocBrushStatus.unbrushed;
-    }
-    export function IsBrushedDegree(doc: Doc) {
-        return computedFn(function IsBrushDegree(doc: Doc) {
-            return Doc.IsBrushedDegreeUnmemoized(doc);
-        })(doc);
-    }
-    export function BrushDoc(doc: Doc) {
-        if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc;
-        brushManager.BrushedDoc.set(doc, true);
-        brushManager.BrushedDoc.set(Doc.GetProto(doc), true);
-        return doc;
-    }
-    export function UnBrushDoc(doc: Doc) {
-        if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc;
-        brushManager.BrushedDoc.delete(doc);
-        brushManager.BrushedDoc.delete(Doc.GetProto(doc));
-        return doc;
-    }
-
-    export function LinkEndpoint(linkDoc: Doc, anchorDoc: Doc) {
-        return Doc.AreProtosEqual(anchorDoc, (linkDoc.anchor1 as Doc).annotationOn as Doc) ||
-            Doc.AreProtosEqual(anchorDoc, linkDoc.anchor1 as Doc) ? "1" : "2";
-    }
-
-    export function linkFollowUnhighlight() {
-        Doc.UnhighlightAll();
-        document.removeEventListener("pointerdown", linkFollowUnhighlight);
-    }
-
-    let _lastDate = 0;
-    export function linkFollowHighlight(destDoc: Doc, dataAndDisplayDocs = true) {
-        linkFollowUnhighlight();
-        Doc.HighlightDoc(destDoc, dataAndDisplayDocs);
-        document.removeEventListener("pointerdown", linkFollowUnhighlight);
-        document.addEventListener("pointerdown", linkFollowUnhighlight);
-        const lastDate = _lastDate = Date.now();
-        window.setTimeout(() => _lastDate === lastDate && linkFollowUnhighlight(), 5000);
-    }
-
-    export class HighlightBrush {
-        @observable HighlightedDoc: Map<Doc, boolean> = new Map();
-    }
-    const highlightManager = new HighlightBrush();
-    export function IsHighlighted(doc: Doc) {
-        if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return false;
-        return highlightManager.HighlightedDoc.get(doc) || highlightManager.HighlightedDoc.get(Doc.GetProto(doc));
-    }
-    export function HighlightDoc(doc: Doc, dataAndDisplayDocs = true) {
-        runInAction(() => {
-            highlightManager.HighlightedDoc.set(doc, true);
-            dataAndDisplayDocs && highlightManager.HighlightedDoc.set(Doc.GetProto(doc), true);
-        });
-    }
-    export function UnHighlightDoc(doc: Doc) {
-        runInAction(() => {
-            highlightManager.HighlightedDoc.set(doc, false);
-            highlightManager.HighlightedDoc.set(Doc.GetProto(doc), false);
-        });
-    }
-    export function UnhighlightAll() {
-        const mapEntries = highlightManager.HighlightedDoc.keys();
-        let docEntry: IteratorResult<Doc>;
-        while (!(docEntry = mapEntries.next()).done) {
-            const targetDoc = docEntry.value;
-            targetDoc && Doc.UnHighlightDoc(targetDoc);
-        }
-
-    }
-    export function UnBrushAllDocs() {
-        brushManager.BrushedDoc.clear();
-    }
-
-    export function getDocTemplate(doc?: Doc) {
-        return !doc ? undefined :
-            doc.isTemplateDoc ? doc :
-                Cast(doc.dragFactory, Doc, null)?.isTemplateDoc ? doc.dragFactory :
-                    Cast(Doc.Layout(doc), Doc, null)?.isTemplateDoc ?
-                        (Cast(Doc.Layout(doc), Doc, null).resolvedDataDoc ? Doc.Layout(doc).proto : Doc.Layout(doc)) :
-                        undefined;
-    }
-
-    export function matchFieldValue(doc: Doc, key: string, value: any): boolean {
-        if (Utils.HasTransparencyFilter(value)) {
-            const isTransparent = (color: string) => color !== "" && (DashColor(color).alpha() !== 1);
-            return isTransparent(StrCast(doc[key]));
-        }
-        if (typeof value === "string") {
-            value = value.replace(`,${Utils.noRecursionHack}`, "");
-        }
-        const fieldVal = key === "#" ? (StrCast(doc.tags).includes(":#" + value + ":") ? StrCast(doc.tags) : undefined) : doc[key];
-        if (Cast(fieldVal, listSpec("string"), []).length) {
-            const vals = Cast(fieldVal, listSpec("string"), []);
-            const docs = vals.some(v => (v as any) instanceof Doc);
-            if (docs) return value === Field.toString(fieldVal as Field);
-            return vals.some(v => v.includes(value));  // bcz: arghh: Todo: comparison should be parameterized as exact, or substring
-        }
-        const fieldStr = Field.toString(fieldVal as Field);
-        return fieldStr.includes(value); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring
-    }
-
-    export function deiconifyView(doc: Doc) {
-        StrCast(doc.layoutKey).split("_")[1] === "icon" && setNativeView(doc);
-    }
-
-    export function setNativeView(doc: any) {
-        const prevLayout = StrCast(doc.layoutKey).split("_")[1];
-        const deiconify = prevLayout === "icon" && StrCast(doc.deiconifyLayout) ? "layout_" + StrCast(doc.deiconifyLayout) : "";
-        prevLayout === "icon" && (doc.deiconifyLayout = undefined);
-        doc.layoutKey = deiconify || "layout";
-    }
-    export function setDocRangeFilter(container: Opt<Doc>, key: string, range?: number[]) {
-        if (!container) return;
-        const docRangeFilters = Cast(container._docRangeFilters, listSpec("string"), []);
-        for (let i = 0; i < docRangeFilters.length; i += 3) {
-            if (docRangeFilters[i] === key) {
-                docRangeFilters.splice(i, 3);
-                break;
+      }
+
+      let _applyCount: number = 0;
+      export function ApplyTemplate(templateDoc: Doc) {
+            if (templateDoc) {
+                  const proto = new Doc();
+                  proto.author = Doc.CurrentUserEmail;
+                  const target = Doc.MakeDelegate(proto);
+                  const targetKey = StrCast(templateDoc.layoutKey, "layout");
+                  const applied = ApplyTemplateTo(templateDoc, target, targetKey, templateDoc.title + "(..." + _applyCount++ + ")");
+                  target.layoutKey = targetKey;
+                  applied && (Doc.GetProto(applied).type = templateDoc.type);
+                  Doc.UserDoc().defaultAclPrivate && (applied["acl-Public"] = "Not Shared");
+                  return applied;
             }
-        }
-        if (range !== undefined) {
-            docRangeFilters.push(key);
-            docRangeFilters.push(range[0].toString());
-            docRangeFilters.push(range[1].toString());
-            container._docRangeFilters = new List<string>(docRangeFilters);
-        }
-    }
-
-    // filters document in a container collection:
-    // all documents with the specified value for the specified key are included/excluded
-    // based on the modifiers :"check", "x", undefined
-    export function setDocFilter(container: Opt<Doc>, key: string, value: any, modifiers: "remove" | "match" | "check" | "x" | "exists" | "unset", toggle?: boolean, fieldSuffix?: string, append: boolean = true) {
-        if (!container) return;
-        const filterField = "_" + (fieldSuffix ? fieldSuffix + "-" : "") + "docFilters";
-        const docFilters = Cast(container[filterField], listSpec("string"), []);
-        runInAction(() => {
-            for (let i = 0; i < docFilters.length; i++) {
-                const fields = docFilters[i].split(":"); // split key:value:modifier
-                if (fields[0] === key && (fields[1] === value || modifiers === "match")) {
-                    if (fields[2] === modifiers && modifiers && fields[1] === value) {
-                        if (toggle) modifiers = "remove";
-                        else return;
-                    }
-                    docFilters.splice(i, 1);
-                    container[filterField] = new List<string>(docFilters);
-                    break;
-                }
+            return undefined;
+      }
+      export function ApplyTemplateTo(templateDoc: Doc, target: Doc, targetKey: string, titleTarget: string | undefined) {
+            if (!Doc.AreProtosEqual(target[targetKey] as Doc, templateDoc)) {
+                  if (target.resolvedDataDoc) {
+                        target[targetKey] = new PrefetchProxy(templateDoc);
+                  } else {
+                        titleTarget && (Doc.GetProto(target).title = titleTarget);
+                        const setDoc = [AclAdmin, AclEdit].includes(GetEffectiveAcl(Doc.GetProto(target))) ? Doc.GetProto(target) : target;
+                        setDoc[targetKey] = new PrefetchProxy(templateDoc);
+                  }
             }
-            if (!docFilters.length && modifiers === "match" && value === undefined) {
-                container[filterField] = undefined;
-            } else if (modifiers !== "remove") {
-                !append && (docFilters.length = 0);
-                docFilters.push(key + ":" + value + ":" + modifiers);
-                container[filterField] = new List<string>(docFilters);
+            return target;
+      }
+
+      //
+      //  This function converts a generic field layout display into a field layout that displays a specific
+      // metadata field indicated by the title of the template field (not the default field that it was rendering)
+      //
+      export function MakeMetadataFieldTemplate(templateField: Doc, templateDoc: Opt<Doc>): boolean {
+
+            // find the metadata field key that this template field doc will display (indicated by its title)
+            const metadataFieldKey = StrCast(templateField.isTemplateForField) || StrCast(templateField.title).replace(/^-/, "");
+
+            // update the original template to mark it as a template
+            templateField.isTemplateForField = metadataFieldKey;
+            templateField.title = metadataFieldKey;
+
+            const templateFieldValue = templateField[metadataFieldKey] || templateField[Doc.LayoutFieldKey(templateField)];
+            const templateCaptionValue = templateField.caption;
+            // move any data that the template field had been rendering over to the template doc so that things will still be rendered
+            // when the template field is adjusted to point to the new metadatafield key.
+            // note 1: if the template field contained a list of documents, each of those documents will be converted to templates as well.
+            // note 2: this will not overwrite any field that already exists on the template doc at the field key
+            if (!templateDoc?.[metadataFieldKey] && templateFieldValue instanceof ObjectField) {
+                  Cast(templateFieldValue, listSpec(Doc), [])?.map(d => d instanceof Doc && MakeMetadataFieldTemplate(d, templateDoc));
+                  (Doc.GetProto(templateField)[metadataFieldKey] = ObjectField.MakeCopy(templateFieldValue));
             }
-        });
-    }
-    export function readDocRangeFilter(doc: Doc, key: string) {
-        const docRangeFilters = Cast(doc._docRangeFilters, listSpec("string"), []);
-        for (let i = 0; i < docRangeFilters.length; i += 3) {
-            if (docRangeFilters[i] === key) {
-                return [Number(docRangeFilters[i + 1]), Number(docRangeFilters[i + 2])];
+            // get the layout string that the template uses to specify its layout
+            const templateFieldLayoutString = StrCast(Doc.LayoutField(Doc.Layout(templateField)));
+
+            // change it to render the target metadata field instead of what it was rendering before and assign it to the template field layout document.
+            Doc.Layout(templateField).layout = templateFieldLayoutString.replace(/fieldKey={'[^']*'}/, `fieldKey={'${metadataFieldKey}'}`);
+
+            // assign the template field doc a delegate of any extension document that was previously used to render the template field (since extension doc's carry rendering informatino)
+            Doc.Layout(templateField)[metadataFieldKey + "_ext"] = Doc.MakeDelegate(templateField[templateFieldLayoutString?.split("'")[1] + "_ext"] as Doc);
+
+            return true;
+      }
+
+
+      // converts a document id to a url path on the server
+      export function globalServerPath(doc: Doc | string = ""): string {
+            return Utils.prepend("/doc/" + (doc instanceof Doc ? doc[Id] : doc));
+      }
+      // converts a document id to a url path on the server
+      export function localServerPath(doc?: Doc): string {
+            return "/doc/" + (doc ? doc[Id] : "");
+      }
+
+      export function overlapping(doc1: Doc, doc2: Doc, clusterDistance: number) {
+            const doc2Layout = Doc.Layout(doc2);
+            const doc1Layout = Doc.Layout(doc1);
+            const x2 = NumCast(doc2.x) - clusterDistance;
+            const y2 = NumCast(doc2.y) - clusterDistance;
+            const w2 = NumCast(doc2Layout._width) + clusterDistance;
+            const h2 = NumCast(doc2Layout._height) + clusterDistance;
+            const x = NumCast(doc1.x) - clusterDistance;
+            const y = NumCast(doc1.y) - clusterDistance;
+            const w = NumCast(doc1Layout._width) + clusterDistance;
+            const h = NumCast(doc1Layout._height) + clusterDistance;
+            return doc1.z === doc2.z && intersectRect({ left: x, top: y, width: w, height: h }, { left: x2, top: y2, width: w2, height: h2 });
+      }
+
+      export function isBrushedHighlightedDegree(doc: Doc) {
+            return Doc.IsHighlighted(doc) ? DocBrushStatus.highlighted : Doc.IsBrushedDegree(doc);
+      }
+
+      export class DocBrush {
+            BrushedDoc: ObservableMap<Doc, boolean> = new ObservableMap();
+            SearchMatchDoc: ObservableMap<Doc, { searchMatch: number }> = new ObservableMap();
+      }
+      const brushManager = new DocBrush();
+
+      export class DocData {
+            @observable _user_doc: Doc = undefined!;
+            @observable _sharing_doc: Doc = undefined!;
+            @observable _searchQuery: string = "";
+      }
+
+      // the document containing the view layout information - will be the Document itself unless the Document has
+      // a layout field or 'layout' is given.
+      export function Layout(doc: Doc, layout?: Doc): Doc {
+            const overrideLayout = layout && Cast(doc[`${StrCast(layout.isTemplateForField, "data")}-layout[` + layout[Id] + "]"], Doc, null);
+            return overrideLayout || doc[LayoutSym] || doc;
+      }
+      export function SetLayout(doc: Doc, layout: Doc | string) { doc[StrCast(doc.layoutKey, "layout")] = layout; }
+      export function LayoutField(doc: Doc) { return doc[StrCast(doc.layoutKey, "layout")]; }
+      export function LayoutFieldKey(doc: Doc): string { return StrCast(Doc.Layout(doc).layout).split("'")[1]; }
+      export function NativeAspect(doc: Doc, dataDoc?: Doc, useDim?: boolean) {
+            return Doc.NativeWidth(doc, dataDoc, useDim) / (Doc.NativeHeight(doc, dataDoc, useDim) || 1);
+      }
+      export function NativeWidth(doc?: Doc, dataDoc?: Doc, useWidth?: boolean) { return !doc ? 0 : NumCast(doc._nativeWidth, NumCast((dataDoc || doc)[Doc.LayoutFieldKey(doc) + "-nativeWidth"], useWidth ? doc[WidthSym]() : 0)); }
+      export function NativeHeight(doc?: Doc, dataDoc?: Doc, useHeight?: boolean) {
+            const dheight = doc ? NumCast((dataDoc || doc)[Doc.LayoutFieldKey(doc) + "-nativeHeight"], useHeight ? doc[HeightSym]() : 0) : 0;
+            const nheight = doc ? Doc.NativeWidth(doc, dataDoc, useHeight) * doc[HeightSym]() / doc[WidthSym]() : 0;
+            return !doc ? 0 : NumCast(doc._nativeHeight, nheight || dheight);
+      }
+      export function SetNativeWidth(doc: Doc, width: number | undefined, fieldKey?: string) { doc[(fieldKey ?? Doc.LayoutFieldKey(doc)) + "-nativeWidth"] = width; }
+      export function SetNativeHeight(doc: Doc, height: number | undefined, fieldKey?: string) { doc[(fieldKey ?? Doc.LayoutFieldKey(doc)) + "-nativeHeight"] = height; }
+
+
+      const manager = new DocData();
+      export function SearchQuery(): string { return manager._searchQuery; }
+      export function SetSearchQuery(query: string) { runInAction(() => manager._searchQuery = query); }
+      export function UserDoc(): Doc { return manager._user_doc; }
+      export function SharingDoc(): Doc { return Cast(Doc.UserDoc().mySharedDocs, Doc, null); }
+      export function LinkDBDoc(): Doc { return Cast(Doc.UserDoc().myLinkDatabase, Doc, null); }
+      export function SetUserDoc(doc: Doc) { return (manager._user_doc = doc); }
+
+      const isSearchMatchCache = computedFn(function IsSearchMatch(doc: Doc) {
+            return brushManager.SearchMatchDoc.has(doc) ? brushManager.SearchMatchDoc.get(doc) :
+                  brushManager.SearchMatchDoc.has(Doc.GetProto(doc)) ? brushManager.SearchMatchDoc.get(Doc.GetProto(doc)) : undefined;
+      });
+      export function IsSearchMatch(doc: Doc) { return isSearchMatchCache(doc); }
+      export function IsSearchMatchUnmemoized(doc: Doc) {
+            return brushManager.SearchMatchDoc.has(doc) ? brushManager.SearchMatchDoc.get(doc) :
+                  brushManager.SearchMatchDoc.has(Doc.GetProto(doc)) ? brushManager.SearchMatchDoc.get(Doc.GetProto(doc)) : undefined;
+      }
+      export function SetSearchMatch(doc: Doc, results: { searchMatch: number }) {
+            if (doc && GetEffectiveAcl(doc) !== AclPrivate && GetEffectiveAcl(Doc.GetProto(doc)) !== AclPrivate) {
+                  brushManager.SearchMatchDoc.set(doc, results);
             }
-        }
-    }
-    export function assignDocToField(doc: Doc, field: string, id: string) {
-        DocServer.GetRefField(id).then(layout => layout instanceof Doc && (doc[field] = layout));
-        return id;
-    }
-
-    export function toggleNativeDimensions(layoutDoc: Doc, contentScale: number, panelWidth: number, panelHeight: number) {
-        runInAction(() => {
-            if (Doc.NativeWidth(layoutDoc) || Doc.NativeHeight(layoutDoc)) {
-                layoutDoc._viewScale = NumCast(layoutDoc._viewScale, 1) * contentScale;
-                layoutDoc._nativeWidth = undefined;
-                layoutDoc._nativeHeight = undefined;
+            return doc;
+      }
+      export function SearchMatchNext(doc: Doc, backward: boolean) {
+            if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc;
+            const result = brushManager.SearchMatchDoc.get(doc);
+            const num = Math.abs(result?.searchMatch || 0) + 1;
+            runInAction(() => result && brushManager.SearchMatchDoc.set(doc, { searchMatch: backward ? -num : num }));
+            return doc;
+      }
+      export function ClearSearchMatches() {
+            brushManager.SearchMatchDoc.clear();
+      }
+
+      const isBrushedCache = computedFn(function IsBrushed(doc: Doc) { return brushManager.BrushedDoc.has(doc) || brushManager.BrushedDoc.has(Doc.GetProto(doc)); });
+      export function IsBrushed(doc: Doc) { return isBrushedCache(doc); }
+
+      export enum DocBrushStatus {
+            unbrushed = 0,
+            protoBrushed = 1,
+            selfBrushed = 2,
+            highlighted = 3
+      }
+      // don't bother memoizing (caching) the result if called from a non-reactive context. (plus this avoids a warning message)
+      export function IsBrushedDegreeUnmemoized(doc: Doc) {
+            if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return DocBrushStatus.unbrushed;
+            return brushManager.BrushedDoc.has(doc) ? DocBrushStatus.selfBrushed : brushManager.BrushedDoc.has(Doc.GetProto(doc)) ? DocBrushStatus.protoBrushed : DocBrushStatus.unbrushed;
+      }
+      export function IsBrushedDegree(doc: Doc) {
+            return computedFn(function IsBrushDegree(doc: Doc) {
+                  return Doc.IsBrushedDegreeUnmemoized(doc);
+            })(doc);
+      }
+      export function BrushDoc(doc: Doc) {
+            if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc;
+            brushManager.BrushedDoc.set(doc, true);
+            brushManager.BrushedDoc.set(Doc.GetProto(doc), true);
+            return doc;
+      }
+      export function UnBrushDoc(doc: Doc) {
+            if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc;
+            brushManager.BrushedDoc.delete(doc);
+            brushManager.BrushedDoc.delete(Doc.GetProto(doc));
+            return doc;
+      }
+
+      export function LinkEndpoint(linkDoc: Doc, anchorDoc: Doc) {
+            return Doc.AreProtosEqual(anchorDoc, (linkDoc.anchor1 as Doc).annotationOn as Doc) ||
+                  Doc.AreProtosEqual(anchorDoc, linkDoc.anchor1 as Doc) ? "1" : "2";
+      }
+
+      export function linkFollowUnhighlight() {
+            Doc.UnhighlightAll();
+            document.removeEventListener("pointerdown", linkFollowUnhighlight);
+      }
+
+      let _lastDate = 0;
+      export function linkFollowHighlight(destDoc: Doc, dataAndDisplayDocs = true) {
+            linkFollowUnhighlight();
+            Doc.HighlightDoc(destDoc, dataAndDisplayDocs);
+            document.removeEventListener("pointerdown", linkFollowUnhighlight);
+            document.addEventListener("pointerdown", linkFollowUnhighlight);
+            const lastDate = _lastDate = Date.now();
+            window.setTimeout(() => _lastDate === lastDate && linkFollowUnhighlight(), 5000);
+      }
+
+      export class HighlightBrush {
+            @observable HighlightedDoc: Map<Doc, boolean> = new Map();
+      }
+      const highlightManager = new HighlightBrush();
+      export function IsHighlighted(doc: Doc) {
+            if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return false;
+            return highlightManager.HighlightedDoc.get(doc) || highlightManager.HighlightedDoc.get(Doc.GetProto(doc));
+      }
+      export function HighlightDoc(doc: Doc, dataAndDisplayDocs = true) {
+            runInAction(() => {
+                  highlightManager.HighlightedDoc.set(doc, true);
+                  dataAndDisplayDocs && highlightManager.HighlightedDoc.set(Doc.GetProto(doc), true);
+            });
+      }
+      export function UnHighlightDoc(doc: Doc) {
+            runInAction(() => {
+                  highlightManager.HighlightedDoc.set(doc, false);
+                  highlightManager.HighlightedDoc.set(Doc.GetProto(doc), false);
+            });
+      }
+      export function UnhighlightAll() {
+            const mapEntries = highlightManager.HighlightedDoc.keys();
+            let docEntry: IteratorResult<Doc>;
+            while (!(docEntry = mapEntries.next()).done) {
+                  const targetDoc = docEntry.value;
+                  targetDoc && Doc.UnHighlightDoc(targetDoc);
             }
-            else {
-                layoutDoc._autoHeight = false;
-                if (!Doc.NativeWidth(layoutDoc)) {
-                    layoutDoc._nativeWidth = NumCast(layoutDoc._width, panelWidth);
-                    layoutDoc._nativeHeight = NumCast(layoutDoc._height, panelHeight);
-                }
+
+      }
+      export function UnBrushAllDocs() {
+            brushManager.BrushedDoc.clear();
+      }
+
+      export function getDocTemplate(doc?: Doc) {
+            return !doc ? undefined :
+                  doc.isTemplateDoc ? doc :
+                        Cast(doc.dragFactory, Doc, null)?.isTemplateDoc ? doc.dragFactory :
+                              Cast(Doc.Layout(doc), Doc, null)?.isTemplateDoc ?
+                                    (Cast(Doc.Layout(doc), Doc, null).resolvedDataDoc ? Doc.Layout(doc).proto : Doc.Layout(doc)) :
+                                    undefined;
+      }
+
+      export function matchFieldValue(doc: Doc, key: string, value: any): boolean {
+            if (Utils.HasTransparencyFilter(value)) {
+                  const isTransparent = (color: string) => color !== "" && (DashColor(color).alpha() !== 1);
+                  return isTransparent(StrCast(doc[key]));
             }
-        });
-    }
-
-    export function isDocPinned(doc: Doc) {
-        //add this new doc to props.Document
-        const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc;
-        return !curPres ? false : DocListCast(curPres.data).findIndex((val) => Doc.AreProtosEqual(val, doc)) !== -1;
-    }
-
-    export function copyDragFactory(dragFactory: Doc) {
-        const ndoc = dragFactory.isTemplateDoc ? Doc.ApplyTemplate(dragFactory) : Doc.MakeCopy(dragFactory, true);
-        ndoc && Doc.AddDocToList(Cast(Doc.UserDoc().myFileOrphans, Doc, null), "data", Doc.GetProto(ndoc));
-        if (ndoc && dragFactory["dragFactory-count"] !== undefined) {
-            dragFactory["dragFactory-count"] = NumCast(dragFactory["dragFactory-count"]) + 1;
-            Doc.SetInPlace(ndoc, "title", ndoc.title + " " + NumCast(dragFactory["dragFactory-count"]).toString(), true);
-        }
-
-        if (ndoc) inheritParentAcls(CurrentUserUtils.ActiveDashboard, ndoc);
-
-        return ndoc;
-    }
-    export function delegateDragFactory(dragFactory: Doc) {
-        const ndoc = Doc.MakeDelegateWithProto(dragFactory);
-        if (ndoc && dragFactory["dragFactory-count"] !== undefined) {
-            dragFactory["dragFactory-count"] = NumCast(dragFactory["dragFactory-count"]) + 1;
-            Doc.GetProto(ndoc).title = ndoc.title + " " + NumCast(dragFactory["dragFactory-count"]).toString();
-        }
-        return ndoc;
-    }
-
-    export function toIcon(doc?: Doc, isOpen?: boolean) {
-        switch (StrCast(doc?.type)) {
-            case DocumentType.IMG: return "image";
-            case DocumentType.COMPARISON: return "columns";
-            case DocumentType.RTF: return "sticky-note";
-            case DocumentType.COL:
-                const folder: IconProp = isOpen ? "folder-open" : "folder";
-                const chevron: IconProp = isOpen ? "chevron-down" : "chevron-right";
-                return !doc?.isFolder ? folder : chevron;
-            case DocumentType.WEB: return "globe-asia";
-            case DocumentType.SCREENSHOT: return "photo-video";
-            case DocumentType.WEBCAM: return "video";
-            case DocumentType.AUDIO: return "microphone";
-            case DocumentType.BUTTON: return "bolt";
-            case DocumentType.PRES: return "tv";
-            case DocumentType.SCRIPTING: return "terminal";
-            case DocumentType.IMPORT: return "cloud-upload-alt";
-            case DocumentType.VID: return "video";
-            case DocumentType.INK: return "pen-nib";
-            case DocumentType.PDF: return "file-pdf";
-            case DocumentType.LINK: return "link";
-            case DocumentType.MAP: return "map-marker-alt";
-            default: return "question";
-        }
-    }
-
-
-    export namespace Get {
-
-        const primitives = ["string", "number", "boolean"];
-
-        export interface JsonConversionOpts {
-            data: any;
-            title?: string;
-            appendToExisting?: { targetDoc: Doc, fieldKey?: string };
-            excludeEmptyObjects?: boolean;
-        }
-
-        const defaultKey = "json";
-
-        /**
-         * This function takes any valid JSON(-like) data, i.e. parsed or unparsed, and at arbitrarily
-         * deep levels of nesting, converts the data and structure into nested documents with the appropriate fields.
-         *
-         * After building a hierarchy within / below a top-level document, it then returns that top-level parent.
-         *
-         * If we've received a string, treat it like valid JSON and try to parse it into an object. If this fails, the
-         * string is invalid JSON, so we should assume that the input is the result of a JSON.parse()
-         * call that returned a regular string value to be stored as a Field.
-         *
-         * If we've received something other than a string, since the caller might also pass in the results of a
-         * JSON.parse() call, valid input might be an object, an array (still typeof object), a boolean or a number.
-         * Anything else (like a function, etc. passed in naively as any) is meaningless for this operation.
-         *
-         * All TS/JS objects get converted directly to documents, directly preserving the key value structure. Everything else,
-         * lacking the key value structure, gets stored as a field in a wrapper document.
-         *
-         * @param data for convenience and flexibility, either a valid JSON string to be parsed,
-         * or the result of any JSON.parse() call.
-         * @param title an optional title to give to the highest parent document in the hierarchy.
-         * If whether this function creates a new document or appendToExisting is specified and that document already has a title,
-         * because this title field can be left undefined for the opposite behavior, including a title will overwrite the existing title.
-         * @param appendToExisting **if specified**, there are two cases, both of which return the target document:
-         *
-         * 1) the json to be converted can be represented as a document, in which case the target document will act as the root
-         * of the tree and receive all the conversion results as new fields on itself
-         * 2) the json can't be represented as a document, in which case the function will assign the field-level conversion
-         * results to either the specified key on the target document, or to its "json" key by default.
-         *
-         * If not specified, the function creates and returns a new entirely generic document (different from the Doc.Create calls)
-         * to act as the root of the tree.
-         *
-         * One might choose to specify this field if you want to write to a document returned from a Document.Create function call,
-         * say a TreeView document that will be rendered, not just an untyped, identityless doc that would otherwise be created
-         * from a default call to new Doc.
-         *
-         * @param excludeEmptyObjects whether non-primitive objects (TypeScript objects and arrays) should be converted even
-         * if they contain no data. By default, empty objects and arrays are ignored.
-         */
-        export function FromJson({ data, title, appendToExisting, excludeEmptyObjects }: JsonConversionOpts): Opt<Doc> {
-            if (excludeEmptyObjects === undefined) {
-                excludeEmptyObjects = true;
+            if (typeof value === "string") {
+                  value = value.replace(`,${Utils.noRecursionHack}`, "");
             }
-            if (data === undefined || data === null || ![...primitives, "object"].includes(typeof data)) {
-                return undefined;
+            const fieldVal = key === "#" ? (StrCast(doc.tags).includes(":#" + value + ":") ? StrCast(doc.tags) : undefined) : doc[key];
+            if (Cast(fieldVal, listSpec("string"), []).length) {
+                  const vals = Cast(fieldVal, listSpec("string"), []);
+                  const docs = vals.some(v => (v as any) instanceof Doc);
+                  if (docs) return value === Field.toString(fieldVal as Field);
+                  return vals.some(v => v.includes(value));  // bcz: arghh: Todo: comparison should be parameterized as exact, or substring
             }
-            let resolved: any;
-            try {
-                resolved = JSON.parse(typeof data === "string" ? data : JSON.stringify(data));
-            } catch (e) {
-                return undefined;
+            const fieldStr = Field.toString(fieldVal as Field);
+            return fieldStr.includes(value); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring
+      }
+
+      export function deiconifyView(doc: Doc) {
+            StrCast(doc.layoutKey).split("_")[1] === "icon" && setNativeView(doc);
+      }
+
+      export function setNativeView(doc: any) {
+            const prevLayout = StrCast(doc.layoutKey).split("_")[1];
+            const deiconify = prevLayout === "icon" && StrCast(doc.deiconifyLayout) ? "layout_" + StrCast(doc.deiconifyLayout) : "";
+            prevLayout === "icon" && (doc.deiconifyLayout = undefined);
+            doc.layoutKey = deiconify || "layout";
+      }
+      export function setDocRangeFilter(container: Opt<Doc>, key: string, range?: number[]) {
+            if (!container) return;
+            const docRangeFilters = Cast(container._docRangeFilters, listSpec("string"), []);
+            for (let i = 0; i < docRangeFilters.length; i += 3) {
+                  if (docRangeFilters[i] === key) {
+                        docRangeFilters.splice(i, 3);
+                        break;
+                  }
             }
-            let output: Opt<Doc>;
-            if (typeof resolved === "object" && !(resolved instanceof Array)) {
-                output = convertObject(resolved, excludeEmptyObjects, title, appendToExisting?.targetDoc);
-            } else {
-                // give the proper types to the data extracted from the JSON
-                const result = toField(resolved, excludeEmptyObjects);
-                if (appendToExisting) {
-                    (output = appendToExisting.targetDoc)[appendToExisting.fieldKey || defaultKey] = result;
-                } else {
-                    (output = new Doc).json = result;
-                }
+            if (range !== undefined) {
+                  docRangeFilters.push(key);
+                  docRangeFilters.push(range[0].toString());
+                  docRangeFilters.push(range[1].toString());
+                  container._docRangeFilters = new List<string>(docRangeFilters);
             }
-            title && output && (output.title = title);
-            return output;
-        }
-
-        /**
-         * For each value of the object, recursively convert it to its appropriate field value
-         * and store the field at the appropriate key in the document if it is not undefined
-         * @param object the object to convert
-         * @returns the object mapped from JSON to field values, where each mapping
-         * might involve arbitrary recursion (since toField might itself call convertObject)
-         */
-        const convertObject = (object: any, excludeEmptyObjects: boolean, title?: string, target?: Doc): Opt<Doc> => {
-            const hasEntries = Object.keys(object).length;
-            if (hasEntries || !excludeEmptyObjects) {
-                const resolved = target ?? new Doc;
-                if (hasEntries) {
-                    let result: Opt<Field>;
-                    Object.keys(object).map(key => {
-                        // if excludeEmptyObjects is true, any qualifying conversions from toField will
-                        // be undefined, and thus the results that would have
-                        // otherwise been empty (List or Doc)s will just not be written
-                        if (result = toField(object[key], excludeEmptyObjects, key)) {
-                            resolved[key] = result;
+      }
+
+      // filters document in a container collection:
+      // all documents with the specified value for the specified key are included/excluded
+      // based on the modifiers :"check", "x", undefined
+      export function setDocFilter(container: Opt<Doc>, key: string, value: any, modifiers: "remove" | "match" | "check" | "x" | "exists" | "unset", toggle?: boolean, fieldSuffix?: string, append: boolean = true) {
+            if (!container) return;
+            const filterField = "_" + (fieldSuffix ? fieldSuffix + "-" : "") + "docFilters";
+            const docFilters = Cast(container[filterField], listSpec("string"), []);
+            runInAction(() => {
+                  for (let i = 0; i < docFilters.length; i++) {
+                        const fields = docFilters[i].split(":"); // split key:value:modifier
+                        if (fields[0] === key && (fields[1] === value || modifiers === "match")) {
+                              if (fields[2] === modifiers && modifiers && fields[1] === value) {
+                                    if (toggle) modifiers = "remove";
+                                    else return;
+                              }
+                              docFilters.splice(i, 1);
+                              container[filterField] = new List<string>(docFilters);
+                              break;
                         }
-                    });
-                }
-                title && (resolved.title = title);
-                return resolved;
+                  }
+                  if (!docFilters.length && modifiers === "match" && value === undefined) {
+                        container[filterField] = undefined;
+                  } else if (modifiers !== "remove") {
+                        !append && (docFilters.length = 0);
+                        docFilters.push(key + ":" + value + ":" + modifiers);
+                        container[filterField] = new List<string>(docFilters);
+                  }
+            });
+      }
+      export function readDocRangeFilter(doc: Doc, key: string) {
+            const docRangeFilters = Cast(doc._docRangeFilters, listSpec("string"), []);
+            for (let i = 0; i < docRangeFilters.length; i += 3) {
+                  if (docRangeFilters[i] === key) {
+                        return [Number(docRangeFilters[i + 1]), Number(docRangeFilters[i + 2])];
+                  }
             }
-        };
-
-        /**
-         * For each element in the list, recursively convert it to a document or other field
-         * and push the field to the list if it is not undefined
-         * @param list the list to convert
-         * @returns the list mapped from JSON to field values, where each mapping
-         * might involve arbitrary recursion (since toField might itself call convertList)
-         */
-        const convertList = (list: Array<any>, excludeEmptyObjects: boolean): Opt<List<Field>> => {
-            const target = new List();
-            let result: Opt<Field>;
-            // if excludeEmptyObjects is true, any qualifying conversions from toField will
-            // be undefined, and thus the results that would have
-            // otherwise been empty (List or Doc)s will just not be written
-            list.map(item => (result = toField(item, excludeEmptyObjects)) && target.push(result));
-            if (target.length || !excludeEmptyObjects) {
-                return target;
+      }
+      export function assignDocToField(doc: Doc, field: string, id: string) {
+            DocServer.GetRefField(id).then(layout => layout instanceof Doc && (doc[field] = layout));
+            return id;
+      }
+
+      export function toggleNativeDimensions(layoutDoc: Doc, contentScale: number, panelWidth: number, panelHeight: number) {
+            runInAction(() => {
+                  if (Doc.NativeWidth(layoutDoc) || Doc.NativeHeight(layoutDoc)) {
+                        layoutDoc._viewScale = NumCast(layoutDoc._viewScale, 1) * contentScale;
+                        layoutDoc._nativeWidth = undefined;
+                        layoutDoc._nativeHeight = undefined;
+                  }
+                  else {
+                        layoutDoc._autoHeight = false;
+                        if (!Doc.NativeWidth(layoutDoc)) {
+                              layoutDoc._nativeWidth = NumCast(layoutDoc._width, panelWidth);
+                              layoutDoc._nativeHeight = NumCast(layoutDoc._height, panelHeight);
+                        }
+                  }
+            });
+      }
+
+      export function isDocPinned(doc: Doc) {
+            //add this new doc to props.Document
+            const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc;
+            return !curPres ? false : DocListCast(curPres.data).findIndex((val) => Doc.AreProtosEqual(val, doc)) !== -1;
+      }
+
+      export function copyDragFactory(dragFactory: Doc) {
+            const ndoc = dragFactory.isTemplateDoc ? Doc.ApplyTemplate(dragFactory) : Doc.MakeCopy(dragFactory, true);
+            ndoc && Doc.AddDocToList(Cast(Doc.UserDoc().myFileOrphans, Doc, null), "data", Doc.GetProto(ndoc));
+            if (ndoc && dragFactory["dragFactory-count"] !== undefined) {
+                  dragFactory["dragFactory-count"] = NumCast(dragFactory["dragFactory-count"]) + 1;
+                  Doc.SetInPlace(ndoc, "title", ndoc.title + " " + NumCast(dragFactory["dragFactory-count"]).toString(), true);
             }
-        };
 
-        const toField = (data: any, excludeEmptyObjects: boolean, title?: string): Opt<Field> => {
-            if (data === null || data === undefined) {
-                return undefined;
+            if (ndoc) inheritParentAcls(CurrentUserUtils.ActiveDashboard, ndoc);
+
+            return ndoc;
+      }
+      export function delegateDragFactory(dragFactory: Doc) {
+            const ndoc = Doc.MakeDelegateWithProto(dragFactory);
+            if (ndoc && dragFactory["dragFactory-count"] !== undefined) {
+                  dragFactory["dragFactory-count"] = NumCast(dragFactory["dragFactory-count"]) + 1;
+                  Doc.GetProto(ndoc).title = ndoc.title + " " + NumCast(dragFactory["dragFactory-count"]).toString();
             }
-            if (primitives.includes(typeof data)) {
-                return data;
+            return ndoc;
+      }
+
+      export function toIcon(doc?: Doc, isOpen?: boolean) {
+            switch (StrCast(doc?.type)) {
+                  case DocumentType.IMG: return "image";
+                  case DocumentType.COMPARISON: return "columns";
+                  case DocumentType.RTF: return "sticky-note";
+                  case DocumentType.COL:
+                        const folder: IconProp = isOpen ? "folder-open" : "folder";
+                        const chevron: IconProp = isOpen ? "chevron-down" : "chevron-right";
+                        return !doc?.isFolder ? folder : chevron;
+                  case DocumentType.WEB: return "globe-asia";
+                  case DocumentType.SCREENSHOT: return "photo-video";
+                  case DocumentType.WEBCAM: return "video";
+                  case DocumentType.AUDIO: return "microphone";
+                  case DocumentType.BUTTON: return "bolt";
+                  case DocumentType.PRES: return "tv";
+                  case DocumentType.SCRIPTING: return "terminal";
+                  case DocumentType.IMPORT: return "cloud-upload-alt";
+                  case DocumentType.VID: return "video";
+                  case DocumentType.INK: return "pen-nib";
+                  case DocumentType.PDF: return "file-pdf";
+                  case DocumentType.LINK: return "link";
+                  case DocumentType.MAP: return "map-marker-alt";
+                  default: return "question";
             }
-            if (typeof data === "object") {
-                return data instanceof Array ? convertList(data, excludeEmptyObjects) : convertObject(data, excludeEmptyObjects, title, undefined);
+      }
+
+
+      export namespace Get {
+
+            const primitives = ["string", "number", "boolean"];
+
+            export interface JsonConversionOpts {
+                  data: any;
+                  title?: string;
+                  appendToExisting?: { targetDoc: Doc, fieldKey?: string };
+                  excludeEmptyObjects?: boolean;
             }
-            throw new Error(`How did ${data} of type ${typeof data} end up in JSON?`);
-        };
-    }
+
+            const defaultKey = "json";
+
+            /**
+             * This function takes any valid JSON(-like) data, i.e. parsed or unparsed, and at arbitrarily
+             * deep levels of nesting, converts the data and structure into nested documents with the appropriate fields.
+             *
+             * After building a hierarchy within / below a top-level document, it then returns that top-level parent.
+             *
+             * If we've received a string, treat it like valid JSON and try to parse it into an object. If this fails, the
+             * string is invalid JSON, so we should assume that the input is the result of a JSON.parse()
+             * call that returned a regular string value to be stored as a Field.
+             *
+             * If we've received something other than a string, since the caller might also pass in the results of a
+             * JSON.parse() call, valid input might be an object, an array (still typeof object), a boolean or a number.
+             * Anything else (like a function, etc. passed in naively as any) is meaningless for this operation.
+             *
+             * All TS/JS objects get converted directly to documents, directly preserving the key value structure. Everything else,
+             * lacking the key value structure, gets stored as a field in a wrapper document.
+             *
+             * @param data for convenience and flexibility, either a valid JSON string to be parsed,
+             * or the result of any JSON.parse() call.
+             * @param title an optional title to give to the highest parent document in the hierarchy.
+             * If whether this function creates a new document or appendToExisting is specified and that document already has a title,
+             * because this title field can be left undefined for the opposite behavior, including a title will overwrite the existing title.
+             * @param appendToExisting **if specified**, there are two cases, both of which return the target document:
+             *
+             * 1) the json to be converted can be represented as a document, in which case the target document will act as the root
+             * of the tree and receive all the conversion results as new fields on itself
+             * 2) the json can't be represented as a document, in which case the function will assign the field-level conversion
+             * results to either the specified key on the target document, or to its "json" key by default.
+             *
+             * If not specified, the function creates and returns a new entirely generic document (different from the Doc.Create calls)
+             * to act as the root of the tree.
+             *
+             * One might choose to specify this field if you want to write to a document returned from a Document.Create function call,
+             * say a TreeView document that will be rendered, not just an untyped, identityless doc that would otherwise be created
+             * from a default call to new Doc.
+             *
+             * @param excludeEmptyObjects whether non-primitive objects (TypeScript objects and arrays) should be converted even
+             * if they contain no data. By default, empty objects and arrays are ignored.
+             */
+            export function FromJson({ data, title, appendToExisting, excludeEmptyObjects }: JsonConversionOpts): Opt<Doc> {
+                  if (excludeEmptyObjects === undefined) {
+                        excludeEmptyObjects = true;
+                  }
+                  if (data === undefined || data === null || ![...primitives, "object"].includes(typeof data)) {
+                        return undefined;
+                  }
+                  let resolved: any;
+                  try {
+                        resolved = JSON.parse(typeof data === "string" ? data : JSON.stringify(data));
+                  } catch (e) {
+                        return undefined;
+                  }
+                  let output: Opt<Doc>;
+                  if (typeof resolved === "object" && !(resolved instanceof Array)) {
+                        output = convertObject(resolved, excludeEmptyObjects, title, appendToExisting?.targetDoc);
+                  } else {
+                        // give the proper types to the data extracted from the JSON
+                        const result = toField(resolved, excludeEmptyObjects);
+                        if (appendToExisting) {
+                              (output = appendToExisting.targetDoc)[appendToExisting.fieldKey || defaultKey] = result;
+                        } else {
+                              (output = new Doc).json = result;
+                        }
+                  }
+                  title && output && (output.title = title);
+                  return output;
+            }
+
+            /**
+             * For each value of the object, recursively convert it to its appropriate field value
+             * and store the field at the appropriate key in the document if it is not undefined
+             * @param object the object to convert
+             * @returns the object mapped from JSON to field values, where each mapping
+             * might involve arbitrary recursion (since toField might itself call convertObject)
+             */
+            const convertObject = (object: any, excludeEmptyObjects: boolean, title?: string, target?: Doc): Opt<Doc> => {
+                  const hasEntries = Object.keys(object).length;
+                  if (hasEntries || !excludeEmptyObjects) {
+                        const resolved = target ?? new Doc;
+                        if (hasEntries) {
+                              let result: Opt<Field>;
+                              Object.keys(object).map(key => {
+                                    // if excludeEmptyObjects is true, any qualifying conversions from toField will
+                                    // be undefined, and thus the results that would have
+                                    // otherwise been empty (List or Doc)s will just not be written
+                                    if (result = toField(object[key], excludeEmptyObjects, key)) {
+                                          resolved[key] = result;
+                                    }
+                              });
+                        }
+                        title && (resolved.title = title);
+                        return resolved;
+                  }
+            };
+
+            /**
+             * For each element in the list, recursively convert it to a document or other field
+             * and push the field to the list if it is not undefined
+             * @param list the list to convert
+             * @returns the list mapped from JSON to field values, where each mapping
+             * might involve arbitrary recursion (since toField might itself call convertList)
+             */
+            const convertList = (list: Array<any>, excludeEmptyObjects: boolean): Opt<List<Field>> => {
+                  const target = new List();
+                  let result: Opt<Field>;
+                  // if excludeEmptyObjects is true, any qualifying conversions from toField will
+                  // be undefined, and thus the results that would have
+                  // otherwise been empty (List or Doc)s will just not be written
+                  list.map(item => (result = toField(item, excludeEmptyObjects)) && target.push(result));
+                  if (target.length || !excludeEmptyObjects) {
+                        return target;
+                  }
+            };
+
+            const toField = (data: any, excludeEmptyObjects: boolean, title?: string): Opt<Field> => {
+                  if (data === null || data === undefined) {
+                        return undefined;
+                  }
+                  if (primitives.includes(typeof data)) {
+                        return data;
+                  }
+                  if (typeof data === "object") {
+                        return data instanceof Array ? convertList(data, excludeEmptyObjects) : convertObject(data, excludeEmptyObjects, title, undefined);
+                  }
+                  throw new Error(`How did ${data} of type ${typeof data} end up in JSON?`);
+            };
+      }
 
 }
 
@@ -1423,14 +1423,14 @@ ScriptingGlobals.add(function DOC(id: string) { console.log("Can't parse a docum
 ScriptingGlobals.add(function assignDoc(doc: Doc, field: string, id: string) { return Doc.assignDocToField(doc, field, id); });
 ScriptingGlobals.add(function docCast(doc: FieldResult): any { return DocCastAsync(doc); });
 ScriptingGlobals.add(function activePresentationItem() {
-    const curPres = Doc.UserDoc().activePresentation as Doc;
-    return curPres && DocListCast(curPres[Doc.LayoutFieldKey(curPres)])[NumCast(curPres._itemIndex)];
+      const curPres = Doc.UserDoc().activePresentation as Doc;
+      return curPres && DocListCast(curPres[Doc.LayoutFieldKey(curPres)])[NumCast(curPres._itemIndex)];
 });
 ScriptingGlobals.add(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) {
-    const docs = SelectionManager.Views().map(dv => dv.props.Document).
-        filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.KVP &&
-            (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null)));
-    return docs.length ? new List(docs) : prevValue;
+      const docs = SelectionManager.Views().map(dv => dv.props.Document).
+            filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.KVP &&
+                  (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null)));
+      return docs.length ? new List(docs) : prevValue;
 });
 ScriptingGlobals.add(function setDocFilter(container: Doc, key: string, value: any, modifiers: "match" | "check" | "x" | "remove") { Doc.setDocFilter(container, key, value, modifiers); });
 ScriptingGlobals.add(function setDocRangeFilter(container: Doc, key: string, range: number[]) { Doc.setDocRangeFilter(container, key, range); });
-- 
cgit v1.2.3-70-g09d2


From 6493d95e92c8ed58bb3a8c07ea4ca28dae82ea1d Mon Sep 17 00:00:00 2001
From: Jenny Yu <jennyyu212@outlook.com>
Date: Tue, 7 Jun 2022 08:51:41 -0700
Subject: removing decorations on recording box

---
 package-lock.json                                  | 8281 +++++++++-----------
 src/client/documents/Documents.ts                  | 2815 +++----
 src/client/views/DocumentDecorations.tsx           | 1068 +--
 src/client/views/nodes/DocumentView.tsx            | 2517 +++---
 .../views/nodes/RecordingBox/RecordingView.tsx     |   20 +-
 src/client/views/nodes/trails/PresElementBox.tsx   |   10 +-
 6 files changed, 6848 insertions(+), 7863 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/package-lock.json b/package-lock.json
index 08b1a21e2..694ee5c8d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,232 +5,179 @@
     "requires": true,
     "dependencies": {
         "@babel/code-frame": {
-            "version": "7.8.3",
-            "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
-            "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
+            "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==",
             "requires": {
-                "@babel/highlight": "^7.8.3"
+                "@babel/highlight": "^7.16.7"
             }
         },
         "@babel/generator": {
-            "version": "7.9.6",
-            "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz",
-            "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==",
-            "requires": {
-                "@babel/types": "^7.9.6",
-                "jsesc": "^2.5.1",
-                "lodash": "^4.17.13",
-                "source-map": "^0.5.0"
-            },
-            "dependencies": {
-                "@babel/types": {
-                    "version": "7.9.6",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
-                    "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
-                    "requires": {
-                        "@babel/helper-validator-identifier": "^7.9.5",
-                        "lodash": "^4.17.13",
-                        "to-fast-properties": "^2.0.0"
-                    }
-                }
+            "version": "7.18.2",
+            "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz",
+            "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==",
+            "requires": {
+                "@babel/types": "^7.18.2",
+                "@jridgewell/gen-mapping": "^0.3.0",
+                "jsesc": "^2.5.1"
             }
         },
         "@babel/helper-annotate-as-pure": {
-            "version": "7.10.4",
-            "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz",
-            "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==",
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz",
+            "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==",
             "requires": {
-                "@babel/types": "^7.10.4"
-            },
-            "dependencies": {
-                "@babel/helper-validator-identifier": {
-                    "version": "7.10.4",
-                    "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
-                    "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw=="
-                },
-                "@babel/types": {
-                    "version": "7.10.5",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.5.tgz",
-                    "integrity": "sha512-ixV66KWfCI6GKoA/2H9v6bQdbfXEwwpOdQ8cRvb4F+eyvhlaHxWFMQB4+3d9QFJXZsiiiqVrewNV0DFEQpyT4Q==",
-                    "requires": {
-                        "@babel/helper-validator-identifier": "^7.10.4",
-                        "lodash": "^4.17.19",
-                        "to-fast-properties": "^2.0.0"
-                    }
-                },
-                "lodash": {
-                    "version": "4.17.19",
-                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
-                    "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
-                }
+                "@babel/types": "^7.16.7"
             }
         },
+        "@babel/helper-environment-visitor": {
+            "version": "7.18.2",
+            "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz",
+            "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ=="
+        },
         "@babel/helper-function-name": {
-            "version": "7.9.5",
-            "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
-            "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
+            "version": "7.17.9",
+            "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz",
+            "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==",
             "requires": {
-                "@babel/helper-get-function-arity": "^7.8.3",
-                "@babel/template": "^7.8.3",
-                "@babel/types": "^7.9.5"
+                "@babel/template": "^7.16.7",
+                "@babel/types": "^7.17.0"
             }
         },
-        "@babel/helper-get-function-arity": {
-            "version": "7.8.3",
-            "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz",
-            "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==",
+        "@babel/helper-hoist-variables": {
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz",
+            "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==",
             "requires": {
-                "@babel/types": "^7.8.3"
+                "@babel/types": "^7.16.7"
             }
         },
         "@babel/helper-module-imports": {
-            "version": "7.10.3",
-            "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.3.tgz",
-            "integrity": "sha512-Jtqw5M9pahLSUWA+76nhK9OG8nwYXzhQzVIGFoNaHnXF/r4l7kz4Fl0UAW7B6mqC5myoJiBP5/YQlXQTMfHI9w==",
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz",
+            "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==",
             "requires": {
-                "@babel/types": "^7.10.3"
-            },
-            "dependencies": {
-                "@babel/helper-validator-identifier": {
-                    "version": "7.10.3",
-                    "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz",
-                    "integrity": "sha512-bU8JvtlYpJSBPuj1VUmKpFGaDZuLxASky3LhaKj3bmpSTY6VWooSM8msk+Z0CZoErFye2tlABF6yDkT3FOPAXw=="
-                },
-                "@babel/types": {
-                    "version": "7.10.3",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.3.tgz",
-                    "integrity": "sha512-nZxaJhBXBQ8HVoIcGsf9qWep3Oh3jCENK54V4mRF7qaJabVsAYdbTtmSD8WmAp1R6ytPiu5apMwSXyxB1WlaBA==",
-                    "requires": {
-                        "@babel/helper-validator-identifier": "^7.10.3",
-                        "lodash": "^4.17.13",
-                        "to-fast-properties": "^2.0.0"
-                    }
-                }
+                "@babel/types": "^7.16.7"
             }
         },
         "@babel/helper-plugin-utils": {
-            "version": "7.16.7",
-            "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz",
-            "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA=="
+            "version": "7.17.12",
+            "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz",
+            "integrity": "sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA=="
         },
         "@babel/helper-split-export-declaration": {
-            "version": "7.8.3",
-            "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz",
-            "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==",
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz",
+            "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==",
             "requires": {
-                "@babel/types": "^7.8.3"
+                "@babel/types": "^7.16.7"
             }
         },
         "@babel/helper-validator-identifier": {
-            "version": "7.9.5",
-            "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz",
-            "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g=="
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
+            "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw=="
         },
         "@babel/highlight": {
-            "version": "7.9.0",
-            "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
-            "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
+            "version": "7.17.12",
+            "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz",
+            "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==",
             "requires": {
-                "@babel/helper-validator-identifier": "^7.9.0",
+                "@babel/helper-validator-identifier": "^7.16.7",
                 "chalk": "^2.0.0",
                 "js-tokens": "^4.0.0"
             }
         },
         "@babel/parser": {
-            "version": "7.9.6",
-            "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
-            "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q=="
+            "version": "7.18.4",
+            "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.4.tgz",
+            "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow=="
         },
         "@babel/plugin-syntax-jsx": {
-            "version": "7.16.7",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz",
-            "integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==",
+            "version": "7.17.12",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.17.12.tgz",
+            "integrity": "sha512-spyY3E3AURfxh/RHtjx5j6hs8am5NbUBGfcZ2vB3uShSpZdQyXSf5rR5Mk76vbtlAZOelyVQ71Fg0x9SG4fsog==",
             "requires": {
-                "@babel/helper-plugin-utils": "^7.16.7"
+                "@babel/helper-plugin-utils": "^7.17.12"
             }
         },
         "@babel/runtime": {
-            "version": "7.9.2",
-            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz",
-            "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==",
+            "version": "7.18.3",
+            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.3.tgz",
+            "integrity": "sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==",
             "requires": {
                 "regenerator-runtime": "^0.13.4"
             }
         },
         "@babel/runtime-corejs3": {
-            "version": "7.17.2",
-            "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.2.tgz",
-            "integrity": "sha512-NcKtr2epxfIrNM4VOmPKO46TvDMCBhgi2CrSHaEarrz+Plk2K5r9QemmOFTGpZaoKnWoGH5MO+CzeRsih/Fcgg==",
+            "version": "7.18.3",
+            "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.18.3.tgz",
+            "integrity": "sha512-l4ddFwrc9rnR+EJsHsh+TJ4A35YqQz/UqcjtlX2ov53hlJYG5CxtQmNZxyajwDVmCxwy++rtvGU5HazCK4W41Q==",
             "requires": {
                 "core-js-pure": "^3.20.2",
                 "regenerator-runtime": "^0.13.4"
             }
         },
         "@babel/template": {
-            "version": "7.8.6",
-            "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
-            "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz",
+            "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==",
             "requires": {
-                "@babel/code-frame": "^7.8.3",
-                "@babel/parser": "^7.8.6",
-                "@babel/types": "^7.8.6"
+                "@babel/code-frame": "^7.16.7",
+                "@babel/parser": "^7.16.7",
+                "@babel/types": "^7.16.7"
             }
         },
         "@babel/traverse": {
-            "version": "7.9.6",
-            "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz",
-            "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==",
-            "requires": {
-                "@babel/code-frame": "^7.8.3",
-                "@babel/generator": "^7.9.6",
-                "@babel/helper-function-name": "^7.9.5",
-                "@babel/helper-split-export-declaration": "^7.8.3",
-                "@babel/parser": "^7.9.6",
-                "@babel/types": "^7.9.6",
+            "version": "7.18.2",
+            "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.2.tgz",
+            "integrity": "sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==",
+            "requires": {
+                "@babel/code-frame": "^7.16.7",
+                "@babel/generator": "^7.18.2",
+                "@babel/helper-environment-visitor": "^7.18.2",
+                "@babel/helper-function-name": "^7.17.9",
+                "@babel/helper-hoist-variables": "^7.16.7",
+                "@babel/helper-split-export-declaration": "^7.16.7",
+                "@babel/parser": "^7.18.0",
+                "@babel/types": "^7.18.2",
                 "debug": "^4.1.0",
-                "globals": "^11.1.0",
-                "lodash": "^4.17.13"
+                "globals": "^11.1.0"
             },
             "dependencies": {
-                "@babel/types": {
-                    "version": "7.9.6",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
-                    "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
-                    "requires": {
-                        "@babel/helper-validator-identifier": "^7.9.5",
-                        "lodash": "^4.17.13",
-                        "to-fast-properties": "^2.0.0"
-                    }
-                },
                 "debug": {
-                    "version": "4.1.1",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+                    "version": "4.3.4",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+                    "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
                     "requires": {
-                        "ms": "^2.1.1"
+                        "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=="
                 }
             }
         },
         "@babel/types": {
-            "version": "7.9.5",
-            "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz",
-            "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==",
+            "version": "7.18.4",
+            "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz",
+            "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==",
             "requires": {
-                "@babel/helper-validator-identifier": "^7.9.5",
-                "lodash": "^4.17.13",
+                "@babel/helper-validator-identifier": "^7.16.7",
                 "to-fast-properties": "^2.0.0"
             }
         },
         "@discoveryjs/json-ext": {
-            "version": "0.5.6",
-            "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz",
-            "integrity": "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA=="
+            "version": "0.5.7",
+            "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
+            "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw=="
         },
         "@emotion/babel-plugin": {
-            "version": "11.7.2",
-            "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.7.2.tgz",
-            "integrity": "sha512-6mGSCWi9UzXut/ZAN6lGFu33wGR3SJisNl3c0tvlmb8XChH1b2SUvxvnOh7hvLpqyRdHHU9AiazV3Cwbk5SXKQ==",
+            "version": "11.9.2",
+            "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.9.2.tgz",
+            "integrity": "sha512-Pr/7HGH6H6yKgnVFNEj2MVlreu3ADqftqjqwUvDy/OJzKFgxKeTQ+eeUf20FOTuHVkDON2iNa25rAXVYtWJCjw==",
             "requires": {
                 "@babel/helper-module-imports": "^7.12.13",
                 "@babel/plugin-syntax-jsx": "^7.12.13",
@@ -246,45 +193,15 @@
                 "stylis": "4.0.13"
             },
             "dependencies": {
-                "@babel/helper-module-imports": {
-                    "version": "7.16.7",
-                    "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz",
-                    "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==",
-                    "requires": {
-                        "@babel/types": "^7.16.7"
-                    }
-                },
-                "@babel/helper-validator-identifier": {
-                    "version": "7.16.7",
-                    "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
-                    "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw=="
-                },
-                "@babel/runtime": {
-                    "version": "7.17.2",
-                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz",
-                    "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==",
-                    "requires": {
-                        "regenerator-runtime": "^0.13.4"
-                    }
-                },
-                "@babel/types": {
-                    "version": "7.17.0",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz",
-                    "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==",
-                    "requires": {
-                        "@babel/helper-validator-identifier": "^7.16.7",
-                        "to-fast-properties": "^2.0.0"
-                    }
-                },
                 "@emotion/memoize": {
                     "version": "0.7.5",
                     "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz",
                     "integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ=="
                 },
                 "@emotion/serialize": {
-                    "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz",
-                    "integrity": "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==",
+                    "version": "1.0.3",
+                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.3.tgz",
+                    "integrity": "sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA==",
                     "requires": {
                         "@emotion/hash": "^0.8.0",
                         "@emotion/memoize": "^0.7.4",
@@ -299,19 +216,14 @@
                     "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ=="
                 },
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
                 },
                 "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=="
-                },
-                "stylis": {
-                    "version": "4.0.13",
-                    "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz",
-                    "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
                 }
             }
         },
@@ -352,13 +264,13 @@
             }
         },
         "@emotion/css": {
-            "version": "11.7.1",
-            "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.7.1.tgz",
-            "integrity": "sha512-RUUgPlMZunlc7SE5A6Hg+VWRzb2cU6O9xlV78KCFgcnl25s7Qz/20oQg71iKudpLqk7xj0vhbJlwcJJMT0BOZg==",
+            "version": "11.9.0",
+            "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.9.0.tgz",
+            "integrity": "sha512-S9UjCxSrxEHawOLnWw4upTwfYKb0gVQdatHejn3W9kPyXxmKv3HmjVfJ84kDLmdX8jR20OuDQwaJ4Um24qD9vA==",
             "requires": {
                 "@emotion/babel-plugin": "^11.7.1",
                 "@emotion/cache": "^11.7.1",
-                "@emotion/serialize": "^1.0.0",
+                "@emotion/serialize": "^1.0.3",
                 "@emotion/sheet": "^1.0.3",
                 "@emotion/utils": "^1.0.0"
             },
@@ -376,9 +288,9 @@
                     }
                 },
                 "@emotion/serialize": {
-                    "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz",
-                    "integrity": "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==",
+                    "version": "1.0.3",
+                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.3.tgz",
+                    "integrity": "sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA==",
                     "requires": {
                         "@emotion/hash": "^0.8.0",
                         "@emotion/memoize": "^0.7.4",
@@ -398,14 +310,9 @@
                     "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ=="
                 },
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
-                },
-                "stylis": {
-                    "version": "4.0.13",
-                    "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz",
-                    "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
                 }
             }
         },
@@ -415,11 +322,11 @@
             "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
         },
         "@emotion/is-prop-valid": {
-            "version": "0.8.8",
-            "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
-            "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.1.2.tgz",
+            "integrity": "sha512-3QnhqeL+WW88YjYbQL5gUIkthuMw7a0NGbZ7wfFVk2kg/CK5w8w5FFa0RzWjyY1+sujN0NWbtSHH6OJmWHtJpQ==",
             "requires": {
-                "@emotion/memoize": "0.7.4"
+                "@emotion/memoize": "^0.7.4"
             }
         },
         "@emotion/memoize": {
@@ -428,28 +335,19 @@
             "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw=="
         },
         "@emotion/react": {
-            "version": "11.8.1",
-            "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.8.1.tgz",
-            "integrity": "sha512-XGaie4nRxmtP1BZYBXqC5JGqMYF2KRKKI7vjqNvQxyRpekVAZhb6QqrElmZCAYXH1L90lAelADSVZC4PFsrJ8Q==",
+            "version": "11.9.0",
+            "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.9.0.tgz",
+            "integrity": "sha512-lBVSF5d0ceKtfKCDQJveNAtkC7ayxpVlgOohLgXqRwqWr9bOf4TZAFFyIcNngnV6xK6X4x2ZeXq7vliHkoVkxQ==",
             "requires": {
                 "@babel/runtime": "^7.13.10",
                 "@emotion/babel-plugin": "^11.7.1",
                 "@emotion/cache": "^11.7.1",
-                "@emotion/serialize": "^1.0.2",
-                "@emotion/sheet": "^1.1.0",
+                "@emotion/serialize": "^1.0.3",
                 "@emotion/utils": "^1.1.0",
                 "@emotion/weak-memoize": "^0.2.5",
                 "hoist-non-react-statics": "^3.3.1"
             },
             "dependencies": {
-                "@babel/runtime": {
-                    "version": "7.17.2",
-                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz",
-                    "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==",
-                    "requires": {
-                        "regenerator-runtime": "^0.13.4"
-                    }
-                },
                 "@emotion/cache": {
                     "version": "11.7.1",
                     "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.7.1.tgz",
@@ -463,9 +361,9 @@
                     }
                 },
                 "@emotion/serialize": {
-                    "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz",
-                    "integrity": "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==",
+                    "version": "1.0.3",
+                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.3.tgz",
+                    "integrity": "sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA==",
                     "requires": {
                         "@emotion/hash": "^0.8.0",
                         "@emotion/memoize": "^0.7.4",
@@ -485,14 +383,9 @@
                     "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ=="
                 },
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
-                },
-                "stylis": {
-                    "version": "4.0.13",
-                    "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz",
-                    "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
                 }
             }
         },
@@ -525,26 +418,10 @@
                 "@emotion/utils": "^1.1.0"
             },
             "dependencies": {
-                "@babel/runtime": {
-                    "version": "7.17.2",
-                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz",
-                    "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==",
-                    "requires": {
-                        "regenerator-runtime": "^0.13.4"
-                    }
-                },
-                "@emotion/is-prop-valid": {
-                    "version": "1.1.2",
-                    "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.1.2.tgz",
-                    "integrity": "sha512-3QnhqeL+WW88YjYbQL5gUIkthuMw7a0NGbZ7wfFVk2kg/CK5w8w5FFa0RzWjyY1+sujN0NWbtSHH6OJmWHtJpQ==",
-                    "requires": {
-                        "@emotion/memoize": "^0.7.4"
-                    }
-                },
                 "@emotion/serialize": {
-                    "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz",
-                    "integrity": "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==",
+                    "version": "1.0.3",
+                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.3.tgz",
+                    "integrity": "sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA==",
                     "requires": {
                         "@emotion/hash": "^0.8.0",
                         "@emotion/memoize": "^0.7.4",
@@ -559,9 +436,9 @@
                     "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ=="
                 },
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
                 }
             }
         },
@@ -644,56 +521,28 @@
             }
         },
         "@fortawesome/react-fontawesome": {
-            "version": "0.1.17",
-            "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.17.tgz",
-            "integrity": "sha512-dX43Z5IvMaW7fwzU8farosYjKNGfRb2HB/DgjVBHeJZ/NSnuuaujPPx0YOdcAq+n3mqn70tyCde2HM1mqbhiuw==",
+            "version": "0.1.18",
+            "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.18.tgz",
+            "integrity": "sha512-RwLIB4TZw0M9gvy5u+TusAA0afbwM4JQIimNH/j3ygd6aIvYPQLqXMhC9ErY26J23rDPyDZldIfPq/HpTTJ/tQ==",
             "requires": {
                 "prop-types": "^15.8.1"
-            },
-            "dependencies": {
-                "prop-types": {
-                    "version": "15.8.1",
-                    "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
-                    "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
-                    "requires": {
-                        "loose-envify": "^1.4.0",
-                        "object-assign": "^4.1.1",
-                        "react-is": "^16.13.1"
-                    }
-                }
             }
         },
         "@googlemaps/js-api-loader": {
-            "version": "1.12.8",
-            "resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.12.8.tgz",
-            "integrity": "sha512-h1RNVIJkHWL4UrdJo8fwECJwSRg8CSIfTEtPdzvThcji7tAPvVBDVBPzvPKhvl8e8mWEGPhnYOt6kPfSxJL+vQ==",
+            "version": "1.14.3",
+            "resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.14.3.tgz",
+            "integrity": "sha512-6iIb+qpGgQpgIHmIFO44WhE1rDUxPVHuezNFL30wRJnkvhwFm94tD291UvNg9L05hLDSoL16jd0lbqqmdy4C5g==",
             "requires": {
                 "fast-deep-equal": "^3.1.3"
-            },
-            "dependencies": {
-                "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=="
-                }
             }
         },
         "@googlemaps/markerclusterer": {
-            "version": "1.0.12",
-            "resolved": "https://registry.npmjs.org/@googlemaps/markerclusterer/-/markerclusterer-1.0.12.tgz",
-            "integrity": "sha512-DSmN2w1ZoI+PBWfNCKYcr+zalP0uaaKIU08+UgebJYZ96X+J6CdUpD+xOVwBV1OJDiIXkneHquOZnT+V6dm+Sg==",
+            "version": "2.0.7",
+            "resolved": "https://registry.npmjs.org/@googlemaps/markerclusterer/-/markerclusterer-2.0.7.tgz",
+            "integrity": "sha512-/xADL31ERrNoVsF+O2A+H+obxOki4DHPQkU/STS5gFG6ZZVpvNV4WLisW2aOlOsH3rUXSq3MFjqFOEDXSQcvog==",
             "requires": {
-                "@turf/clusters-dbscan": "^6.4.0",
-                "@turf/clusters-kmeans": "^6.4.0",
                 "fast-deep-equal": "^3.1.3",
                 "supercluster": "^7.1.3"
-            },
-            "dependencies": {
-                "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=="
-                }
             }
         },
         "@hig/flyout": {
@@ -717,9 +566,9 @@
             }
         },
         "@hig/theme-data": {
-            "version": "2.23.1",
-            "resolved": "https://registry.npmjs.org/@hig/theme-data/-/theme-data-2.23.1.tgz",
-            "integrity": "sha512-Yca1iCIs8U1dpkLW1VNiKOJW9fCJdb70f1dc61+R+HO1QJ8jMBu5eOpmQE1NKotJmcazhsXpo6xC11yV1crE4w==",
+            "version": "2.26.0",
+            "resolved": "https://registry.npmjs.org/@hig/theme-data/-/theme-data-2.26.0.tgz",
+            "integrity": "sha512-jEiCieyafBePgFLlIPRPIhNPulWELeOgWJUY4wxdvozRdFUEq50ydx0ysuYPQOh4ucy0jI7Q8FcsBd+aEe7WXQ==",
             "requires": {
                 "tinycolor2": "^1.4.1"
             }
@@ -757,20 +606,63 @@
             "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz",
             "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw=="
         },
+        "@jridgewell/gen-mapping": {
+            "version": "0.3.1",
+            "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz",
+            "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==",
+            "requires": {
+                "@jridgewell/set-array": "^1.0.0",
+                "@jridgewell/sourcemap-codec": "^1.4.10",
+                "@jridgewell/trace-mapping": "^0.3.9"
+            }
+        },
+        "@jridgewell/resolve-uri": {
+            "version": "3.0.7",
+            "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz",
+            "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA=="
+        },
+        "@jridgewell/set-array": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz",
+            "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ=="
+        },
+        "@jridgewell/source-map": {
+            "version": "0.3.2",
+            "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
+            "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
+            "requires": {
+                "@jridgewell/gen-mapping": "^0.3.0",
+                "@jridgewell/trace-mapping": "^0.3.9"
+            }
+        },
+        "@jridgewell/sourcemap-codec": {
+            "version": "1.4.13",
+            "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz",
+            "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w=="
+        },
+        "@jridgewell/trace-mapping": {
+            "version": "0.3.13",
+            "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz",
+            "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==",
+            "requires": {
+                "@jridgewell/resolve-uri": "^3.0.3",
+                "@jridgewell/sourcemap-codec": "^1.4.10"
+            }
+        },
         "@log4js-node/log4js-api": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/@log4js-node/log4js-api/-/log4js-api-1.0.2.tgz",
             "integrity": "sha512-6SJfx949YEWooh/CUPpJ+F491y4BYJmknz4hUN1+RHvKoUEynKbRmhnwbk/VLmh4OthLLDNCyWXfbh4DG1cTXA=="
         },
         "@mapbox/node-pre-gyp": {
-            "version": "1.0.8",
-            "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.8.tgz",
-            "integrity": "sha512-CMGKi28CF+qlbXh26hDe6NxCd7amqeAzEqnS6IHeO6LoaKyM/n+Xw3HT1COdq8cuioOdlKdqn/hCmqPUOMOywg==",
+            "version": "1.0.9",
+            "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz",
+            "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==",
             "requires": {
-                "detect-libc": "^1.0.3",
+                "detect-libc": "^2.0.0",
                 "https-proxy-agent": "^5.0.0",
                 "make-dir": "^3.1.0",
-                "node-fetch": "^2.6.5",
+                "node-fetch": "^2.6.7",
                 "nopt": "^5.0.0",
                 "npmlog": "^5.0.1",
                 "rimraf": "^3.0.2",
@@ -778,104 +670,6 @@
                 "tar": "^6.1.11"
             },
             "dependencies": {
-                "ansi-regex": {
-                    "version": "5.0.1",
-                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-                    "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
-                },
-                "are-we-there-yet": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
-                    "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
-                    "requires": {
-                        "delegates": "^1.0.0",
-                        "readable-stream": "^3.6.0"
-                    }
-                },
-                "chownr": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
-                    "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="
-                },
-                "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=="
-                },
-                "fs-minipass": {
-                    "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
-                    "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
-                    "requires": {
-                        "minipass": "^3.0.0"
-                    }
-                },
-                "gauge": {
-                    "version": "3.0.2",
-                    "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
-                    "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
-                    "requires": {
-                        "aproba": "^1.0.3 || ^2.0.0",
-                        "color-support": "^1.1.2",
-                        "console-control-strings": "^1.0.0",
-                        "has-unicode": "^2.0.1",
-                        "object-assign": "^4.1.1",
-                        "signal-exit": "^3.0.0",
-                        "string-width": "^4.2.3",
-                        "strip-ansi": "^6.0.1",
-                        "wide-align": "^1.1.2"
-                    }
-                },
-                "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=="
-                },
-                "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==",
-                    "requires": {
-                        "yallist": "^4.0.0"
-                    }
-                },
-                "make-dir": {
-                    "version": "3.1.0",
-                    "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
-                    "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
-                    "requires": {
-                        "semver": "^6.0.0"
-                    },
-                    "dependencies": {
-                        "semver": {
-                            "version": "6.3.0",
-                            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-                            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
-                        }
-                    }
-                },
-                "minipass": {
-                    "version": "3.1.6",
-                    "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
-                    "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
-                    "requires": {
-                        "yallist": "^4.0.0"
-                    }
-                },
-                "minizlib": {
-                    "version": "2.1.2",
-                    "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
-                    "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
-                    "requires": {
-                        "minipass": "^3.0.0",
-                        "yallist": "^4.0.0"
-                    }
-                },
-                "mkdirp": {
-                    "version": "1.0.4",
-                    "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
-                    "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
-                },
                 "node-fetch": {
                     "version": "2.6.7",
                     "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
@@ -884,100 +678,26 @@
                         "whatwg-url": "^5.0.0"
                     }
                 },
-                "nopt": {
-                    "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
-                    "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
-                    "requires": {
-                        "abbrev": "1"
-                    }
-                },
-                "npmlog": {
-                    "version": "5.0.1",
-                    "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
-                    "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
-                    "requires": {
-                        "are-we-there-yet": "^2.0.0",
-                        "console-control-strings": "^1.1.0",
-                        "gauge": "^3.0.0",
-                        "set-blocking": "^2.0.0"
-                    }
-                },
                 "semver": {
-                    "version": "7.3.5",
-                    "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
-                    "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+                    "version": "7.3.7",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+                    "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
                     "requires": {
                         "lru-cache": "^6.0.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==",
-                    "requires": {
-                        "emoji-regex": "^8.0.0",
-                        "is-fullwidth-code-point": "^3.0.0",
-                        "strip-ansi": "^6.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==",
-                    "requires": {
-                        "ansi-regex": "^5.0.1"
-                    }
-                },
-                "tar": {
-                    "version": "6.1.11",
-                    "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
-                    "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
-                    "requires": {
-                        "chownr": "^2.0.0",
-                        "fs-minipass": "^2.0.0",
-                        "minipass": "^3.0.0",
-                        "minizlib": "^2.1.1",
-                        "mkdirp": "^1.0.3",
-                        "yallist": "^4.0.0"
-                    }
-                },
-                "tr46": {
-                    "version": "0.0.3",
-                    "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
-                    "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
-                },
-                "webidl-conversions": {
-                    "version": "3.0.1",
-                    "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
-                    "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
-                },
-                "whatwg-url": {
-                    "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
-                    "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
-                    "requires": {
-                        "tr46": "~0.0.3",
-                        "webidl-conversions": "^3.0.0"
-                    }
-                },
-                "yallist": {
-                    "version": "4.0.0",
-                    "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-                    "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
                 }
             }
         },
         "@material-ui/core": {
-            "version": "4.12.3",
-            "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.3.tgz",
-            "integrity": "sha512-sdpgI/PL56QVsEJldwEe4FFaFTLUqN+rd7sSZiRCdx2E/C7z5yK0y/khAWVBH24tXwto7I1hCzNWfJGZIYJKnw==",
+            "version": "4.12.4",
+            "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.4.tgz",
+            "integrity": "sha512-tr7xekNlM9LjA6pagJmL8QCgZXaubWUwkJnoYcMKd4gw/t4XiyvnTkjdGrUVicyB2BsdaAv1tvow45bPM4sSwQ==",
             "requires": {
                 "@babel/runtime": "^7.4.4",
-                "@material-ui/styles": "^4.11.4",
-                "@material-ui/system": "^4.12.1",
+                "@material-ui/styles": "^4.11.5",
+                "@material-ui/system": "^4.12.2",
                 "@material-ui/types": "5.1.0",
-                "@material-ui/utils": "^4.11.2",
+                "@material-ui/utils": "^4.11.3",
                 "@types/react-transition-group": "^4.2.0",
                 "clsx": "^1.0.4",
                 "hoist-non-react-statics": "^3.3.2",
@@ -988,9 +708,9 @@
             },
             "dependencies": {
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
                 },
                 "dom-helpers": {
                     "version": "5.2.1",
@@ -1015,14 +735,14 @@
             }
         },
         "@material-ui/styles": {
-            "version": "4.11.4",
-            "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz",
-            "integrity": "sha512-KNTIZcnj/zprG5LW0Sao7zw+yG3O35pviHzejMdcSGCdWbiO8qzRgOYL8JAxAsWBKOKYwVZxXtHWaB5T2Kvxew==",
+            "version": "4.11.5",
+            "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.5.tgz",
+            "integrity": "sha512-o/41ot5JJiUsIETME9wVLAJrmIWL3j0R0Bj2kCOLbSfqEkKf0fmaPt+5vtblUh5eXr2S+J/8J3DaCb10+CzPGA==",
             "requires": {
                 "@babel/runtime": "^7.4.4",
                 "@emotion/hash": "^0.8.0",
                 "@material-ui/types": "5.1.0",
-                "@material-ui/utils": "^4.11.2",
+                "@material-ui/utils": "^4.11.3",
                 "clsx": "^1.0.4",
                 "csstype": "^2.5.2",
                 "hoist-non-react-statics": "^3.3.2",
@@ -1038,12 +758,12 @@
             }
         },
         "@material-ui/system": {
-            "version": "4.12.1",
-            "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.1.tgz",
-            "integrity": "sha512-lUdzs4q9kEXZGhbN7BptyiS1rLNHe6kG9o8Y307HCvF4sQxbCgpL2qi+gUk+yI8a2DNk48gISEQxoxpgph0xIw==",
+            "version": "4.12.2",
+            "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.2.tgz",
+            "integrity": "sha512-6CSKu2MtmiJgcCGf6nBQpM8fLkuB9F55EKfbdTC80NND5wpTmKzwdhLYLH3zL4cLlK0gVaaltW7/wMuyTnN0Lw==",
             "requires": {
                 "@babel/runtime": "^7.4.4",
-                "@material-ui/utils": "^4.11.2",
+                "@material-ui/utils": "^4.11.3",
                 "csstype": "^2.5.2",
                 "prop-types": "^15.7.2"
             }
@@ -1054,9 +774,9 @@
             "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A=="
         },
         "@material-ui/utils": {
-            "version": "4.11.2",
-            "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.2.tgz",
-            "integrity": "sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==",
+            "version": "4.11.3",
+            "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.3.tgz",
+            "integrity": "sha512-ZuQPV4rBK/V1j2dIkSSEcH5uT6AaHuKWFfotADHsC0wVL1NLd2WkFCm4ZZbX33iO4ydl6V0GPngKm8HZQ2oujg==",
             "requires": {
                 "@babel/runtime": "^7.4.4",
                 "prop-types": "^15.7.2",
@@ -1064,27 +784,27 @@
             }
         },
         "@react-google-maps/api": {
-            "version": "2.7.0",
-            "resolved": "https://registry.npmjs.org/@react-google-maps/api/-/api-2.7.0.tgz",
-            "integrity": "sha512-Fb/l7aR69ObYvzhpt1d1931454ylRkTPKF1C8GfLvXtg19wc36zTev2Afbahd+qAdyKuQyDdf5/SQyMjYBHI/A==",
-            "requires": {
-                "@googlemaps/js-api-loader": "1.12.8",
-                "@googlemaps/markerclusterer": "1.0.12",
-                "@react-google-maps/infobox": "2.6.0",
-                "@react-google-maps/marker-clusterer": "2.6.0",
-                "@types/google.maps": "3.46.1",
+            "version": "2.12.0",
+            "resolved": "https://registry.npmjs.org/@react-google-maps/api/-/api-2.12.0.tgz",
+            "integrity": "sha512-BqsclJ9p2I6yZa++0R3oEcneECcH7PFsULhn8UDlWQ9uNAQR/aqvqGb9SXYvdpIAOJdk3E737iTrGhFg4j5Ucw==",
+            "requires": {
+                "@googlemaps/js-api-loader": "1.14.3",
+                "@googlemaps/markerclusterer": "2.0.7",
+                "@react-google-maps/infobox": "2.11.8",
+                "@react-google-maps/marker-clusterer": "2.11.8",
+                "@types/google.maps": "3.49.1",
                 "invariant": "2.2.4"
             }
         },
         "@react-google-maps/infobox": {
-            "version": "2.6.0",
-            "resolved": "https://registry.npmjs.org/@react-google-maps/infobox/-/infobox-2.6.0.tgz",
-            "integrity": "sha512-2dXVZsuZ2PjelVg+slpUSYPnvoSIySwf4P/wScGijjqu6bpvhyX9AivitsF7zHfbwnZ0gAPX1Q8xtQhKgawkEg=="
+            "version": "2.11.8",
+            "resolved": "https://registry.npmjs.org/@react-google-maps/infobox/-/infobox-2.11.8.tgz",
+            "integrity": "sha512-15y3dniys1Op5HREyLwiJI2pAdeeHRJT5b4WPrS+vyL5KF6iXK1P3y/9bXtnxHiKe2v6iPreaEhR3VgvfRA50Q=="
         },
         "@react-google-maps/marker-clusterer": {
-            "version": "2.6.0",
-            "resolved": "https://registry.npmjs.org/@react-google-maps/marker-clusterer/-/marker-clusterer-2.6.0.tgz",
-            "integrity": "sha512-EjeoCM+U/6W9qoGWqurcDbCubqTEDTFET7Jd3XcLHqTLvFAE473x2YbQg98mJXKNgPKcPTNEcTiYYGiIz9tEjA=="
+            "version": "2.11.8",
+            "resolved": "https://registry.npmjs.org/@react-google-maps/marker-clusterer/-/marker-clusterer-2.11.8.tgz",
+            "integrity": "sha512-OEcdbTXEgPwdpGvVuSrhIhjcZPhlzPz2TvaKCBLraf1PKiDyLOPhlTVRlbIziLiu0xN89pJcill1w9UVIVFF+Q=="
         },
         "@react-three/fiber": {
             "version": "6.2.3",
@@ -1101,16 +821,6 @@
                 "use-asset": "^1.0.4",
                 "utility-types": "^3.10.0",
                 "zustand": "^3.5.1"
-            },
-            "dependencies": {
-                "@babel/runtime": {
-                    "version": "7.17.2",
-                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz",
-                    "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==",
-                    "requires": {
-                        "regenerator-runtime": "^0.13.4"
-                    }
-                }
             }
         },
         "@rkusa/linebreak": {
@@ -1126,12 +836,6 @@
             "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
             "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="
         },
-        "@socket.io/component-emitter": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.0.0.tgz",
-            "integrity": "sha512-2pTGuibAXJswAPJjaKisthqS/NOK5ypG4LYT6tEAV0S/mxW0zOIvYvGK0V8w8+SHxAm6vRMSjqSalFXeBAqs+Q==",
-            "dev": true
-        },
         "@szmarczak/http-timer": {
             "version": "5.0.1",
             "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz",
@@ -1140,75 +844,13 @@
                 "defer-to-connect": "^2.0.1"
             }
         },
-        "@turf/clone": {
-            "version": "6.5.0",
-            "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-6.5.0.tgz",
-            "integrity": "sha512-mzVtTFj/QycXOn6ig+annKrM6ZlimreKYz6f/GSERytOpgzodbQyOgkfwru100O1KQhhjSudKK4DsQ0oyi9cTw==",
-            "requires": {
-                "@turf/helpers": "^6.5.0"
-            }
-        },
-        "@turf/clusters-dbscan": {
-            "version": "6.5.0",
-            "resolved": "https://registry.npmjs.org/@turf/clusters-dbscan/-/clusters-dbscan-6.5.0.tgz",
-            "integrity": "sha512-SxZEE4kADU9DqLRiT53QZBBhu8EP9skviSyl+FGj08Y01xfICM/RR9ACUdM0aEQimhpu+ZpRVcUK+2jtiCGrYQ==",
-            "requires": {
-                "@turf/clone": "^6.5.0",
-                "@turf/distance": "^6.5.0",
-                "@turf/helpers": "^6.5.0",
-                "@turf/meta": "^6.5.0",
-                "density-clustering": "1.3.0"
-            }
-        },
-        "@turf/clusters-kmeans": {
-            "version": "6.5.0",
-            "resolved": "https://registry.npmjs.org/@turf/clusters-kmeans/-/clusters-kmeans-6.5.0.tgz",
-            "integrity": "sha512-DwacD5+YO8kwDPKaXwT9DV46tMBVNsbi1IzdajZu1JDSWoN7yc7N9Qt88oi+p30583O0UPVkAK+A10WAQv4mUw==",
+        "@types/adm-zip": {
+            "version": "0.4.34",
+            "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.4.34.tgz",
+            "integrity": "sha512-8ToYLLAYhkRfcmmljrKi22gT2pqu7hGMDtORP1emwIEGmgUTZOsaDjzWFzW5N2frcFRz/50CWt4zA1CxJ73pmQ==",
+            "dev": true,
             "requires": {
-                "@turf/clone": "^6.5.0",
-                "@turf/helpers": "^6.5.0",
-                "@turf/invariant": "^6.5.0",
-                "@turf/meta": "^6.5.0",
-                "skmeans": "0.9.7"
-            }
-        },
-        "@turf/distance": {
-            "version": "6.5.0",
-            "resolved": "https://registry.npmjs.org/@turf/distance/-/distance-6.5.0.tgz",
-            "integrity": "sha512-xzykSLfoURec5qvQJcfifw/1mJa+5UwByZZ5TZ8iaqjGYN0vomhV9aiSLeYdUGtYRESZ+DYC/OzY+4RclZYgMg==",
-            "requires": {
-                "@turf/helpers": "^6.5.0",
-                "@turf/invariant": "^6.5.0"
-            }
-        },
-        "@turf/helpers": {
-            "version": "6.5.0",
-            "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-6.5.0.tgz",
-            "integrity": "sha512-VbI1dV5bLFzohYYdgqwikdMVpe7pJ9X3E+dlr425wa2/sMJqYDhTO++ec38/pcPvPE6oD9WEEeU3Xu3gza+VPw=="
-        },
-        "@turf/invariant": {
-            "version": "6.5.0",
-            "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-6.5.0.tgz",
-            "integrity": "sha512-Wv8PRNCtPD31UVbdJE/KVAWKe7l6US+lJItRR/HOEW3eh+U/JwRCSUl/KZ7bmjM/C+zLNoreM2TU6OoLACs4eg==",
-            "requires": {
-                "@turf/helpers": "^6.5.0"
-            }
-        },
-        "@turf/meta": {
-            "version": "6.5.0",
-            "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-6.5.0.tgz",
-            "integrity": "sha512-RrArvtsV0vdsCBegoBtOalgdSOfkBrTJ07VkpiCnq/491W67hnMWmDu7e6Ztw0C3WldRYTXkg3SumfdzZxLBHA==",
-            "requires": {
-                "@turf/helpers": "^6.5.0"
-            }
-        },
-        "@types/adm-zip": {
-            "version": "0.4.34",
-            "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.4.34.tgz",
-            "integrity": "sha512-8ToYLLAYhkRfcmmljrKi22gT2pqu7hGMDtORP1emwIEGmgUTZOsaDjzWFzW5N2frcFRz/50CWt4zA1CxJ73pmQ==",
-            "dev": true,
-            "requires": {
-                "@types/node": "*"
+                "@types/node": "*"
             }
         },
         "@types/animejs": {
@@ -1238,14 +880,14 @@
             "dev": true
         },
         "@types/babel-types": {
-            "version": "7.0.7",
-            "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.7.tgz",
-            "integrity": "sha512-dBtBbrc+qTHy1WdfHYjBwRln4+LWqASWakLHsWHR2NWHIFkv4W3O070IGoGLEBrJBvct3r0L1BUPuvURi7kYUQ=="
+            "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.5",
-            "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.5.tgz",
-            "integrity": "sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w==",
+            "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": "*"
             }
@@ -1253,7 +895,7 @@
         "@types/bcrypt-nodejs": {
             "version": "0.0.30",
             "resolved": "https://registry.npmjs.org/@types/bcrypt-nodejs/-/bcrypt-nodejs-0.0.30.tgz",
-            "integrity": "sha1-TN2WtJKTs5MhIuS34pVD415rrlg=",
+            "integrity": "sha512-gSWCu7EOXhcM0FYM8tanV0deaX1VM07sgBS8dSUmgnAQ5/3Xn6k+mWF+ZfE+c/OCW14IVnNdTOKcHgvL78oDFQ==",
             "dev": true
         },
         "@types/bezier-js": {
@@ -1278,11 +920,18 @@
             }
         },
         "@types/bson": {
-            "version": "4.2.0",
-            "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.2.0.tgz",
-            "integrity": "sha512-ELCPqAdroMdcuxqwMgUpifQyRoTpyYCNr1V9xKyF40VsBobsj+BbWNRvwGchMgBPGqkw655ypkjj2MEF5ywVwg==",
+            "version": "4.0.5",
+            "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.5.tgz",
+            "integrity": "sha512-vVLwMUqhYJSQ/WKcE60eFqcyuWse5fGH+NMAXHuKrUAPoryq3ATxk5o4bgYNtg5aOM4APVg7Hnb3ASqUYG0PKg==",
             "requires": {
-                "bson": "*"
+                "@types/node": "*"
+            },
+            "dependencies": {
+                "@types/node": {
+                    "version": "17.0.40",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.40.tgz",
+                    "integrity": "sha512-UXdBxNGqTMtm7hCwh9HtncFVLrXoqA3oJW30j6XWp5BH/wu3mVeaxo7cq5benFdBw34HB3XDT2TRPI7rXZ+mDg=="
+                }
             }
         },
         "@types/cacheable-request": {
@@ -1294,6 +943,13 @@
                 "@types/keyv": "*",
                 "@types/node": "*",
                 "@types/responselike": "*"
+            },
+            "dependencies": {
+                "@types/node": {
+                    "version": "17.0.40",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.40.tgz",
+                    "integrity": "sha512-UXdBxNGqTMtm7hCwh9HtncFVLrXoqA3oJW30j6XWp5BH/wu3mVeaxo7cq5benFdBw34HB3XDT2TRPI7rXZ+mDg=="
+                }
             }
         },
         "@types/caseless": {
@@ -1303,9 +959,9 @@
             "dev": true
         },
         "@types/chai": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz",
-            "integrity": "sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw==",
+            "version": "4.3.1",
+            "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.1.tgz",
+            "integrity": "sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ==",
             "dev": true
         },
         "@types/color": {
@@ -1329,12 +985,13 @@
         "@types/color-name": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
-            "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
+            "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
+            "dev": true
         },
         "@types/connect": {
-            "version": "3.4.33",
-            "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz",
-            "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==",
+            "version": "3.4.35",
+            "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
+            "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
             "dev": true,
             "requires": {
                 "@types/node": "*"
@@ -1350,9 +1007,9 @@
             }
         },
         "@types/cookie-parser": {
-            "version": "1.4.2",
-            "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.2.tgz",
-            "integrity": "sha512-uwcY8m6SDQqciHsqcKDGbo10GdasYsPCYkH3hVegj9qAah6pX5HivOnOuI3WYmyQMnOATV39zv/Ybs0bC/6iVg==",
+            "version": "1.4.3",
+            "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.3.tgz",
+            "integrity": "sha512-CqSKwFwefj4PzZ5n/iwad/bow2hTCh0FlNAeWLtQM3JA/NX/iYagIpWG2cf1bQKQ2c9gU2log5VUCrn7LDOs0w==",
             "dev": true,
             "requires": {
                 "@types/express": "*"
@@ -1428,9 +1085,9 @@
             }
         },
         "@types/eslint": {
-            "version": "8.4.1",
-            "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz",
-            "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==",
+            "version": "8.4.2",
+            "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.2.tgz",
+            "integrity": "sha512-Z1nseZON+GEnFjJc04sv4NSALGjhFwy6K0HXt7qsn5ArfAKtb63dXNJHf+1YW6IpOIYRBGUbu3GwJdj8DGnCjA==",
             "dev": true,
             "requires": {
                 "@types/estree": "*",
@@ -1531,6 +1188,13 @@
             "requires": {
                 "@types/events": "*",
                 "@types/node": "*"
+            },
+            "dependencies": {
+                "@types/node": {
+                    "version": "17.0.40",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.40.tgz",
+                    "integrity": "sha512-UXdBxNGqTMtm7hCwh9HtncFVLrXoqA3oJW30j6XWp5BH/wu3mVeaxo7cq5benFdBw34HB3XDT2TRPI7rXZ+mDg=="
+                }
             }
         },
         "@types/geojson": {
@@ -1566,9 +1230,9 @@
             }
         },
         "@types/google.maps": {
-            "version": "3.46.1",
-            "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.46.1.tgz",
-            "integrity": "sha512-GAa5ZWYgXG50yLXybb7A824esGm/L0LKHS7qD0qkP0IA/Qp5r922P9tmYcbCkGEf3Zgf7Ukbp7l08/IGIJuQwQ=="
+            "version": "3.49.1",
+            "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.49.1.tgz",
+            "integrity": "sha512-Sbl5anucT7LUcUxXsRxkCozHdXIkUiY+Tyru+OVl5rot0+VIZuuulmABC7X+nF7rL7BRTAguSBSAD/e/AfIkkA=="
         },
         "@types/hoist-non-react-statics": {
             "version": "3.3.1",
@@ -1577,6 +1241,23 @@
             "requires": {
                 "@types/react": "*",
                 "hoist-non-react-statics": "^3.3.0"
+            },
+            "dependencies": {
+                "@types/react": {
+                    "version": "18.0.12",
+                    "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.12.tgz",
+                    "integrity": "sha512-duF1OTASSBQtcigUvhuiTB1Ya3OvSy+xORCiEf20H0P0lzx+/KeVsA99U5UjLXSbyo1DRJDlLKqTeM1ngosqtg==",
+                    "requires": {
+                        "@types/prop-types": "*",
+                        "@types/scheduler": "*",
+                        "csstype": "^3.0.2"
+                    }
+                },
+                "csstype": {
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
+                }
             }
         },
         "@types/html-minifier-terser": {
@@ -1606,12 +1287,24 @@
                 "@types/node": "*",
                 "@types/parse5": "*",
                 "@types/tough-cookie": "*"
+            },
+            "dependencies": {
+                "@types/node": {
+                    "version": "17.0.40",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.40.tgz",
+                    "integrity": "sha512-UXdBxNGqTMtm7hCwh9HtncFVLrXoqA3oJW30j6XWp5BH/wu3mVeaxo7cq5benFdBw34HB3XDT2TRPI7rXZ+mDg=="
+                }
             }
         },
+        "@types/json-buffer": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/@types/json-buffer/-/json-buffer-3.0.0.tgz",
+            "integrity": "sha512-3YP80IxxFJB4b5tYC2SUPwkg0XQLiu0nWvhRgEatgjf+29IcWO9X1k8xRv5DGssJ/lCrjYTjQPcobJr2yWIVuQ=="
+        },
         "@types/json-schema": {
-            "version": "7.0.9",
-            "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
-            "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ=="
+            "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=="
         },
         "@types/keygrip": {
             "version": "1.0.2",
@@ -1620,11 +1313,18 @@
             "dev": true
         },
         "@types/keyv": {
-            "version": "3.1.3",
-            "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz",
-            "integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==",
+            "version": "3.1.4",
+            "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
+            "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
             "requires": {
                 "@types/node": "*"
+            },
+            "dependencies": {
+                "@types/node": {
+                    "version": "17.0.40",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.40.tgz",
+                    "integrity": "sha512-UXdBxNGqTMtm7hCwh9HtncFVLrXoqA3oJW30j6XWp5BH/wu3mVeaxo7cq5benFdBw34HB3XDT2TRPI7rXZ+mDg=="
+                }
             }
         },
         "@types/libxmljs": {
@@ -1637,9 +1337,9 @@
             }
         },
         "@types/lodash": {
-            "version": "4.14.179",
-            "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.179.tgz",
-            "integrity": "sha512-uwc1x90yCKqGcIOAT6DwOSuxnrAbpkdPsUOZtwrXb4D/6wZs+6qG7QnIawDuZWg0sWpxl+ltIKCaLoMlna678w==",
+            "version": "4.14.182",
+            "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz",
+            "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==",
             "dev": true
         },
         "@types/mime": {
@@ -1676,6 +1376,13 @@
             "requires": {
                 "@types/bson": "*",
                 "@types/node": "*"
+            },
+            "dependencies": {
+                "@types/node": {
+                    "version": "17.0.40",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.40.tgz",
+                    "integrity": "sha512-UXdBxNGqTMtm7hCwh9HtncFVLrXoqA3oJW30j6XWp5BH/wu3mVeaxo7cq5benFdBw34HB3XDT2TRPI7rXZ+mDg=="
+                }
             }
         },
         "@types/mongoose": {
@@ -1690,7 +1397,8 @@
         "@types/node": {
             "version": "10.17.60",
             "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz",
-            "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw=="
+            "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==",
+            "dev": true
         },
         "@types/nodemailer": {
             "version": "4.6.8",
@@ -1727,9 +1435,9 @@
             "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g=="
         },
         "@types/passport": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.7.tgz",
-            "integrity": "sha512-JtswU8N3kxBYgo+n9of7C97YQBT+AYPP2aBfNGTzABqPAZnK/WOAaKfh3XesUYMZRrXFuoPc2Hv0/G/nQFveHw==",
+            "version": "1.0.8",
+            "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.8.tgz",
+            "integrity": "sha512-Gdcvis7+7G/Mobm+25AeFi+oe5teBhHzpbCOFWeN10Bj8tnoEE1L5lkraQjzmDEKkJQuM7xSJUGIFGl/giyRfQ==",
             "dev": true,
             "requires": {
                 "@types/express": "*"
@@ -1788,9 +1496,9 @@
             }
         },
         "@types/prop-types": {
-            "version": "15.7.4",
-            "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz",
-            "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ=="
+            "version": "15.7.5",
+            "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
+            "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
         },
         "@types/prosemirror-commands": {
             "version": "1.0.4",
@@ -1857,9 +1565,9 @@
             }
         },
         "@types/prosemirror-model": {
-            "version": "1.16.1",
-            "resolved": "https://registry.npmjs.org/@types/prosemirror-model/-/prosemirror-model-1.16.1.tgz",
-            "integrity": "sha512-SrrCe2cHlYrQ9o55e2i/c3wt1yRajTTpRLvzfmB+2DWjWEbBLTByVWyjrdpKtQTxAaTeU2aeDGo1iuwl/jF27w==",
+            "version": "1.16.2",
+            "resolved": "https://registry.npmjs.org/@types/prosemirror-model/-/prosemirror-model-1.16.2.tgz",
+            "integrity": "sha512-1XPJopkKP3oHSBP61uuSuW13DIDZPWvAzP6Pv2/6mixk8EBPUeRGIW548DjJTicMo23gEg1zvCZy9asblQdWag==",
             "dev": true,
             "requires": {
                 "@types/orderedmap": "*"
@@ -1877,9 +1585,9 @@
             }
         },
         "@types/prosemirror-state": {
-            "version": "1.2.8",
-            "resolved": "https://registry.npmjs.org/@types/prosemirror-state/-/prosemirror-state-1.2.8.tgz",
-            "integrity": "sha512-mq9uyQWcpu8jeamO6Callrdvf/e1H/aRLR2kZWSpZrPHctEsxWHBbluD/wqVjXBRIOoMHLf6ZvOkrkmGLoCHVA==",
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/@types/prosemirror-state/-/prosemirror-state-1.3.0.tgz",
+            "integrity": "sha512-nMdUF6w8B++NH4V54X+4GvDty7M02UfuHQW0s1AS25Z4ZrOW4RSY2+s57doXBbeMSjzYV/QoMxCY2sT3KQ2VdQ==",
             "dev": true,
             "requires": {
                 "@types/prosemirror-model": "*",
@@ -1888,18 +1596,18 @@
             }
         },
         "@types/prosemirror-transform": {
-            "version": "1.1.5",
-            "resolved": "https://registry.npmjs.org/@types/prosemirror-transform/-/prosemirror-transform-1.1.5.tgz",
-            "integrity": "sha512-Wr2HXaEF4JPklWpC17RTxE6PxyU54Taqk5FMhK1ojgcN93J+GpkYW8s0mD3rl7KfTmlhVwZPCHE9o0cYf2Go5A==",
+            "version": "1.4.2",
+            "resolved": "https://registry.npmjs.org/@types/prosemirror-transform/-/prosemirror-transform-1.4.2.tgz",
+            "integrity": "sha512-FZNzjYm6YUkb1XXOrw2193TiFzwM92ui1nycNaRSd5JDbugf9yBLkXm4Rq3HGJJxBBkRcUE8niqUW5aWlXQQiQ==",
             "dev": true,
             "requires": {
                 "@types/prosemirror-model": "*"
             }
         },
         "@types/prosemirror-view": {
-            "version": "1.23.1",
-            "resolved": "https://registry.npmjs.org/@types/prosemirror-view/-/prosemirror-view-1.23.1.tgz",
-            "integrity": "sha512-6e1B2oKUnhmZPUrsVvYjDqeVjE6jGezygjtoHsAK4ZENAxHzHqy5NT4jUvdPTWjCYeH0t2Y7pSfRPNrPIyQX4A==",
+            "version": "1.23.3",
+            "resolved": "https://registry.npmjs.org/@types/prosemirror-view/-/prosemirror-view-1.23.3.tgz",
+            "integrity": "sha512-T5dPDmZiXAazJVSvnx55D6h4mcpiH2q2wTyO9zIeOdox5zx964+zcDl9dFNaXG3qCGlERwMPckhBZL1HCxyygw==",
             "dev": true,
             "requires": {
                 "@types/prosemirror-model": "*",
@@ -1929,9 +1637,10 @@
             }
         },
         "@types/react": {
-            "version": "16.14.23",
-            "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.23.tgz",
-            "integrity": "sha512-WngBZLuSkP4IAgPi0HOsGCHo6dn3CcuLQnCfC17VbA7YBgipZiZoTOhObwl/93DsFW0Y2a/ZXeonpW4DxirEJg==",
+            "version": "16.14.26",
+            "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.26.tgz",
+            "integrity": "sha512-c/5CYyciOO4XdFcNhZW1O2woVx86k4T+DO2RorHZL7EhitkNQgSD/SgpdZJAUJa/qjVgOmTM44gHkAdZSXeQuQ==",
+            "dev": true,
             "requires": {
                 "@types/prop-types": "*",
                 "@types/scheduler": "*",
@@ -1939,9 +1648,10 @@
             },
             "dependencies": {
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==",
+                    "dev": true
                 }
             }
         },
@@ -1984,9 +1694,9 @@
             }
         },
         "@types/react-dom": {
-            "version": "16.9.14",
-            "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.14.tgz",
-            "integrity": "sha512-FIX2AVmPTGP30OUJ+0vadeIFJJ07Mh1m+U0rxfgyW34p3rTlXI+nlenvAxNn4BP36YyI9IJ/+UJ7Wu22N1pI7A==",
+            "version": "16.9.16",
+            "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.16.tgz",
+            "integrity": "sha512-Oqc0RY4fggGA3ltEgyPLc3IV9T73IGoWjkONbsyJ3ZBn+UPPCYpU2ec0i3cEbJuEdZtkqcCF2l1zf2pBdgUGSg==",
             "dev": true,
             "requires": {
                 "@types/react": "^16"
@@ -2019,22 +1729,56 @@
             }
         },
         "@types/react-reconciler": {
-            "version": "0.26.4",
-            "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.26.4.tgz",
-            "integrity": "sha512-bdx4aIBkQRDAnzc23JBFeZmVpmfLJHfHikmQukEt9qs4bQtq9f+PDbNwhR9u74FkIUyIDz1I1qJ8OF6RwadKpw==",
+            "version": "0.26.7",
+            "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.26.7.tgz",
+            "integrity": "sha512-mBDYl8x+oyPX/VBb3E638N0B7xG+SPk/EAMcVPeexqus/5aTpTphQi0curhhshOqRrc9t6OPoJfEUkbymse/lQ==",
             "requires": {
                 "@types/react": "*"
+            },
+            "dependencies": {
+                "@types/react": {
+                    "version": "18.0.12",
+                    "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.12.tgz",
+                    "integrity": "sha512-duF1OTASSBQtcigUvhuiTB1Ya3OvSy+xORCiEf20H0P0lzx+/KeVsA99U5UjLXSbyo1DRJDlLKqTeM1ngosqtg==",
+                    "requires": {
+                        "@types/prop-types": "*",
+                        "@types/scheduler": "*",
+                        "csstype": "^3.0.2"
+                    }
+                },
+                "csstype": {
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
+                }
             }
         },
         "@types/react-redux": {
-            "version": "7.1.22",
-            "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.22.tgz",
-            "integrity": "sha512-GxIA1kM7ClU73I6wg9IRTVwSO9GS+SAKZKe0Enj+82HMU6aoESFU2HNAdNi3+J53IaOHPiUfT3kSG4L828joDQ==",
+            "version": "7.1.24",
+            "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz",
+            "integrity": "sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ==",
             "requires": {
                 "@types/hoist-non-react-statics": "^3.3.0",
                 "@types/react": "*",
                 "hoist-non-react-statics": "^3.3.0",
                 "redux": "^4.0.0"
+            },
+            "dependencies": {
+                "@types/react": {
+                    "version": "18.0.12",
+                    "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.12.tgz",
+                    "integrity": "sha512-duF1OTASSBQtcigUvhuiTB1Ya3OvSy+xORCiEf20H0P0lzx+/KeVsA99U5UjLXSbyo1DRJDlLKqTeM1ngosqtg==",
+                    "requires": {
+                        "@types/prop-types": "*",
+                        "@types/scheduler": "*",
+                        "csstype": "^3.0.2"
+                    }
+                },
+                "csstype": {
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
+                }
             }
         },
         "@types/react-select": {
@@ -2054,6 +1798,23 @@
             "integrity": "sha512-fVQXjy/EYDbgraScgjDONA291McKqGrw0R0NeK639fx2bS4T19TnXMjg3FjOPlkI3qYTQtFTPADlRYysaQIMpA==",
             "requires": {
                 "@types/react": "*"
+            },
+            "dependencies": {
+                "@types/react": {
+                    "version": "18.0.12",
+                    "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.12.tgz",
+                    "integrity": "sha512-duF1OTASSBQtcigUvhuiTB1Ya3OvSy+xORCiEf20H0P0lzx+/KeVsA99U5UjLXSbyo1DRJDlLKqTeM1ngosqtg==",
+                    "requires": {
+                        "@types/prop-types": "*",
+                        "@types/scheduler": "*",
+                        "csstype": "^3.0.2"
+                    }
+                },
+                "csstype": {
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
+                }
             }
         },
         "@types/react-transition-group": {
@@ -2062,6 +1823,23 @@
             "integrity": "sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug==",
             "requires": {
                 "@types/react": "*"
+            },
+            "dependencies": {
+                "@types/react": {
+                    "version": "18.0.12",
+                    "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.12.tgz",
+                    "integrity": "sha512-duF1OTASSBQtcigUvhuiTB1Ya3OvSy+xORCiEf20H0P0lzx+/KeVsA99U5UjLXSbyo1DRJDlLKqTeM1ngosqtg==",
+                    "requires": {
+                        "@types/prop-types": "*",
+                        "@types/scheduler": "*",
+                        "csstype": "^3.0.2"
+                    }
+                },
+                "csstype": {
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
+                }
             }
         },
         "@types/reactcss": {
@@ -2083,6 +1861,19 @@
                 "@types/node": "*",
                 "@types/tough-cookie": "*",
                 "form-data": "^2.5.0"
+            },
+            "dependencies": {
+                "form-data": {
+                    "version": "2.5.1",
+                    "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
+                    "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
+                    "dev": true,
+                    "requires": {
+                        "asynckit": "^0.4.0",
+                        "combined-stream": "^1.0.6",
+                        "mime-types": "^2.1.12"
+                    }
+                }
             }
         },
         "@types/request-promise": {
@@ -2101,6 +1892,13 @@
             "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==",
             "requires": {
                 "@types/node": "*"
+            },
+            "dependencies": {
+                "@types/node": {
+                    "version": "17.0.40",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.40.tgz",
+                    "integrity": "sha512-UXdBxNGqTMtm7hCwh9HtncFVLrXoqA3oJW30j6XWp5BH/wu3mVeaxo7cq5benFdBw34HB3XDT2TRPI7rXZ+mDg=="
+                }
             }
         },
         "@types/reveal": {
@@ -2193,7 +1991,7 @@
         "@types/strip-bom": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
-            "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=",
+            "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==",
             "dev": true
         },
         "@types/strip-json-comments": {
@@ -2222,23 +2020,23 @@
             "integrity": "sha512-6JqTgijtfXcTJik8NtiNxr2L90ex6ElM00qilOGeUcrEsJLOdzLJSIkXHUYS+KPAYQYtRJQKD6XaXds3HjS+gg=="
         },
         "@types/tough-cookie": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.1.tgz",
-            "integrity": "sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg=="
+            "version": "4.0.2",
+            "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz",
+            "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw=="
         },
         "@types/typescript": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/@types/typescript/-/typescript-2.0.0.tgz",
-            "integrity": "sha1-xDNTnJi64oaCswfqp6D9IRW4PCg=",
+            "integrity": "sha512-WMEWfMISiJ2QKyk5/dSdgL0ZwP//PZj0jmDU0hMh51FmLq4WIYzjlngsUQZXejQL+QtkXJUOGjb3G3UCvgZuSQ==",
             "dev": true,
             "requires": {
                 "typescript": "*"
             }
         },
         "@types/uglify-js": {
-            "version": "3.13.1",
-            "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.1.tgz",
-            "integrity": "sha512-O3MmRAk6ZuAKa9CHgg0Pr0+lUOqoMLpc9AS4R8ano2auvsg7IE8syF3Xh/NPr26TWklxYcqoEEFdzLLs1fV9PQ==",
+            "version": "3.13.3",
+            "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.3.tgz",
+            "integrity": "sha512-9dmBYXt/rKxedUXfCvXSxyiPvpDXLkiRlv17DnqdhS+pRustL1967rI1jZVt1xysTO+xJGMoZzcy3cWC9+b6Tw==",
             "dev": true,
             "requires": {
                 "source-map": "^0.6.1"
@@ -2310,14 +2108,6 @@
                 "@types/connect": "*",
                 "tapable": "^2.2.0",
                 "webpack": "^5"
-            },
-            "dependencies": {
-                "tapable": {
-                    "version": "2.2.1",
-                    "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
-                    "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
-                    "dev": true
-                }
             }
         },
         "@types/webpack-sources": {
@@ -2332,9 +2122,9 @@
             },
             "dependencies": {
                 "source-map": {
-                    "version": "0.7.3",
-                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
-                    "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+                    "version": "0.7.4",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
+                    "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
                     "dev": true
                 }
             }
@@ -2345,6 +2135,23 @@
             "integrity": "sha512-e1DZGD+eH19BnllTWCGXAdrMa2kI53wEMuhn/d+wUmnu8//ZI6BiuK/EPdw07fI4+tlyo5qdPZdXdpkoXHJVOw==",
             "requires": {
                 "@types/react": "*"
+            },
+            "dependencies": {
+                "@types/react": {
+                    "version": "18.0.12",
+                    "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.12.tgz",
+                    "integrity": "sha512-duF1OTASSBQtcigUvhuiTB1Ya3OvSy+xORCiEf20H0P0lzx+/KeVsA99U5UjLXSbyo1DRJDlLKqTeM1ngosqtg==",
+                    "requires": {
+                        "@types/prop-types": "*",
+                        "@types/scheduler": "*",
+                        "csstype": "^3.0.2"
+                    }
+                },
+                "csstype": {
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
+                }
             }
         },
         "@types/xregexp": {
@@ -2357,12 +2164,20 @@
             }
         },
         "@types/yauzl": {
-            "version": "2.9.1",
-            "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz",
-            "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==",
+            "version": "2.10.0",
+            "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz",
+            "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==",
             "optional": true,
             "requires": {
                 "@types/node": "*"
+            },
+            "dependencies": {
+                "@types/node": {
+                    "version": "17.0.40",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.40.tgz",
+                    "integrity": "sha512-UXdBxNGqTMtm7hCwh9HtncFVLrXoqA3oJW30j6XWp5BH/wu3mVeaxo7cq5benFdBw34HB3XDT2TRPI7rXZ+mDg==",
+                    "optional": true
+                }
             }
         },
         "@types/youtube": {
@@ -2566,7 +2381,7 @@
         "Base64": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz",
-            "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg="
+            "integrity": "sha512-reGEWshDmTDQDsCec/HduOO9Wyj6yMOupMfhIf3ugN1TDlK2NQW4DDJSqNNtp380SNcvRfXtO8HSCQot0d0SMw=="
         },
         "D": {
             "version": "1.0.0",
@@ -2574,9 +2389,9 @@
             "integrity": "sha512-nQvrCBu7K2pSSEtIM0EEF03FVjcczCXInMt3moLNFbjlWx6bZrX72uT6/1uAXDbnzGUAx9gTyDiQ+vrFi663oA=="
         },
         "abab": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz",
-            "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==",
+            "version": "2.0.6",
+            "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
+            "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
             "dev": true
         },
         "abbrev": {
@@ -2599,32 +2414,17 @@
             "requires": {
                 "mime-types": "~2.1.34",
                 "negotiator": "0.6.3"
-            },
-            "dependencies": {
-                "mime-db": {
-                    "version": "1.51.0",
-                    "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
-                    "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
-                },
-                "mime-types": {
-                    "version": "2.1.34",
-                    "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
-                    "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
-                    "requires": {
-                        "mime-db": "1.51.0"
-                    }
-                }
             }
         },
         "acorn": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
-            "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo="
+            "version": "8.7.1",
+            "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
+            "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A=="
         },
         "acorn-globals": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz",
-            "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=",
+            "integrity": "sha512-uWttZCk96+7itPxK8xCzY86PnxKTMrReKDqrHzv42VQY0K30PUO8WY13WMOuI+cOdX4EIdzdvQ8k6jkuGRFMYw==",
             "requires": {
                 "acorn": "^4.0.4"
             },
@@ -2632,7 +2432,7 @@
                 "acorn": {
                     "version": "4.0.13",
                     "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
-                    "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c="
+                    "integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug=="
                 }
             }
         },
@@ -2661,30 +2461,35 @@
         "after": {
             "version": "0.8.2",
             "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
-            "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8="
+            "integrity": "sha512-QbJ0NTQ/I9DI3uSJA4cbexiwQeRAfjPScqIbSjUDd9TOrcg6pTkdgziesOqxBMBzit8vFCTwrP27t13vFOORRA=="
         },
         "agent-base": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz",
-            "integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==",
+            "version": "6.0.2",
+            "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+            "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
             "requires": {
                 "debug": "4"
             },
             "dependencies": {
                 "debug": {
-                    "version": "4.1.1",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+                    "version": "4.3.4",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+                    "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
                     "requires": {
-                        "ms": "^2.1.1"
+                        "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=="
                 }
             }
         },
         "ajv": {
-            "version": "6.12.2",
-            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
-            "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+            "version": "6.12.6",
+            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+            "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
             "requires": {
                 "fast-deep-equal": "^3.1.1",
                 "fast-json-stable-stringify": "^2.0.0",
@@ -2706,9 +2511,9 @@
             },
             "dependencies": {
                 "ajv": {
-                    "version": "8.10.0",
-                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz",
-                    "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==",
+                    "version": "8.11.0",
+                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
+                    "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
                     "requires": {
                         "fast-deep-equal": "^3.1.1",
                         "json-schema-traverse": "^1.0.0",
@@ -2724,14 +2529,14 @@
             }
         },
         "ajv-keywords": {
-            "version": "3.4.1",
-            "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
-            "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ=="
+            "version": "3.5.2",
+            "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+            "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ=="
         },
         "align-text": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
-            "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
+            "integrity": "sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==",
             "requires": {
                 "kind-of": "^3.0.2",
                 "longest": "^1.0.1",
@@ -2746,7 +2551,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -2756,12 +2561,12 @@
         "amdefine": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
-            "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
+            "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg=="
         },
         "ansi-align": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz",
-            "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=",
+            "integrity": "sha512-TdlOggdA/zURfMYa7ABC66j+oqfMew58KpJMbUlH3bcZP1b+cBHIHDDn5uH9INsxrHBPjsqM0tDB4jPTF/vgJA==",
             "requires": {
                 "string-width": "^2.0.0"
             }
@@ -2793,9 +2598,9 @@
             "dev": true
         },
         "ansi-regex": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
-            "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz",
+            "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw=="
         },
         "ansi-styles": {
             "version": "3.2.1",
@@ -2808,7 +2613,7 @@
         "any-promise": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
-            "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
+            "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
         },
         "anymatch": {
             "version": "2.0.0",
@@ -2822,7 +2627,7 @@
                 "normalize-path": {
                     "version": "2.1.1",
                     "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
-                    "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+                    "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==",
                     "requires": {
                         "remove-trailing-separator": "^1.0.1"
                     }
@@ -2830,9 +2635,9 @@
             }
         },
         "aproba": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
-            "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+            "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ=="
         },
         "archiver": {
             "version": "3.1.1",
@@ -2882,28 +2687,12 @@
             }
         },
         "are-we-there-yet": {
-            "version": "1.1.5",
-            "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
-            "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
+            "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
             "requires": {
                 "delegates": "^1.0.0",
-                "readable-stream": "^2.0.6"
-            },
-            "dependencies": {
-                "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"
-                    }
-                }
+                "readable-stream": "^3.6.0"
             }
         },
         "arg": {
@@ -2923,7 +2712,7 @@
         "arr-diff": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
-            "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
+            "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA=="
         },
         "arr-flatten": {
             "version": "1.1.0",
@@ -2933,7 +2722,7 @@
         "arr-union": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
-            "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="
+            "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q=="
         },
         "array-back": {
             "version": "2.0.0",
@@ -2956,9 +2745,9 @@
             },
             "dependencies": {
                 "@types/node": {
-                    "version": "12.12.37",
-                    "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.37.tgz",
-                    "integrity": "sha512-4mXKoDptrXAwZErQHrLzpe0FN/0Wmf5JRniSVIdwUrtDf9wnmEV1teCNLBo/TwuXhkK/bVegoEn/wmb+x0AuPg=="
+                    "version": "12.20.54",
+                    "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.54.tgz",
+                    "integrity": "sha512-CFMnEPkSXWALI73t1oIWyb8QOmVrp6RruAqIx349sd+1ImaFwzlKcz55mwrx/yLyOyz1gkq/UKuNOigt27PXqg=="
                 },
                 "glob": {
                     "version": "7.1.3",
@@ -2973,6 +2762,14 @@
                         "path-is-absolute": "^1.0.0"
                     }
                 },
+                "minimatch": {
+                    "version": "3.0.4",
+                    "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+                    "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+                    "requires": {
+                        "brace-expansion": "^1.1.7"
+                    }
+                },
                 "mocha": {
                     "version": "6.2.3",
                     "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz",
@@ -3016,23 +2813,23 @@
         "array-equal": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
-            "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
+            "integrity": "sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA==",
             "dev": true
         },
         "array-find-index": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
-            "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E="
+            "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw=="
         },
         "array-flatten": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
-            "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+            "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
         },
         "array-union": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
-            "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+            "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==",
             "dev": true,
             "requires": {
                 "array-uniq": "^1.0.1"
@@ -3041,13 +2838,25 @@
         "array-uniq": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
-            "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+            "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==",
             "dev": true
         },
         "array-unique": {
             "version": "0.3.2",
             "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
-            "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
+            "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ=="
+        },
+        "array.prototype.reduce": {
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.4.tgz",
+            "integrity": "sha512-WnM+AjG/DvLRLo4DDl+r+SvCzYtD2Jd9oeBYMcEaI7t3fFrHY9M53/wdLcTvmZNQ70IU6Htj0emFkZ5TS+lrdw==",
+            "requires": {
+                "call-bind": "^1.0.2",
+                "define-properties": "^1.1.3",
+                "es-abstract": "^1.19.2",
+                "es-array-method-boxes-properly": "^1.0.0",
+                "is-string": "^1.0.7"
+            }
         },
         "arraybuffer.slice": {
             "version": "0.0.7",
@@ -3062,7 +2871,7 @@
         "asap": {
             "version": "2.0.6",
             "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
-            "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
+            "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="
         },
         "asn1": {
             "version": "0.2.6",
@@ -3075,7 +2884,7 @@
         "assert-plus": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
-            "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+            "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw=="
         },
         "assertion-error": {
             "version": "1.1.0",
@@ -3085,12 +2894,12 @@
         "assign-symbols": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
-            "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
+            "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw=="
         },
         "async": {
-            "version": "2.6.3",
-            "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
-            "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+            "version": "2.6.4",
+            "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
+            "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
             "requires": {
                 "lodash": "^4.17.14"
             }
@@ -3103,7 +2912,7 @@
         "async-foreach": {
             "version": "0.1.3",
             "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
-            "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI="
+            "integrity": "sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA=="
         },
         "async-limiter": {
             "version": "1.0.1",
@@ -3114,7 +2923,7 @@
         "asynckit": {
             "version": "0.4.0",
             "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-            "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+            "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
         },
         "atob": {
             "version": "2.1.2",
@@ -3140,12 +2949,31 @@
                 "mkdirp": "^0.5.1",
                 "source-map-support": "^0.5.3",
                 "webpack-log": "^1.2.0"
+            },
+            "dependencies": {
+                "enhanced-resolve": {
+                    "version": "4.5.0",
+                    "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz",
+                    "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==",
+                    "dev": true,
+                    "requires": {
+                        "graceful-fs": "^4.1.2",
+                        "memory-fs": "^0.5.0",
+                        "tapable": "^1.0.0"
+                    }
+                },
+                "tapable": {
+                    "version": "1.1.3",
+                    "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+                    "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
+                    "dev": true
+                }
             }
         },
         "aws-sign2": {
             "version": "0.7.0",
             "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
-            "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
+            "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA=="
         },
         "aws4": {
             "version": "1.11.0",
@@ -3158,63 +2986,40 @@
             "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
             "requires": {
                 "follow-redirects": "1.5.10"
-            },
-            "dependencies": {
-                "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"
-                    }
-                },
-                "follow-redirects": {
-                    "version": "1.5.10",
-                    "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
-                    "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
-                    "requires": {
-                        "debug": "=3.1.0"
-                    }
-                },
-                "ms": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
-                }
-            }
-        },
-        "babel": {
-            "version": "6.23.0",
-            "resolved": "https://registry.npmjs.org/babel/-/babel-6.23.0.tgz",
-            "integrity": "sha1-0NHn2APpdHZb7qMjLU4VPA77kPQ="
-        },
-        "babel-code-frame": {
-            "version": "6.26.0",
-            "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
-            "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
-            "dev": true,
-            "requires": {
-                "chalk": "^1.1.3",
-                "esutils": "^2.0.2",
-                "js-tokens": "^3.0.2"
+            }
+        },
+        "babel": {
+            "version": "6.23.0",
+            "resolved": "https://registry.npmjs.org/babel/-/babel-6.23.0.tgz",
+            "integrity": "sha512-ZDcCaI8Vlct8PJ3DvmyqUz+5X2Ylz3ZuuItBe/74yXosk2dwyVo/aN7MCJ8HJzhnnJ+6yP4o+lDgG9MBe91DLA=="
+        },
+        "babel-code-frame": {
+            "version": "6.26.0",
+            "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+            "integrity": "sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==",
+            "dev": true,
+            "requires": {
+                "chalk": "^1.1.3",
+                "esutils": "^2.0.2",
+                "js-tokens": "^3.0.2"
             },
             "dependencies": {
                 "ansi-regex": {
                     "version": "2.1.1",
                     "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+                    "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": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+                    "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==",
                     "dev": true
                 },
                 "chalk": {
                     "version": "1.1.3",
                     "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-                    "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+                    "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
                     "dev": true,
                     "requires": {
                         "ansi-styles": "^2.2.1",
@@ -3227,7 +3032,7 @@
                 "js-tokens": {
                     "version": "3.0.2",
                     "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
-                    "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+                    "integrity": "sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==",
                     "dev": true
                 },
                 "strip-ansi": {
@@ -3275,25 +3080,26 @@
             }
         },
         "babel-plugin-styled-components": {
-            "version": "1.10.7",
-            "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.10.7.tgz",
-            "integrity": "sha512-MBMHGcIA22996n9hZRf/UJLVVgkEOITuR2SvjHLb5dSTUyR4ZRGn+ngITapes36FI3WLxZHfRhkA1ffHxihOrg==",
+            "version": "2.0.7",
+            "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz",
+            "integrity": "sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==",
             "requires": {
-                "@babel/helper-annotate-as-pure": "^7.0.0",
-                "@babel/helper-module-imports": "^7.0.0",
+                "@babel/helper-annotate-as-pure": "^7.16.0",
+                "@babel/helper-module-imports": "^7.16.0",
                 "babel-plugin-syntax-jsx": "^6.18.0",
-                "lodash": "^4.17.11"
+                "lodash": "^4.17.11",
+                "picomatch": "^2.3.0"
             }
         },
         "babel-plugin-syntax-jsx": {
             "version": "6.18.0",
             "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
-            "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
+            "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw=="
         },
         "babel-runtime": {
             "version": "6.26.0",
             "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
-            "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+            "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
             "requires": {
                 "core-js": "^2.4.0",
                 "regenerator-runtime": "^0.11.0"
@@ -3314,7 +3120,7 @@
         "babel-types": {
             "version": "6.26.0",
             "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
-            "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+            "integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==",
             "requires": {
                 "babel-runtime": "^6.26.0",
                 "esutils": "^2.0.2",
@@ -3337,12 +3143,12 @@
         "backo2": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
-            "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
+            "integrity": "sha512-zj6Z6M7Eq+PBZ7PQxl5NT665MvJdAkzp0f60nAJ+sLaSCBPMwVak5ZegFbgVCzFcCJTKFoMizvM5Ld7+JrRJHA=="
         },
         "balanced-match": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
-            "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+            "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
         },
         "base": {
             "version": "0.11.2",
@@ -3361,7 +3167,7 @@
                 "define-property": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-                    "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+                    "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
                     "requires": {
                         "is-descriptor": "^1.0.0"
                     }
@@ -3397,17 +3203,17 @@
         "base16": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz",
-            "integrity": "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA="
+            "integrity": "sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ=="
         },
         "base64-arraybuffer": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz",
-            "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI="
+            "integrity": "sha512-a1eIFi4R9ySrbiMuyTGx5e92uRH5tQY6kArNcFaKBUleIoLjdjBg7Zxm3Mqm3Kmkf27HLR/1fnxX9q8GQ7Iavg=="
         },
         "base64-js": {
-            "version": "1.3.1",
-            "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
-            "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
+            "version": "1.5.1",
+            "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+            "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
         },
         "base64id": {
             "version": "2.0.0",
@@ -3422,18 +3228,18 @@
         "batch": {
             "version": "0.6.1",
             "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
-            "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
+            "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
             "dev": true
         },
         "bcrypt-nodejs": {
             "version": "0.0.3",
             "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz",
-            "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs="
+            "integrity": "sha512-NmTbLm867btBHCBZ222FQXkQKzecB0KG6pTXFa6NeTVZaSnLfCsx7EK2PL3J+kX8xJThUquEBbhimRCKKZX9zA=="
         },
         "bcrypt-pbkdf": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
-            "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+            "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
             "requires": {
                 "tweetnacl": "^0.14.3"
             }
@@ -3441,7 +3247,7 @@
         "bezier-curve": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/bezier-curve/-/bezier-curve-1.0.0.tgz",
-            "integrity": "sha1-o9+v6rEqlMRicw1QeYxSqEBdc3k="
+            "integrity": "sha512-h6uZJ6qdFfswS1rIRericgouhTeiVi/MnH10OKtCu2IZzXa+ZcjaxRLHY4u/evRsJcxYbbiNkgWQj2Z4UIcpEQ=="
         },
         "bezier-js": {
             "version": "4.1.1",
@@ -3454,19 +3260,28 @@
             "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="
         },
         "bignumber.js": {
-            "version": "7.2.1",
-            "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz",
-            "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ=="
+            "version": "9.0.2",
+            "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz",
+            "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw=="
         },
         "binary-extensions": {
             "version": "1.13.1",
             "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
             "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw=="
         },
+        "bindings": {
+            "version": "1.5.0",
+            "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+            "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+            "optional": true,
+            "requires": {
+                "file-uri-to-path": "1.0.0"
+            }
+        },
         "bl": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.2.tgz",
-            "integrity": "sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ==",
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+            "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
             "requires": {
                 "buffer": "^5.5.0",
                 "inherits": "^2.0.4",
@@ -3481,7 +3296,7 @@
         "block-stream": {
             "version": "0.0.9",
             "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
-            "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
+            "integrity": "sha512-OorbnJVPII4DuUKbjARAe8u8EfqOmkEEaSFIyoQ7OjTHn6kafxWl0wLgoZ2rXaYd7MyLcDaU4TmhfxtwgcccMQ==",
             "requires": {
                 "inherits": "~2.0.0"
             }
@@ -3497,20 +3312,22 @@
             "integrity": "sha512-6sTGh1OiUmuH8ftAYvUzALivoOmcnahinGmjZFI4puZVowXoKTn/bXtth7N1skW5AlezEOfjgFH4lNXHeNRQog=="
         },
         "body-parser": {
-            "version": "1.19.2",
-            "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz",
-            "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==",
+            "version": "1.20.0",
+            "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
+            "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==",
             "requires": {
                 "bytes": "3.1.2",
                 "content-type": "~1.0.4",
                 "debug": "2.6.9",
-                "depd": "~1.1.2",
-                "http-errors": "1.8.1",
+                "depd": "2.0.0",
+                "destroy": "1.2.0",
+                "http-errors": "2.0.0",
                 "iconv-lite": "0.4.24",
-                "on-finished": "~2.3.0",
-                "qs": "6.9.7",
-                "raw-body": "2.4.3",
-                "type-is": "~1.6.18"
+                "on-finished": "2.4.1",
+                "qs": "6.10.3",
+                "raw-body": "2.5.1",
+                "type-is": "~1.6.18",
+                "unpipe": "1.0.0"
             },
             "dependencies": {
                 "debug": {
@@ -3521,22 +3338,33 @@
                         "ms": "2.0.0"
                     }
                 },
+                "iconv-lite": {
+                    "version": "0.4.24",
+                    "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+                    "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+                    "requires": {
+                        "safer-buffer": ">= 2.1.2 < 3"
+                    }
+                },
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                 },
                 "qs": {
-                    "version": "6.9.7",
-                    "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz",
-                    "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw=="
+                    "version": "6.10.3",
+                    "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
+                    "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
+                    "requires": {
+                        "side-channel": "^1.0.4"
+                    }
                 }
             }
         },
         "bonjour": {
             "version": "3.5.0",
             "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
-            "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
+            "integrity": "sha512-RaVTblr+OnEli0r/ud8InrU7D+G0y6aJhlxaLa6Pwty4+xoxboF1BsUI45tujvRpbj9dQVoglChqonGAsjEBYg==",
             "dev": true,
             "requires": {
                 "array-flatten": "^2.1.0",
@@ -3558,7 +3386,7 @@
         "boolbase": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
-            "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
+            "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
         },
         "bootstrap": {
             "version": "4.6.1",
@@ -3587,7 +3415,7 @@
                 "camelcase": {
                     "version": "4.1.0",
                     "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-                    "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
+                    "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw=="
                 }
             }
         },
@@ -3620,22 +3448,17 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
-                },
-                "is-extendable": {
-                    "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-                    "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
                 }
             }
         },
         "browser-assert": {
             "version": "1.2.1",
             "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz",
-            "integrity": "sha1-mqpaKox0aFwq4Fv+Ru/WBvBowgA="
+            "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ=="
         },
         "browser-process-hrtime": {
             "version": "1.0.0",
@@ -3649,48 +3472,48 @@
             "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="
         },
         "browserslist": {
-            "version": "4.19.3",
-            "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz",
-            "integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==",
+            "version": "4.20.3",
+            "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz",
+            "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==",
             "requires": {
-                "caniuse-lite": "^1.0.30001312",
-                "electron-to-chromium": "^1.4.71",
+                "caniuse-lite": "^1.0.30001332",
+                "electron-to-chromium": "^1.4.118",
                 "escalade": "^3.1.1",
-                "node-releases": "^2.0.2",
+                "node-releases": "^2.0.3",
                 "picocolors": "^1.0.0"
             }
         },
         "bson": {
-            "version": "4.6.1",
-            "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.1.tgz",
-            "integrity": "sha512-I1LQ7Hz5zgwR4QquilLNZwbhPw0Apx7i7X9kGMBTsqPdml/03Q9NBtD9nt/19ahjlphktQImrnderxqpzeVDjw==",
+            "version": "4.6.4",
+            "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.4.tgz",
+            "integrity": "sha512-TdQ3FzguAu5HKPPlr0kYQCyrYUYh8tFM+CMTpxjNzVzxeiJY00Rtuj3LXLHSgiGvmaWlZ8PE+4KyM2thqE38pQ==",
             "requires": {
                 "buffer": "^5.6.0"
             }
         },
         "buffer": {
-            "version": "5.6.0",
-            "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz",
-            "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==",
+            "version": "5.7.1",
+            "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+            "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
             "requires": {
-                "base64-js": "^1.0.2",
-                "ieee754": "^1.1.4"
+                "base64-js": "^1.3.1",
+                "ieee754": "^1.1.13"
             }
         },
         "buffer-crc32": {
             "version": "0.2.13",
             "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
-            "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
+            "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="
         },
         "buffer-equal-constant-time": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
-            "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
+            "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
         },
         "buffer-from": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
-            "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
+            "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-indexof": {
             "version": "1.1.1",
@@ -3701,21 +3524,20 @@
         "buffer-shims": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
-            "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E="
+            "integrity": "sha512-Zy8ZXMyxIT6RMTeY7OP/bDndfj6bwCan7SS98CEndS6deHwWPpseeHlwarNcBim+etXnF9HBc1non5JgDaJU1g=="
         },
         "built-in-math-eval": {
             "version": "0.3.0",
             "resolved": "https://registry.npmjs.org/built-in-math-eval/-/built-in-math-eval-0.3.0.tgz",
-            "integrity": "sha1-JA3CHLOJQ5WIxhxGDrAHZJfvxBw=",
+            "integrity": "sha512-5XD5cujru60ooKJ4sGZqoH5v2Xvgw7ezV54gJX/OnPkgDKoH3BnlMEi8xW6hl8xaEjxKHebgrsawroeZnGwIMA==",
             "requires": {
                 "math-codegen": "^0.3.5"
             }
         },
         "builtin-modules": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
-            "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
-            "dev": true
+            "version": "3.3.0",
+            "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
+            "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw=="
         },
         "bytes": {
             "version": "3.1.2",
@@ -3743,6 +3565,12 @@
                 "y18n": "^4.0.0"
             },
             "dependencies": {
+                "chownr": {
+                    "version": "1.1.4",
+                    "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+                    "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+                    "dev": true
+                },
                 "lru-cache": {
                     "version": "4.1.5",
                     "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
@@ -3832,7 +3660,7 @@
         "caller-callsite": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
-            "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+            "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==",
             "requires": {
                 "callsites": "^2.0.0"
             },
@@ -3840,14 +3668,14 @@
                 "callsites": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
-                    "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA="
+                    "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ=="
                 }
             }
         },
         "caller-path": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
-            "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+            "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==",
             "requires": {
                 "caller-callsite": "^2.0.0"
             }
@@ -3864,723 +3692,148 @@
             "requires": {
                 "pascal-case": "^3.1.2",
                 "tslib": "^2.0.3"
-            },
-            "dependencies": {
-                "tslib": {
-                    "version": "2.3.1",
-                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
-                    "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
-                }
             }
         },
-        "camelcase": {
-            "version": "5.3.1",
-            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
-            "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
-        },
-        "camelcase-keys": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
-            "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
-            "requires": {
-                "camelcase": "^2.0.0",
-                "map-obj": "^1.0.0"
-            },
-            "dependencies": {
-                "camelcase": {
-                    "version": "2.1.1",
-                    "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
-                    "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
-                }
-            }
-        },
-        "camelize": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
-            "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
-        },
-        "caniuse-lite": {
-            "version": "1.0.30001312",
-            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz",
-            "integrity": "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ=="
-        },
-        "canvas": {
-            "version": "2.9.0",
-            "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.9.0.tgz",
-            "integrity": "sha512-0l93g7uxp7rMyr7H+XRQ28A3ud0dKIUTIEkUe1Dxh4rjUYN7B93+SjC3r1PDKA18xcQN87OFGgUnyw7LSgNLSQ==",
-            "requires": {
-                "@mapbox/node-pre-gyp": "^1.0.0",
-                "nan": "^2.15.0",
-                "simple-get": "^3.0.3"
-            },
-            "dependencies": {
-                "nan": {
-                    "version": "2.15.0",
-                    "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
-                    "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
-                }
-            }
-        },
-        "capture-stack-trace": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz",
-            "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw=="
-        },
-        "caseless": {
-            "version": "0.12.0",
-            "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
-            "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
-        },
-        "center-align": {
-            "version": "0.1.3",
-            "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
-            "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
-            "requires": {
-                "align-text": "^0.1.3",
-                "lazy-cache": "^1.0.3"
-            }
-        },
-        "chai": {
-            "version": "4.3.6",
-            "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
-            "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
-            "requires": {
-                "assertion-error": "^1.1.0",
-                "check-error": "^1.0.2",
-                "deep-eql": "^3.0.1",
-                "get-func-name": "^2.0.0",
-                "loupe": "^2.3.1",
-                "pathval": "^1.1.1",
-                "type-detect": "^4.0.5"
-            }
-        },
-        "chain-function": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/chain-function/-/chain-function-1.0.1.tgz",
-            "integrity": "sha512-SxltgMwL9uCko5/ZCLiyG2B7R9fY4pDZUw7hJ4MhirdjBLosoDqkWABi3XMucddHdLiFJMb7PD2MZifZriuMTg=="
-        },
-        "chalk": {
-            "version": "2.4.2",
-            "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-            "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-            "requires": {
-                "ansi-styles": "^3.2.1",
-                "escape-string-regexp": "^1.0.5",
-                "supports-color": "^5.3.0"
-            }
-        },
-        "change-emitter": {
-            "version": "0.1.6",
-            "resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz",
-            "integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU="
-        },
-        "character-parser": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz",
-            "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=",
-            "requires": {
-                "is-regex": "^1.0.3"
-            }
-        },
-        "check-error": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
-            "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
-        },
-        "child_process": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz",
-            "integrity": "sha1-sffn/HPSXn/R1FWtyU4UODAYK1o="
-        },
-        "chokidar": {
-            "version": "2.1.8",
-            "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
-            "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
-            "requires": {
-                "anymatch": "^2.0.0",
-                "async-each": "^1.0.1",
-                "braces": "^2.3.2",
-                "fsevents": "^1.2.7",
-                "glob-parent": "^3.1.0",
-                "inherits": "^2.0.3",
-                "is-binary-path": "^1.0.0",
-                "is-glob": "^4.0.0",
-                "normalize-path": "^3.0.0",
-                "path-is-absolute": "^1.0.0",
-                "readdirp": "^2.2.1",
-                "upath": "^1.1.1"
-            },
-            "dependencies": {
-                "bindings": {
-                    "version": "1.5.0",
-                    "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
-                    "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
-                    "optional": true,
-                    "requires": {
-                        "file-uri-to-path": "1.0.0"
-                    }
-                },
-                "fsevents": {
-                    "version": "1.2.12",
-                    "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.12.tgz",
-                    "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==",
-                    "optional": true,
-                    "requires": {
-                        "bindings": "^1.5.0",
-                        "nan": "^2.12.1",
-                        "node-pre-gyp": "*"
-                    },
-                    "dependencies": {
-                        "abbrev": {
-                            "version": "1.1.1",
-                            "resolved": false,
-                            "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
-                            "optional": true
-                        },
-                        "ansi-regex": {
-                            "version": "2.1.1",
-                            "resolved": false,
-                            "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
-                            "optional": true
-                        },
-                        "aproba": {
-                            "version": "1.2.0",
-                            "resolved": false,
-                            "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
-                            "optional": true
-                        },
-                        "are-we-there-yet": {
-                            "version": "1.1.5",
-                            "resolved": false,
-                            "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
-                            "optional": true,
-                            "requires": {
-                                "delegates": "^1.0.0",
-                                "readable-stream": "^2.0.6"
-                            }
-                        },
-                        "balanced-match": {
-                            "version": "1.0.0",
-                            "resolved": false,
-                            "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
-                            "optional": true
-                        },
-                        "brace-expansion": {
-                            "version": "1.1.11",
-                            "resolved": false,
-                            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-                            "optional": true,
-                            "requires": {
-                                "balanced-match": "^1.0.0",
-                                "concat-map": "0.0.1"
-                            }
-                        },
-                        "chownr": {
-                            "version": "1.1.4",
-                            "resolved": false,
-                            "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
-                            "optional": true
-                        },
-                        "code-point-at": {
-                            "version": "1.1.0",
-                            "resolved": false,
-                            "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
-                            "optional": true
-                        },
-                        "concat-map": {
-                            "version": "0.0.1",
-                            "resolved": false,
-                            "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
-                            "optional": true
-                        },
-                        "console-control-strings": {
-                            "version": "1.1.0",
-                            "resolved": false,
-                            "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
-                            "optional": true
-                        },
-                        "core-util-is": {
-                            "version": "1.0.2",
-                            "resolved": false,
-                            "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
-                            "optional": true
-                        },
-                        "debug": {
-                            "version": "3.2.6",
-                            "resolved": false,
-                            "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
-                            "optional": true,
-                            "requires": {
-                                "ms": "^2.1.1"
-                            }
-                        },
-                        "deep-extend": {
-                            "version": "0.6.0",
-                            "resolved": false,
-                            "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
-                            "optional": true
-                        },
-                        "delegates": {
-                            "version": "1.0.0",
-                            "resolved": false,
-                            "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
-                            "optional": true
-                        },
-                        "detect-libc": {
-                            "version": "1.0.3",
-                            "resolved": false,
-                            "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
-                            "optional": true
-                        },
-                        "fs-minipass": {
-                            "version": "1.2.7",
-                            "resolved": false,
-                            "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
-                            "optional": true,
-                            "requires": {
-                                "minipass": "^2.6.0"
-                            }
-                        },
-                        "fs.realpath": {
-                            "version": "1.0.0",
-                            "resolved": false,
-                            "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
-                            "optional": true
-                        },
-                        "gauge": {
-                            "version": "2.7.4",
-                            "resolved": false,
-                            "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
-                            "optional": true,
-                            "requires": {
-                                "aproba": "^1.0.3",
-                                "console-control-strings": "^1.0.0",
-                                "has-unicode": "^2.0.0",
-                                "object-assign": "^4.1.0",
-                                "signal-exit": "^3.0.0",
-                                "string-width": "^1.0.1",
-                                "strip-ansi": "^3.0.1",
-                                "wide-align": "^1.1.0"
-                            }
-                        },
-                        "glob": {
-                            "version": "7.1.6",
-                            "resolved": false,
-                            "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
-                            "optional": true,
-                            "requires": {
-                                "fs.realpath": "^1.0.0",
-                                "inflight": "^1.0.4",
-                                "inherits": "2",
-                                "minimatch": "^3.0.4",
-                                "once": "^1.3.0",
-                                "path-is-absolute": "^1.0.0"
-                            }
-                        },
-                        "has-unicode": {
-                            "version": "2.0.1",
-                            "resolved": false,
-                            "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
-                            "optional": true
-                        },
-                        "iconv-lite": {
-                            "version": "0.4.24",
-                            "resolved": false,
-                            "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
-                            "optional": true,
-                            "requires": {
-                                "safer-buffer": ">= 2.1.2 < 3"
-                            }
-                        },
-                        "ignore-walk": {
-                            "version": "3.0.3",
-                            "resolved": false,
-                            "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
-                            "optional": true,
-                            "requires": {
-                                "minimatch": "^3.0.4"
-                            }
-                        },
-                        "inflight": {
-                            "version": "1.0.6",
-                            "resolved": false,
-                            "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
-                            "optional": true,
-                            "requires": {
-                                "once": "^1.3.0",
-                                "wrappy": "1"
-                            }
-                        },
-                        "inherits": {
-                            "version": "2.0.4",
-                            "resolved": false,
-                            "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-                            "optional": true
-                        },
-                        "ini": {
-                            "version": "1.3.5",
-                            "resolved": false,
-                            "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
-                            "optional": true
-                        },
-                        "is-fullwidth-code-point": {
-                            "version": "1.0.0",
-                            "resolved": false,
-                            "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
-                            "optional": true,
-                            "requires": {
-                                "number-is-nan": "^1.0.0"
-                            }
-                        },
-                        "isarray": {
-                            "version": "1.0.0",
-                            "resolved": false,
-                            "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
-                            "optional": true
-                        },
-                        "minimatch": {
-                            "version": "3.0.4",
-                            "resolved": false,
-                            "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
-                            "optional": true,
-                            "requires": {
-                                "brace-expansion": "^1.1.7"
-                            }
-                        },
-                        "minimist": {
-                            "version": "1.2.5",
-                            "resolved": false,
-                            "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
-                            "optional": true
-                        },
-                        "minipass": {
-                            "version": "2.9.0",
-                            "resolved": false,
-                            "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
-                            "optional": true,
-                            "requires": {
-                                "safe-buffer": "^5.1.2",
-                                "yallist": "^3.0.0"
-                            }
-                        },
-                        "minizlib": {
-                            "version": "1.3.3",
-                            "resolved": false,
-                            "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
-                            "optional": true,
-                            "requires": {
-                                "minipass": "^2.9.0"
-                            }
-                        },
-                        "mkdirp": {
-                            "version": "0.5.3",
-                            "resolved": false,
-                            "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==",
-                            "optional": true,
-                            "requires": {
-                                "minimist": "^1.2.5"
-                            }
-                        },
-                        "ms": {
-                            "version": "2.1.2",
-                            "resolved": false,
-                            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-                            "optional": true
-                        },
-                        "needle": {
-                            "version": "2.3.3",
-                            "resolved": false,
-                            "integrity": "sha512-EkY0GeSq87rWp1hoq/sH/wnTWgFVhYlnIkbJ0YJFfRgEFlz2RraCjBpFQ+vrEgEdp0ThfyHADmkChEhcb7PKyw==",
-                            "optional": true,
-                            "requires": {
-                                "debug": "^3.2.6",
-                                "iconv-lite": "^0.4.4",
-                                "sax": "^1.2.4"
-                            }
-                        },
-                        "node-pre-gyp": {
-                            "version": "0.14.0",
-                            "resolved": false,
-                            "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==",
-                            "optional": true,
-                            "requires": {
-                                "detect-libc": "^1.0.2",
-                                "mkdirp": "^0.5.1",
-                                "needle": "^2.2.1",
-                                "nopt": "^4.0.1",
-                                "npm-packlist": "^1.1.6",
-                                "npmlog": "^4.0.2",
-                                "rc": "^1.2.7",
-                                "rimraf": "^2.6.1",
-                                "semver": "^5.3.0",
-                                "tar": "^4.4.2"
-                            }
-                        },
-                        "nopt": {
-                            "version": "4.0.3",
-                            "resolved": false,
-                            "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
-                            "optional": true,
-                            "requires": {
-                                "abbrev": "1",
-                                "osenv": "^0.1.4"
-                            }
-                        },
-                        "npm-bundled": {
-                            "version": "1.1.1",
-                            "resolved": false,
-                            "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
-                            "optional": true,
-                            "requires": {
-                                "npm-normalize-package-bin": "^1.0.1"
-                            }
-                        },
-                        "npm-normalize-package-bin": {
-                            "version": "1.0.1",
-                            "resolved": false,
-                            "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==",
-                            "optional": true
-                        },
-                        "npm-packlist": {
-                            "version": "1.4.8",
-                            "resolved": false,
-                            "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
-                            "optional": true,
-                            "requires": {
-                                "ignore-walk": "^3.0.1",
-                                "npm-bundled": "^1.0.1",
-                                "npm-normalize-package-bin": "^1.0.1"
-                            }
-                        },
-                        "npmlog": {
-                            "version": "4.1.2",
-                            "resolved": false,
-                            "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
-                            "optional": true,
-                            "requires": {
-                                "are-we-there-yet": "~1.1.2",
-                                "console-control-strings": "~1.1.0",
-                                "gauge": "~2.7.3",
-                                "set-blocking": "~2.0.0"
-                            }
-                        },
-                        "number-is-nan": {
-                            "version": "1.0.1",
-                            "resolved": false,
-                            "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
-                            "optional": true
-                        },
-                        "object-assign": {
-                            "version": "4.1.1",
-                            "resolved": false,
-                            "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
-                            "optional": true
-                        },
-                        "once": {
-                            "version": "1.4.0",
-                            "resolved": false,
-                            "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
-                            "optional": true,
-                            "requires": {
-                                "wrappy": "1"
-                            }
-                        },
-                        "os-homedir": {
-                            "version": "1.0.2",
-                            "resolved": false,
-                            "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
-                            "optional": true
-                        },
-                        "os-tmpdir": {
-                            "version": "1.0.2",
-                            "resolved": false,
-                            "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
-                            "optional": true
-                        },
-                        "osenv": {
-                            "version": "0.1.5",
-                            "resolved": false,
-                            "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
-                            "optional": true,
-                            "requires": {
-                                "os-homedir": "^1.0.0",
-                                "os-tmpdir": "^1.0.0"
-                            }
-                        },
-                        "path-is-absolute": {
-                            "version": "1.0.1",
-                            "resolved": false,
-                            "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
-                            "optional": true
-                        },
-                        "process-nextick-args": {
-                            "version": "2.0.1",
-                            "resolved": false,
-                            "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
-                            "optional": true
-                        },
-                        "rc": {
-                            "version": "1.2.8",
-                            "resolved": false,
-                            "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
-                            "optional": true,
-                            "requires": {
-                                "deep-extend": "^0.6.0",
-                                "ini": "~1.3.0",
-                                "minimist": "^1.2.0",
-                                "strip-json-comments": "~2.0.1"
-                            }
-                        },
-                        "readable-stream": {
-                            "version": "2.3.7",
-                            "resolved": false,
-                            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-                            "optional": 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"
-                            }
-                        },
-                        "rimraf": {
-                            "version": "2.7.1",
-                            "resolved": false,
-                            "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-                            "optional": true,
-                            "requires": {
-                                "glob": "^7.1.3"
-                            }
-                        },
-                        "safe-buffer": {
-                            "version": "5.1.2",
-                            "resolved": false,
-                            "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
-                            "optional": true
-                        },
-                        "safer-buffer": {
-                            "version": "2.1.2",
-                            "resolved": false,
-                            "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
-                            "optional": true
-                        },
-                        "sax": {
-                            "version": "1.2.4",
-                            "resolved": false,
-                            "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
-                            "optional": true
-                        },
-                        "semver": {
-                            "version": "5.7.1",
-                            "resolved": false,
-                            "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-                            "optional": true
-                        },
-                        "set-blocking": {
-                            "version": "2.0.0",
-                            "resolved": false,
-                            "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
-                            "optional": true
-                        },
-                        "signal-exit": {
-                            "version": "3.0.2",
-                            "resolved": false,
-                            "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
-                            "optional": true
-                        },
-                        "string-width": {
-                            "version": "1.0.2",
-                            "resolved": false,
-                            "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
-                            "optional": true,
-                            "requires": {
-                                "code-point-at": "^1.0.0",
-                                "is-fullwidth-code-point": "^1.0.0",
-                                "strip-ansi": "^3.0.0"
-                            }
-                        },
-                        "string_decoder": {
-                            "version": "1.1.1",
-                            "resolved": false,
-                            "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-                            "optional": true,
-                            "requires": {
-                                "safe-buffer": "~5.1.0"
-                            }
-                        },
-                        "strip-ansi": {
-                            "version": "3.0.1",
-                            "resolved": false,
-                            "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
-                            "optional": true,
-                            "requires": {
-                                "ansi-regex": "^2.0.0"
-                            }
-                        },
-                        "strip-json-comments": {
-                            "version": "2.0.1",
-                            "resolved": false,
-                            "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
-                            "optional": true
-                        },
-                        "tar": {
-                            "version": "4.4.13",
-                            "resolved": false,
-                            "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
-                            "optional": true,
-                            "requires": {
-                                "chownr": "^1.1.1",
-                                "fs-minipass": "^1.2.5",
-                                "minipass": "^2.8.6",
-                                "minizlib": "^1.2.1",
-                                "mkdirp": "^0.5.0",
-                                "safe-buffer": "^5.1.2",
-                                "yallist": "^3.0.3"
-                            }
-                        },
-                        "util-deprecate": {
-                            "version": "1.0.2",
-                            "resolved": false,
-                            "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
-                            "optional": true
-                        },
-                        "wide-align": {
-                            "version": "1.1.3",
-                            "resolved": false,
-                            "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
-                            "optional": true,
-                            "requires": {
-                                "string-width": "^1.0.2 || 2"
-                            }
-                        },
-                        "wrappy": {
-                            "version": "1.0.2",
-                            "resolved": false,
-                            "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
-                            "optional": true
-                        },
-                        "yallist": {
-                            "version": "3.1.1",
-                            "resolved": false,
-                            "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
-                            "optional": true
-                        }
-                    }
+        "camelcase": {
+            "version": "5.3.1",
+            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+            "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
+        },
+        "camelcase-keys": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+            "integrity": "sha512-bA/Z/DERHKqoEOrp+qeGKw1QlvEQkGZSc0XaY6VnTxZr+Kv1G5zFwttpjv8qxZ/sBPT4nthwZaAcsAZTJlSKXQ==",
+            "requires": {
+                "camelcase": "^2.0.0",
+                "map-obj": "^1.0.0"
+            },
+            "dependencies": {
+                "camelcase": {
+                    "version": "2.1.1",
+                    "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+                    "integrity": "sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw=="
                 }
             }
         },
+        "camelize": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
+            "integrity": "sha512-W2lPwkBkMZwFlPCXhIlYgxu+7gC/NUlCtdK652DAJ1JdgV0sTrvuPFshNPrFa1TY2JOkLhgdeEBplB4ezEa+xg=="
+        },
+        "caniuse-lite": {
+            "version": "1.0.30001346",
+            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001346.tgz",
+            "integrity": "sha512-q6ibZUO2t88QCIPayP/euuDREq+aMAxFE5S70PkrLh0iTDj/zEhgvJRKC2+CvXY6EWc6oQwUR48lL5vCW6jiXQ=="
+        },
+        "canvas": {
+            "version": "2.9.1",
+            "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.9.1.tgz",
+            "integrity": "sha512-vSQti1uG/2gjv3x6QLOZw7TctfufaerTWbVe+NSduHxxLGB+qf3kFgQ6n66DSnuoINtVUjrLLIK2R+lxrBG07A==",
+            "requires": {
+                "@mapbox/node-pre-gyp": "^1.0.0",
+                "nan": "^2.15.0",
+                "simple-get": "^3.0.3"
+            }
+        },
+        "capture-stack-trace": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz",
+            "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw=="
+        },
+        "caseless": {
+            "version": "0.12.0",
+            "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+            "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
+        },
+        "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"
+            }
+        },
+        "chai": {
+            "version": "4.3.6",
+            "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
+            "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
+            "requires": {
+                "assertion-error": "^1.1.0",
+                "check-error": "^1.0.2",
+                "deep-eql": "^3.0.1",
+                "get-func-name": "^2.0.0",
+                "loupe": "^2.3.1",
+                "pathval": "^1.1.1",
+                "type-detect": "^4.0.5"
+            }
+        },
+        "chain-function": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/chain-function/-/chain-function-1.0.1.tgz",
+            "integrity": "sha512-SxltgMwL9uCko5/ZCLiyG2B7R9fY4pDZUw7hJ4MhirdjBLosoDqkWABi3XMucddHdLiFJMb7PD2MZifZriuMTg=="
+        },
+        "chalk": {
+            "version": "2.4.2",
+            "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+            "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+            "requires": {
+                "ansi-styles": "^3.2.1",
+                "escape-string-regexp": "^1.0.5",
+                "supports-color": "^5.3.0"
+            }
+        },
+        "change-emitter": {
+            "version": "0.1.6",
+            "resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz",
+            "integrity": "sha512-YXzt1cQ4a2jqazhcuSWEOc1K2q8g9H6eWNsyZgi640LDzRWVQ2eDe+Y/kVdftH+vYdPF2rgDb3dLdpxE1jvAxw=="
+        },
+        "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"
+            }
+        },
+        "check-error": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+            "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA=="
+        },
+        "child_process": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz",
+            "integrity": "sha512-Wmza/JzL0SiWz7kl6MhIKT5ceIlnFPJX+lwUGj7Clhy5MMldsSoJR0+uvRzOS5Kv45Mq7t1PoE8TsOA9bzvb6g=="
+        },
+        "chokidar": {
+            "version": "2.1.8",
+            "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+            "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+            "requires": {
+                "anymatch": "^2.0.0",
+                "async-each": "^1.0.1",
+                "braces": "^2.3.2",
+                "fsevents": "^1.2.7",
+                "glob-parent": "^3.1.0",
+                "inherits": "^2.0.3",
+                "is-binary-path": "^1.0.0",
+                "is-glob": "^4.0.0",
+                "normalize-path": "^3.0.0",
+                "path-is-absolute": "^1.0.0",
+                "readdirp": "^2.2.1",
+                "upath": "^1.1.1"
+            }
+        },
         "chownr": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
-            "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+            "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="
         },
         "chrome": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/chrome/-/chrome-0.1.0.tgz",
-            "integrity": "sha1-9h2beS/v6MGUxwVt3BAscmqGQyk=",
+            "integrity": "sha512-6KYl20U4Taj6YipylsWr2etUvp9AElJKfGNSBmyGTymYmancnOb041ZNadolEZi2nboLXH7jMSqUmm4kpuTzfg==",
             "requires": {
                 "exeq": "^2.2.0",
                 "plist": "^1.1.0"
@@ -4600,7 +3853,7 @@
         "clamp": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz",
-            "integrity": "sha1-ZqDmQBGBbjcZaCj9yMjBRzEshjQ="
+            "integrity": "sha512-kgMuFyE78OC6Dyu3Dy7vcx4uy97EIbVxJB/B0eJ3bUNAkwdNcxYzgKltnyADiYwsR7SEqkkUPsEUT//OVS6XMA=="
         },
         "class-transformer": {
             "version": "0.2.3",
@@ -4621,7 +3874,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -4629,14 +3882,14 @@
             }
         },
         "classnames": {
-            "version": "2.2.6",
-            "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
-            "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
+            "version": "2.3.1",
+            "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
+            "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA=="
         },
         "clean-css": {
-            "version": "4.2.3",
-            "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
-            "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==",
+            "version": "5.3.0",
+            "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz",
+            "integrity": "sha512-YYuuxv4H/iNb1Z/5IbMRoxgrzjWGhOEFfd+groZ5dMCVkpENiMZmwspdrzBo9286JjM1gZJPAyL7ZIdzuvu2AQ==",
             "requires": {
                 "source-map": "~0.6.0"
             },
@@ -4651,12 +3904,12 @@
         "cli-boxes": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
-            "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM="
+            "integrity": "sha512-3Fo5wu8Ytle8q9iCzS4D2MWVL2X7JVWRiS1BnXbTFDhS9c/REkM9vd1AmabsoZoY5/dGi5TT9iKL8Kb6DeBRQg=="
         },
         "clipboard": {
             "version": "1.7.1",
             "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-1.7.1.tgz",
-            "integrity": "sha1-Ng1taUbpmnof7zleQrqStem1oWs=",
+            "integrity": "sha512-smkaRaIQsrnKN1F3wd1/vY9Q+DeR4L8ZCXKeHCFC2j8RZuSBbuImcLdnIO4GTxmzJxQuDGNKkyfpGoPW7Ua5bQ==",
             "requires": {
                 "good-listener": "^1.2.2",
                 "select": "^1.1.2",
@@ -4681,7 +3934,7 @@
                 "camelcase": {
                     "version": "4.1.0",
                     "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-                    "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
+                    "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw=="
                 },
                 "yargs-parser": {
                     "version": "7.0.0",
@@ -4704,9 +3957,9 @@
             },
             "dependencies": {
                 "ansi-regex": {
-                    "version": "4.1.0",
-                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-                    "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+                    "version": "4.1.1",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+                    "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="
                 },
                 "string-width": {
                     "version": "3.1.0",
@@ -4731,7 +3984,7 @@
         "clj-fuzzy": {
             "version": "0.3.3",
             "resolved": "https://registry.npmjs.org/clj-fuzzy/-/clj-fuzzy-0.3.3.tgz",
-            "integrity": "sha1-seU0MJHFIC28UlMoY+HEp4RX8D0="
+            "integrity": "sha512-9cyh9A8+OphDZeKIG21MgyDHWDkWxTvagwvFLVjtdi6eToFENF7iDLlKwhHrnBQRSQwprKNhazG053nE/UgwfQ=="
         },
         "clone-deep": {
             "version": "4.0.1",
@@ -4746,7 +3999,7 @@
         "clone-response": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
-            "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
+            "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==",
             "requires": {
                 "mimic-response": "^1.0.0"
             },
@@ -4766,12 +4019,12 @@
         "code-point-at": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
-            "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+            "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA=="
         },
         "collection-visit": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
-            "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+            "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==",
             "requires": {
                 "map-visit": "^1.0.0",
                 "object-visit": "^1.0.0"
@@ -4797,12 +4050,12 @@
         "color-name": {
             "version": "1.1.3",
             "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-            "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+            "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
         },
         "color-string": {
-            "version": "1.9.0",
-            "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz",
-            "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==",
+            "version": "1.9.1",
+            "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+            "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
             "requires": {
                 "color-name": "^1.0.0",
                 "simple-swizzle": "^0.2.2"
@@ -4814,9 +4067,9 @@
             "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="
         },
         "colorette": {
-            "version": "2.0.16",
-            "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz",
-            "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g=="
+            "version": "2.0.17",
+            "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.17.tgz",
+            "integrity": "sha512-hJo+3Bkn0NCHybn9Tu35fIeoOKGOk5OCC32y4Hz2It+qlCO2Q3DeQ1hRn/tDDMQKRYUEzqsl7jbF6dYKjlE60g=="
         },
         "colors": {
             "version": "1.4.0",
@@ -4848,20 +4101,20 @@
             }
         },
         "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=="
+            "version": "8.3.0",
+            "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+            "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="
         },
         "commondir": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
-            "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+            "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
             "dev": true
         },
         "component-bind": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
-            "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E="
+            "integrity": "sha512-WZveuKPeKAG9qY+FkYDeADzdHyTYdIboXS59ixDeRJL5ZhxpqUnxSOwop4FQjMsiYm3/Or8cegVbpAHNA7pHxw=="
         },
         "component-emitter": {
             "version": "1.3.0",
@@ -4871,7 +4124,16 @@
         "component-inherit": {
             "version": "0.0.3",
             "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
-            "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM="
+            "integrity": "sha512-w+LhYREhatpVqTESyGFg3NlP6Iu0kEKUHETY9GoZP/pQyW4mHFZuFWRUCIqVPZ36ueVLtoOEZaAqbCF2RDndaA=="
+        },
+        "compress-brotli": {
+            "version": "1.3.8",
+            "resolved": "https://registry.npmjs.org/compress-brotli/-/compress-brotli-1.3.8.tgz",
+            "integrity": "sha512-lVcQsjhxhIXsuupfy9fmZUFtAIdBmXA7EGY6GBdgZ++qkM9zG4YFT8iU7FoBxzryNDMOpD1HIFHUSX4D87oqhQ==",
+            "requires": {
+                "@types/json-buffer": "~3.0.0",
+                "json-buffer": "~3.0.1"
+            }
         },
         "compress-commons": {
             "version": "2.1.1",
@@ -4927,7 +4189,7 @@
                 "bytes": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
-                    "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
+                    "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==",
                     "dev": true
                 },
                 "debug": {
@@ -4942,7 +4204,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
                     "dev": true
                 }
             }
@@ -4950,7 +4212,7 @@
         "concat-map": {
             "version": "0.0.1",
             "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-            "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+            "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
         },
         "concat-stream": {
             "version": "1.6.2",
@@ -4980,22 +4242,37 @@
             }
         },
         "configstore": {
-            "version": "3.1.2",
-            "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz",
-            "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==",
+            "version": "3.1.5",
+            "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.5.tgz",
+            "integrity": "sha512-nlOhI4+fdzoK5xmJ+NY+1gZK56bwEaWZr8fYuXohZ9Vkc1o3a4T/R3M+yE/w7x/ZVJ1zF8c+oaOvF0dztdUgmA==",
             "requires": {
-                "dot-prop": "^4.1.0",
+                "dot-prop": "^4.2.1",
                 "graceful-fs": "^4.1.2",
                 "make-dir": "^1.0.0",
                 "unique-string": "^1.0.0",
                 "write-file-atomic": "^2.0.0",
                 "xdg-basedir": "^3.0.0"
+            },
+            "dependencies": {
+                "make-dir": {
+                    "version": "1.3.0",
+                    "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+                    "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+                    "requires": {
+                        "pify": "^3.0.0"
+                    }
+                },
+                "pify": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+                    "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg=="
+                }
             }
         },
         "connect-flash": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz",
-            "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA="
+            "integrity": "sha512-2rcfELQt/ZMP+SM/pG8PyhJRaLKp+6Hk2IUBNkEit09X+vwn3QsAL3ZbYtxUn7NVPzbMTSLRDhqe0B/eh30RYA=="
         },
         "connect-history-api-fallback": {
             "version": "1.6.0",
@@ -5024,7 +4301,7 @@
                 "process-nextick-args": {
                     "version": "1.0.7",
                     "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
-                    "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
+                    "integrity": "sha512-yN0WQmuCX63LP/TMvAg31nvT6m4vDqJEiiv2CAZqWOGNWutc9DfDk1NPYYmKUFmaVM2UwDowH4u5AHWYP/jxKw=="
                 },
                 "readable-stream": {
                     "version": "2.2.7",
@@ -5053,7 +4330,7 @@
         "console-control-strings": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
-            "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
+            "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
         },
         "constantinople": {
             "version": "3.1.2",
@@ -5137,7 +4414,7 @@
         "cookie-signature": {
             "version": "1.0.6",
             "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
-            "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+            "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
         },
         "cookies": {
             "version": "0.8.0",
@@ -5146,13 +4423,6 @@
             "requires": {
                 "depd": "~2.0.0",
                 "keygrip": "~1.1.0"
-            },
-            "dependencies": {
-                "depd": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
-                    "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
-                }
             }
         },
         "copy-concurrently": {
@@ -5169,6 +4439,12 @@
                 "run-queue": "^1.0.0"
             },
             "dependencies": {
+                "aproba": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                    "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+                    "dev": true
+                },
                 "rimraf": {
                     "version": "2.7.1",
                     "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
@@ -5183,7 +4459,7 @@
         "copy-descriptor": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
-            "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
+            "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw=="
         },
         "copy-webpack-plugin": {
             "version": "4.6.0",
@@ -5213,7 +4489,13 @@
                 "p-try": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
-                    "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+                    "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
+                    "dev": true
+                },
+                "serialize-javascript": {
+                    "version": "1.9.1",
+                    "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz",
+                    "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==",
                     "dev": true
                 }
             }
@@ -5221,17 +4503,17 @@
         "core-js": {
             "version": "1.2.7",
             "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
-            "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
+            "integrity": "sha512-ZiPp9pZlgxpWRu0M+YWbm6+aQ84XEfH1JRXvfOc/fILWI0VKhLC2LX13X1NYq4fULzLMq7Hfh43CSo2/aIaUPA=="
         },
         "core-js-pure": {
-            "version": "3.21.1",
-            "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.1.tgz",
-            "integrity": "sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ=="
+            "version": "3.22.8",
+            "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.22.8.tgz",
+            "integrity": "sha512-bOxbZIy9S5n4OVH63XaLVXZ49QKicjowDx/UELyJ68vxfCRpYsbyh/WNZNfEfAk+ekA8vSjt+gCDpvh672bc3w=="
         },
         "core-util-is": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
-            "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+            "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
         },
         "cors": {
             "version": "2.8.5",
@@ -5285,7 +4567,7 @@
         "create-error-class": {
             "version": "3.0.2",
             "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
-            "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=",
+            "integrity": "sha512-gYTKKexFO3kh200H1Nit76sRwRtOY32vQd3jpAQKpLtZqyNsSQNfI4N7o3eP2wUjV35pTWKRYqFUDBvUha/Pkw==",
             "requires": {
                 "capture-stack-trace": "^1.0.0"
             }
@@ -5344,32 +4626,13 @@
                     "requires": {
                         "whatwg-url": "^5.0.0"
                     }
-                },
-                "tr46": {
-                    "version": "0.0.3",
-                    "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
-                    "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
-                },
-                "webidl-conversions": {
-                    "version": "3.0.1",
-                    "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
-                    "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
-                },
-                "whatwg-url": {
-                    "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
-                    "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
-                    "requires": {
-                        "tr46": "~0.0.3",
-                        "webidl-conversions": "^3.0.0"
-                    }
                 }
             }
         },
         "cross-spawn": {
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
-            "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
+            "integrity": "sha512-eZ+m1WNhSZutOa/uRblAc9Ut5MQfukFrFMtPSm3bZCA888NmMd5AWXWdgRZ80zd+pTk1P2JrGjg9pUPTvl2PWQ==",
             "requires": {
                 "lru-cache": "^4.0.1",
                 "which": "^1.2.9"
@@ -5399,7 +4662,7 @@
         "crypto-random-string": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
-            "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4="
+            "integrity": "sha512-GsVpkFPlycH7/fRR7Dhcmnoii54gV1nz7y4CWyeFS14N+JVBBhY+r8amRHE4BwSYal7BPTDp8isvAlCxyFt3Hg=="
         },
         "css-box-model": {
             "version": "1.2.1",
@@ -5412,7 +4675,7 @@
         "css-color-keywords": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
-            "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU="
+            "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg=="
         },
         "css-in-js-utils": {
             "version": "2.0.1",
@@ -5440,37 +4703,24 @@
                 "postcss-modules-values": "^2.0.0",
                 "postcss-value-parser": "^3.3.0",
                 "schema-utils": "^1.0.0"
-            },
-            "dependencies": {
-                "schema-utils": {
-                    "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
-                    "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
-                    "dev": true,
-                    "requires": {
-                        "ajv": "^6.1.0",
-                        "ajv-errors": "^1.0.0",
-                        "ajv-keywords": "^3.1.0"
-                    }
-                }
             }
         },
         "css-select": {
-            "version": "4.2.1",
-            "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz",
-            "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==",
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
+            "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
             "requires": {
                 "boolbase": "^1.0.0",
-                "css-what": "^5.1.0",
-                "domhandler": "^4.3.0",
+                "css-what": "^6.0.1",
+                "domhandler": "^4.3.1",
                 "domutils": "^2.8.0",
                 "nth-check": "^2.0.1"
             },
             "dependencies": {
                 "dom-serializer": {
-                    "version": "1.3.2",
-                    "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
-                    "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
+                    "version": "1.4.1",
+                    "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
+                    "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
                     "requires": {
                         "domelementtype": "^2.0.1",
                         "domhandler": "^4.2.0",
@@ -5478,14 +4728,14 @@
                     }
                 },
                 "domelementtype": {
-                    "version": "2.2.0",
-                    "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
-                    "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
+                    "version": "2.3.0",
+                    "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+                    "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
                 },
                 "domhandler": {
-                    "version": "4.3.0",
-                    "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
-                    "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
+                    "version": "4.3.1",
+                    "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
+                    "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
                     "requires": {
                         "domelementtype": "^2.2.0"
                     }
@@ -5527,9 +4777,9 @@
             }
         },
         "css-what": {
-            "version": "5.1.0",
-            "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz",
-            "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw=="
+            "version": "6.1.0",
+            "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
+            "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw=="
         },
         "cssesc": {
             "version": "3.0.0",
@@ -5544,9 +4794,9 @@
             "dev": true
         },
         "cssstyle": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.2.0.tgz",
-            "integrity": "sha512-sEb3XFPx3jNnCAMtqrXPDeSgQr+jojtCeNf8cvMNMh1cG970+lljssvQDzPq6lmmJu2Vhqood/gtEomBiHOGnA==",
+            "version": "2.3.0",
+            "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz",
+            "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==",
             "dev": true,
             "requires": {
                 "cssom": "~0.3.6"
@@ -5561,14 +4811,14 @@
             }
         },
         "csstype": {
-            "version": "2.6.19",
-            "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.19.tgz",
-            "integrity": "sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ=="
+            "version": "2.6.20",
+            "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz",
+            "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA=="
         },
         "currently-unhandled": {
             "version": "0.4.1",
             "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
-            "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+            "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==",
             "requires": {
                 "array-find-index": "^1.0.1"
             }
@@ -5576,18 +4826,21 @@
         "custom-event": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz",
-            "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU="
+            "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg=="
         },
         "cyclist": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
-            "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
+            "integrity": "sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A==",
             "dev": true
         },
         "d3-array": {
-            "version": "1.2.4",
-            "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
-            "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
+            "version": "2.12.1",
+            "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
+            "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
+            "requires": {
+                "internmap": "^1.0.0"
+            }
         },
         "d3-axis": {
             "version": "2.1.0",
@@ -5646,16 +4899,6 @@
                 "d3-interpolate": "1.2.0 - 2",
                 "d3-time": "^2.1.1",
                 "d3-time-format": "2 - 3"
-            },
-            "dependencies": {
-                "d3-array": {
-                    "version": "2.12.1",
-                    "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
-                    "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
-                    "requires": {
-                        "internmap": "^1.0.0"
-                    }
-                }
             }
         },
         "d3-selection": {
@@ -5677,16 +4920,6 @@
             "integrity": "sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==",
             "requires": {
                 "d3-array": "2"
-            },
-            "dependencies": {
-                "d3-array": {
-                    "version": "2.12.1",
-                    "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
-                    "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
-                    "requires": {
-                        "internmap": "^1.0.0"
-                    }
-                }
             }
         },
         "d3-time-format": {
@@ -5729,7 +4962,7 @@
         "dashdash": {
             "version": "1.14.1",
             "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
-            "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+            "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
             "requires": {
                 "assert-plus": "^1.0.0"
             }
@@ -5743,6 +4976,34 @@
                 "abab": "^2.0.0",
                 "whatwg-mimetype": "^2.2.0",
                 "whatwg-url": "^7.0.0"
+            },
+            "dependencies": {
+                "tr46": {
+                    "version": "1.0.1",
+                    "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
+                    "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
+                    "dev": true,
+                    "requires": {
+                        "punycode": "^2.1.0"
+                    }
+                },
+                "webidl-conversions": {
+                    "version": "4.0.2",
+                    "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
+                    "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
+                    "dev": true
+                },
+                "whatwg-url": {
+                    "version": "7.1.0",
+                    "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
+                    "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
+                    "dev": true,
+                    "requires": {
+                        "lodash.sortby": "^4.7.0",
+                        "tr46": "^1.0.1",
+                        "webidl-conversions": "^4.0.2"
+                    }
+                }
             }
         },
         "date-fns": {
@@ -5753,7 +5014,7 @@
         "de-indent": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
-            "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0="
+            "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg=="
         },
         "debounce": {
             "version": "1.2.1",
@@ -5771,12 +5032,12 @@
         "decamelize": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
-            "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+            "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": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
+            "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og=="
         },
         "decompress-response": {
             "version": "4.2.1",
@@ -5813,9 +5074,9 @@
             "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
         },
         "deep-is": {
-            "version": "0.1.3",
-            "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
-            "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+            "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
         },
         "deepmerge": {
@@ -5878,11 +5139,12 @@
             "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg=="
         },
         "define-properties": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
-            "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
+            "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
             "requires": {
-                "object-keys": "^1.0.12"
+                "has-property-descriptors": "^1.0.0",
+                "object-keys": "^1.1.1"
             }
         },
         "define-property": {
@@ -5940,7 +5202,7 @@
                 "globby": {
                     "version": "6.1.0",
                     "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
-                    "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
+                    "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==",
                     "dev": true,
                     "requires": {
                         "array-union": "^1.0.1",
@@ -5953,11 +5215,17 @@
                         "pify": {
                             "version": "2.3.0",
                             "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-                            "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+                            "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
                             "dev": true
                         }
                     }
                 },
+                "pify": {
+                    "version": "4.0.1",
+                    "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+                    "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+                    "dev": true
+                },
                 "rimraf": {
                     "version": "2.7.1",
                     "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
@@ -5972,7 +5240,7 @@
         "delayed-stream": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-            "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+            "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
         },
         "delegate": {
             "version": "3.2.0",
@@ -5982,18 +5250,13 @@
         "delegates": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
-            "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
+            "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
         },
         "denque": {
             "version": "1.5.1",
             "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz",
             "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw=="
         },
-        "density-clustering": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/density-clustering/-/density-clustering-1.3.0.tgz",
-            "integrity": "sha1-3J9ZyPCrl+FiSsZJMP0xlIF9ysU="
-        },
         "depcheck": {
             "version": "0.9.2",
             "resolved": "https://registry.npmjs.org/depcheck/-/depcheck-0.9.2.tgz",
@@ -6019,24 +5282,18 @@
             },
             "dependencies": {
                 "ansi-regex": {
-                    "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
-                    "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
+                    "version": "5.0.1",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+                    "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
                 },
                 "ansi-styles": {
-                    "version": "4.2.1",
-                    "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
-                    "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+                    "version": "4.3.0",
+                    "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+                    "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
                     "requires": {
-                        "@types/color-name": "^1.1.1",
                         "color-convert": "^2.0.1"
                     }
                 },
-                "builtin-modules": {
-                    "version": "3.1.0",
-                    "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz",
-                    "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw=="
-                },
                 "cliui": {
                     "version": "6.0.0",
                     "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
@@ -6072,11 +5329,11 @@
                     }
                 },
                 "debug": {
-                    "version": "4.1.1",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+                    "version": "4.3.4",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+                    "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
                     "requires": {
-                        "ms": "^2.1.1"
+                        "ms": "2.1.2"
                     }
                 },
                 "emoji-regex": {
@@ -6096,7 +5353,7 @@
                 "import-fresh": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
-                    "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
+                    "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==",
                     "requires": {
                         "caller-path": "^2.0.0",
                         "resolve-from": "^3.0.0"
@@ -6115,6 +5372,11 @@
                         "p-locate": "^4.1.0"
                     }
                 },
+                "ms": {
+                    "version": "2.1.2",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+                    "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+                },
                 "p-locate": {
                     "version": "4.1.0",
                     "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
@@ -6126,7 +5388,7 @@
                 "parse-json": {
                     "version": "4.0.0",
                     "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
-                    "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+                    "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
                     "requires": {
                         "error-ex": "^1.3.1",
                         "json-parse-better-errors": "^1.0.1"
@@ -6143,21 +5405,21 @@
                     "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
                 },
                 "string-width": {
-                    "version": "4.2.0",
-                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
-                    "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+                    "version": "4.2.3",
+                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+                    "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
                     "requires": {
                         "emoji-regex": "^8.0.0",
                         "is-fullwidth-code-point": "^3.0.0",
-                        "strip-ansi": "^6.0.0"
+                        "strip-ansi": "^6.0.1"
                     }
                 },
                 "strip-ansi": {
-                    "version": "6.0.0",
-                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
-                    "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+                    "version": "6.0.1",
+                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+                    "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
                     "requires": {
-                        "ansi-regex": "^5.0.0"
+                        "ansi-regex": "^5.0.1"
                     }
                 },
                 "wrap-ansi": {
@@ -6171,9 +5433,9 @@
                     }
                 },
                 "yargs": {
-                    "version": "15.3.1",
-                    "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz",
-                    "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==",
+                    "version": "15.4.1",
+                    "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+                    "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
                     "requires": {
                         "cliui": "^6.0.0",
                         "decamelize": "^1.2.0",
@@ -6185,7 +5447,7 @@
                         "string-width": "^4.2.0",
                         "which-module": "^2.0.0",
                         "y18n": "^4.0.0",
-                        "yargs-parser": "^18.1.1"
+                        "yargs-parser": "^18.1.2"
                     }
                 },
                 "yargs-parser": {
@@ -6200,24 +5462,24 @@
             }
         },
         "depd": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
-            "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+            "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
         },
         "deps-regex": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/deps-regex/-/deps-regex-0.1.4.tgz",
-            "integrity": "sha1-UYZnt2kUYKXn4KNBvnbrfOgJAYQ="
+            "integrity": "sha512-3tzwGYogSJi8HoG93R5x9NrdefZQOXgHgGih/7eivloOq6yC6O+yoFxZnkgP661twvfILONfoKRdF9GQOGx2RA=="
         },
         "destroy": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
-            "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+            "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
         },
         "detect-libc": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
-            "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
+            "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w=="
         },
         "detect-node": {
             "version": "2.1.0",
@@ -6256,7 +5518,7 @@
                 "pify": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-                    "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+                    "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
                     "dev": true
                 }
             }
@@ -6264,7 +5526,7 @@
         "dns-equal": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
-            "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
+            "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==",
             "dev": true
         },
         "dns-packet": {
@@ -6280,7 +5542,7 @@
         "dns-txt": {
             "version": "2.0.2",
             "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
-            "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
+            "integrity": "sha512-Ix5PrWjphuSoUXV/Zv5gaFHjnaJtb02F2+Si3Ht9dyJ87+Z/lMmy+dpNHtTGraNK958ndXq2i+GLkWsWHcKaBQ==",
             "dev": true,
             "requires": {
                 "buffer-indexof": "^1.0.0"
@@ -6289,7 +5551,7 @@
         "doctypes": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz",
-            "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk="
+            "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ=="
         },
         "dom-converter": {
             "version": "0.2.0",
@@ -6317,14 +5579,14 @@
             },
             "dependencies": {
                 "domelementtype": {
-                    "version": "2.0.1",
-                    "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz",
-                    "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ=="
+                    "version": "2.3.0",
+                    "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+                    "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
                 },
                 "entities": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz",
-                    "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw=="
+                    "version": "2.2.0",
+                    "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
+                    "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
                 }
             }
         },
@@ -6340,6 +5602,14 @@
             "dev": true,
             "requires": {
                 "webidl-conversions": "^4.0.2"
+            },
+            "dependencies": {
+                "webidl-conversions": {
+                    "version": "4.0.2",
+                    "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
+                    "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
+                    "dev": true
+                }
             }
         },
         "domhandler": {
@@ -6350,6 +5620,11 @@
                 "domelementtype": "1"
             }
         },
+        "dommatrix": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/dommatrix/-/dommatrix-1.0.3.tgz",
+            "integrity": "sha512-l32Xp/TLgWb8ReqbVJAFIvXmY7go4nTxxlWiAFyhoQw9RKEOHBZNnyGvJWqDVSPmq3Y9HlM4npqF/T6VMOXhww=="
+        },
         "domutils": {
             "version": "1.7.0",
             "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
@@ -6366,19 +5641,12 @@
             "requires": {
                 "no-case": "^3.0.4",
                 "tslib": "^2.0.3"
-            },
-            "dependencies": {
-                "tslib": {
-                    "version": "2.3.1",
-                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
-                    "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
-                }
             }
         },
         "dot-prop": {
-            "version": "4.2.0",
-            "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
-            "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
+            "version": "4.2.1",
+            "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz",
+            "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==",
             "requires": {
                 "is-obj": "^1.0.0"
             }
@@ -6392,12 +5660,12 @@
         "double-bits": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/double-bits/-/double-bits-1.1.1.tgz",
-            "integrity": "sha1-WKu6RUlNpND6Nrc60RoobJGEscY="
+            "integrity": "sha512-BCLEIBq0O/DWoA7BsCu/R+RP0ZXiowP8BhtJT3qeuuQEBpnS8LK/Wo6UTJQv6v8mK1fj8n90YziHLwGdM5whSg=="
         },
         "duplexer3": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
-            "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
+            "integrity": "sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA=="
         },
         "duplexify": {
             "version": "3.7.1",
@@ -6431,7 +5699,7 @@
         "dynamic-dedupe": {
             "version": "0.3.0",
             "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
-            "integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=",
+            "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==",
             "dev": true,
             "requires": {
                 "xtend": "^4.0.0"
@@ -6440,7 +5708,7 @@
         "ecc-jsbn": {
             "version": "0.1.2",
             "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
-            "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+            "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
             "requires": {
                 "jsbn": "~0.1.0",
                 "safer-buffer": "^2.1.0"
@@ -6457,12 +5725,12 @@
         "ee-first": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
-            "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+            "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
         },
         "electron-to-chromium": {
-            "version": "1.4.75",
-            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.75.tgz",
-            "integrity": "sha512-LxgUNeu3BVU7sXaKjUDD9xivocQLxFtq6wgERrutdY/yIOps3ODOZExK1jg8DTEg4U8TUCb5MLGeWFOYuxjF3Q=="
+            "version": "1.4.146",
+            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.146.tgz",
+            "integrity": "sha512-4eWebzDLd+hYLm4csbyMU2EbBnqhwl8Oe9eF/7CBDPWcRxFmqzx4izxvHH+lofQxzieg8UbB8ZuzNTxeukzfTg=="
         },
         "emoji-regex": {
             "version": "7.0.3",
@@ -6486,14 +5754,14 @@
         "encodeurl": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
-            "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+            "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
         },
         "encoding": {
-            "version": "0.1.12",
-            "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
-            "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
+            "version": "0.1.13",
+            "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
+            "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
             "requires": {
-                "iconv-lite": "~0.4.13"
+                "iconv-lite": "^0.6.2"
             }
         },
         "end-of-stream": {
@@ -6561,7 +5829,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                 },
                 "ws": {
                     "version": "7.4.6",
@@ -6583,14 +5851,13 @@
             }
         },
         "enhanced-resolve": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz",
-            "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==",
+            "version": "5.9.3",
+            "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz",
+            "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==",
             "dev": true,
             "requires": {
-                "graceful-fs": "^4.1.2",
-                "memory-fs": "^0.5.0",
-                "tapable": "^1.0.0"
+                "graceful-fs": "^4.2.4",
+                "tapable": "^2.2.0"
             }
         },
         "entities": {
@@ -6604,17 +5871,17 @@
             "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw=="
         },
         "equation-editor-react": {
-            "version": "git+ssh://git@github.com/bobzel/equation-editor-react.git#75915e852b4b36a6a4cd3e1cbc80598da6b65227",
-            "from": "equation-editor-react@github:bobzel/equation-editor-react#useLocally",
+            "version": "github:bobzel/equation-editor-react#75915e852b4b36a6a4cd3e1cbc80598da6b65227",
+            "from": "github:bobzel/equation-editor-react#useLocally",
             "requires": {
                 "jquery": "^3.4.1",
                 "mathquill": "^0.10.1-a"
             }
         },
         "errno": {
-            "version": "0.1.7",
-            "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
-            "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+            "version": "0.1.8",
+            "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
+            "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
             "dev": true,
             "requires": {
                 "prr": "~1.0.1"
@@ -6629,23 +5896,53 @@
             }
         },
         "es-abstract": {
-            "version": "1.17.5",
-            "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
-            "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
+            "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-symbols": "^1.0.1",
-                "is-callable": "^1.1.5",
-                "is-regex": "^1.0.5",
-                "object-inspect": "^1.7.0",
+                "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.0",
-                "string.prototype.trimleft": "^2.1.1",
-                "string.prototype.trimright": "^2.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"
+            },
+            "dependencies": {
+                "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"
+                    }
+                }
             }
         },
+        "es-array-method-boxes-properly": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz",
+            "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA=="
+        },
         "es-module-lexer": {
             "version": "0.9.3",
             "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz",
@@ -6662,44 +5959,10 @@
                 "is-symbol": "^1.0.2"
             }
         },
-        "es5-ext": {
-            "version": "0.10.59",
-            "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.59.tgz",
-            "integrity": "sha512-cOgyhW0tIJyQY1Kfw6Kr0viu9ZlUctVchRMZ7R0HiH3dxTSp5zJDLecwxUqPUrGKMsgBI1wd1FL+d9Jxfi4cLw==",
-            "dev": true,
-            "requires": {
-                "es6-iterator": "^2.0.3",
-                "es6-symbol": "^3.1.3",
-                "next-tick": "^1.1.0"
-            }
-        },
-        "es6-iterator": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
-            "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
-            "dev": true,
-            "requires": {
-                "d": "1",
-                "es5-ext": "^0.10.35",
-                "es6-symbol": "^3.1.1"
-            },
-            "dependencies": {
-                "d": {
-                    "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
-                    "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
-                    "dev": true,
-                    "requires": {
-                        "es5-ext": "^0.10.50",
-                        "type": "^1.0.1"
-                    }
-                }
-            }
-        },
         "es6-promise": {
             "version": "3.2.1",
             "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz",
-            "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q="
+            "integrity": "sha512-oj4jOSXvWglTsc3wrw86iom3LDPOx1nbipQk+jaG3dy+sMRM6ReSgVr/VlmBuF6lXUrflN9DCcQHeSbAwGUl4g=="
         },
         "es6-symbol": {
             "version": "3.1.3",
@@ -6707,20 +5970,7 @@
             "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
             "dev": true,
             "requires": {
-                "d": "^1.0.1",
                 "ext": "^1.1.2"
-            },
-            "dependencies": {
-                "d": {
-                    "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
-                    "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
-                    "dev": true,
-                    "requires": {
-                        "es5-ext": "^0.10.50",
-                        "type": "^1.0.1"
-                    }
-                }
             }
         },
         "escalade": {
@@ -6731,17 +5981,17 @@
         "escape-html": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-            "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+            "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": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+            "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
         },
         "escodegen": {
-            "version": "1.14.1",
-            "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz",
-            "integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==",
+            "version": "1.14.3",
+            "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz",
+            "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==",
             "dev": true,
             "requires": {
                 "esprima": "^4.0.1",
@@ -6806,7 +6056,7 @@
         "etag": {
             "version": "1.8.1",
             "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
-            "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+            "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
         },
         "event-target-shim": {
             "version": "5.0.1",
@@ -6826,18 +6076,15 @@
             "dev": true
         },
         "eventsource": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.0.tgz",
-            "integrity": "sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==",
-            "dev": true,
-            "requires": {
-                "original": "^1.0.0"
-            }
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz",
+            "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==",
+            "dev": true
         },
         "execa": {
             "version": "0.7.0",
             "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
-            "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+            "integrity": "sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==",
             "requires": {
                 "cross-spawn": "^5.0.1",
                 "get-stream": "^3.0.0",
@@ -6851,13 +6098,18 @@
                 "cross-spawn": {
                     "version": "5.1.0",
                     "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
-                    "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+                    "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==",
                     "requires": {
                         "lru-cache": "^4.0.1",
                         "shebang-command": "^1.2.0",
                         "which": "^1.2.9"
                     }
                 },
+                "get-stream": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+                    "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ=="
+                },
                 "lru-cache": {
                     "version": "4.1.5",
                     "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
@@ -6877,12 +6129,12 @@
         "exenv": {
             "version": "1.2.2",
             "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
-            "integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50="
+            "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw=="
         },
         "exeq": {
             "version": "2.4.0",
             "resolved": "https://registry.npmjs.org/exeq/-/exeq-2.4.0.tgz",
-            "integrity": "sha1-Td8qaEZIxCeteZNJzzO9dTWPiEo=",
+            "integrity": "sha512-B648qbDS00nQZv9UQGLT5RbZm/5dNBX10F8oWeXcgpFHSLm1249u95t/3sn2wXdQjLhlF+edAECdshFtSr1K0Q==",
             "requires": {
                 "bluebird": "^3.0.3",
                 "native-or-bluebird": "^1.2.0"
@@ -6891,7 +6143,7 @@
         "exif": {
             "version": "0.6.0",
             "resolved": "https://registry.npmjs.org/exif/-/exif-0.6.0.tgz",
-            "integrity": "sha1-YKYmaAdlQst+T1cZnUrG830sX0o=",
+            "integrity": "sha512-gEwM4uanNMfLnDNKclZ7jPEA99E3rpy4ntoS6QW8u6murZjl1o8qRaPdMoC46Syg3d9/QaET0bYKhWlTwJCPgg==",
             "requires": {
                 "debug": "^2.2"
             },
@@ -6907,7 +6159,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                 }
             }
         },
@@ -6919,7 +6171,7 @@
         "expand-brackets": {
             "version": "2.1.4",
             "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
-            "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+            "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==",
             "requires": {
                 "debug": "^2.3.3",
                 "define-property": "^0.2.5",
@@ -6941,7 +6193,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -6949,20 +6201,15 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
                 },
-                "is-extendable": {
-                    "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-                    "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
-                },
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                 }
             }
         },
@@ -6972,46 +6219,47 @@
             "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="
         },
         "express": {
-            "version": "4.17.3",
-            "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz",
-            "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==",
+            "version": "4.18.1",
+            "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
+            "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
             "requires": {
                 "accepts": "~1.3.8",
                 "array-flatten": "1.1.1",
-                "body-parser": "1.19.2",
+                "body-parser": "1.20.0",
                 "content-disposition": "0.5.4",
                 "content-type": "~1.0.4",
-                "cookie": "0.4.2",
+                "cookie": "0.5.0",
                 "cookie-signature": "1.0.6",
                 "debug": "2.6.9",
-                "depd": "~1.1.2",
+                "depd": "2.0.0",
                 "encodeurl": "~1.0.2",
                 "escape-html": "~1.0.3",
                 "etag": "~1.8.1",
-                "finalhandler": "~1.1.2",
+                "finalhandler": "1.2.0",
                 "fresh": "0.5.2",
+                "http-errors": "2.0.0",
                 "merge-descriptors": "1.0.1",
                 "methods": "~1.1.2",
-                "on-finished": "~2.3.0",
+                "on-finished": "2.4.1",
                 "parseurl": "~1.3.3",
                 "path-to-regexp": "0.1.7",
                 "proxy-addr": "~2.0.7",
-                "qs": "6.9.7",
+                "qs": "6.10.3",
                 "range-parser": "~1.2.1",
                 "safe-buffer": "5.2.1",
-                "send": "0.17.2",
-                "serve-static": "1.14.2",
+                "send": "0.18.0",
+                "serve-static": "1.15.0",
                 "setprototypeof": "1.2.0",
-                "statuses": "~1.5.0",
+                "statuses": "2.0.1",
                 "type-is": "~1.6.18",
                 "utils-merge": "1.0.1",
                 "vary": "~1.1.2"
             },
             "dependencies": {
                 "cookie": {
-                    "version": "0.4.2",
-                    "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
-                    "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA=="
+                    "version": "0.5.0",
+                    "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
+                    "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="
                 },
                 "debug": {
                     "version": "2.6.9",
@@ -7024,12 +6272,15 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                 },
                 "qs": {
-                    "version": "6.9.7",
-                    "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz",
-                    "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw=="
+                    "version": "6.10.3",
+                    "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
+                    "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
+                    "requires": {
+                        "side-channel": "^1.0.4"
+                    }
                 },
                 "safe-buffer": {
                     "version": "5.2.1",
@@ -7041,17 +6292,17 @@
         "express-flash": {
             "version": "0.0.2",
             "resolved": "https://registry.npmjs.org/express-flash/-/express-flash-0.0.2.tgz",
-            "integrity": "sha1-I9GovPP5DXB5KOSJ+Whp7K0KzaI=",
+            "integrity": "sha512-QVUR0ZZRCaa8+iPHoUQaQJrQWcQuK/Q+19M7IUIdIEtvwhrA/ifHT7y1CVJI41YfGiOQnbGtn3uvd2vOdgu58A==",
             "requires": {
                 "connect-flash": "0.1.x"
             }
         },
         "express-session": {
-            "version": "1.17.2",
-            "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz",
-            "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==",
+            "version": "1.17.3",
+            "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz",
+            "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==",
             "requires": {
-                "cookie": "0.4.1",
+                "cookie": "0.4.2",
                 "cookie-signature": "1.0.6",
                 "debug": "2.6.9",
                 "depd": "~2.0.0",
@@ -7061,6 +6312,11 @@
                 "uid-safe": "~2.1.5"
             },
             "dependencies": {
+                "cookie": {
+                    "version": "0.4.2",
+                    "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
+                    "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA=="
+                },
                 "debug": {
                     "version": "2.6.9",
                     "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -7069,15 +6325,10 @@
                         "ms": "2.0.0"
                     }
                 },
-                "depd": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
-                    "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
-                },
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                 },
                 "safe-buffer": {
                     "version": "5.2.1",
@@ -7098,21 +6349,21 @@
         "expressjs": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/expressjs/-/expressjs-1.0.1.tgz",
-            "integrity": "sha1-IgMoRpoY31rWFeK3oM6ZXxf7ru8="
+            "integrity": "sha512-eFnQ5bMJxTZ29XwRJPV8ee/OURBBMS6Fm+b5rvMMEyz6u2IxPEh2SRzMZt9WvgnV+SMLmnzkALE1DnGG1HxJCw=="
         },
         "ext": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz",
-            "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==",
+            "version": "1.6.0",
+            "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz",
+            "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==",
             "dev": true,
             "requires": {
-                "type": "^2.0.0"
+                "type": "^2.5.0"
             },
             "dependencies": {
                 "type": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz",
-                    "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==",
+                    "version": "2.6.0",
+                    "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz",
+                    "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==",
                     "dev": true
                 }
             }
@@ -7125,10 +6376,20 @@
         "extend-shallow": {
             "version": "3.0.2",
             "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
-            "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+            "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==",
             "requires": {
                 "assign-symbols": "^1.0.0",
                 "is-extendable": "^1.0.1"
+            },
+            "dependencies": {
+                "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"
+                    }
+                }
             }
         },
         "extglob": {
@@ -7149,7 +6410,7 @@
                 "define-property": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-                    "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+                    "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
                     "requires": {
                         "is-descriptor": "^1.0.0"
                     }
@@ -7157,7 +6418,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -7187,11 +6448,6 @@
                         "is-data-descriptor": "^1.0.0",
                         "kind-of": "^6.0.2"
                     }
-                },
-                "is-extendable": {
-                    "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-                    "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
                 }
             }
         },
@@ -7207,32 +6463,37 @@
             },
             "dependencies": {
                 "debug": {
-                    "version": "4.1.1",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+                    "version": "4.3.4",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+                    "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
                     "requires": {
-                        "ms": "^2.1.1"
+                        "ms": "2.1.2"
                     }
                 },
                 "get-stream": {
-                    "version": "5.1.0",
-                    "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
-                    "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
+                    "version": "5.2.0",
+                    "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+                    "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
                     "requires": {
                         "pump": "^3.0.0"
                     }
+                },
+                "ms": {
+                    "version": "2.1.2",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+                    "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
                 }
             }
         },
         "extsprintf": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
-            "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
+            "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g=="
         },
         "fast-deep-equal": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
-            "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA=="
+            "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=="
         },
         "fast-json-stable-stringify": {
             "version": "2.1.0",
@@ -7242,13 +6503,13 @@
         "fast-levenshtein": {
             "version": "2.0.6",
             "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-            "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+            "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
             "dev": true
         },
         "fast-text-encoding": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.2.tgz",
-            "integrity": "sha512-5rQdinSsycpzvAoHga2EDn+LRX1d5xLFsuNG0Kg61JrAT/tASXcLL0nf/33v+sAxlQcfYmWbTURa1mmAf55jGw=="
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz",
+            "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig=="
         },
         "fastest-levenshtein": {
             "version": "1.0.12",
@@ -7265,9 +6526,9 @@
             }
         },
         "fbjs": {
-            "version": "0.8.17",
-            "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz",
-            "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=",
+            "version": "0.8.18",
+            "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.18.tgz",
+            "integrity": "sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA==",
             "requires": {
                 "core-js": "^1.0.0",
                 "isomorphic-fetch": "^2.1.1",
@@ -7275,13 +6536,13 @@
                 "object-assign": "^4.1.0",
                 "promise": "^7.1.1",
                 "setimmediate": "^1.0.5",
-                "ua-parser-js": "^0.7.18"
+                "ua-parser-js": "^0.7.30"
             }
         },
         "fd-slicer": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
-            "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
+            "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
             "requires": {
                 "pend": "~1.2.0"
             }
@@ -7289,7 +6550,7 @@
         "ffmpeg": {
             "version": "0.0.4",
             "resolved": "https://registry.npmjs.org/ffmpeg/-/ffmpeg-0.0.4.tgz",
-            "integrity": "sha1-HEYN+OfaUSf2LO70v6BsWciWMMs=",
+            "integrity": "sha512-3TgWUJJlZGQn+crJFyhsO/oNeRRnGTy6GhgS98oUCIfZrOW5haPPV7DUfOm3xJcHr5q3TJpjk2GudPutrNisRA==",
             "requires": {
                 "when": ">= 0.0.1"
             }
@@ -7302,19 +6563,6 @@
             "requires": {
                 "loader-utils": "^1.0.2",
                 "schema-utils": "^1.0.0"
-            },
-            "dependencies": {
-                "schema-utils": {
-                    "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
-                    "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
-                    "dev": true,
-                    "requires": {
-                        "ajv": "^6.1.0",
-                        "ajv-errors": "^1.0.0",
-                        "ajv-keywords": "^3.1.0"
-                    }
-                }
             }
         },
         "file-saver": {
@@ -7331,7 +6579,7 @@
         "fill-range": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
-            "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+            "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==",
             "requires": {
                 "extend-shallow": "^2.0.1",
                 "is-number": "^3.0.0",
@@ -7342,34 +6590,29 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
-                },
-                "is-extendable": {
-                    "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-                    "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
                 }
             }
         },
         "filter-obj": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
-            "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs="
+            "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ=="
         },
         "finalhandler": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
-            "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
+            "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
             "requires": {
                 "debug": "2.6.9",
                 "encodeurl": "~1.0.2",
                 "escape-html": "~1.0.3",
-                "on-finished": "~2.3.0",
+                "on-finished": "2.4.1",
                 "parseurl": "~1.3.3",
-                "statuses": "~1.5.0",
+                "statuses": "2.0.1",
                 "unpipe": "~1.0.0"
             },
             "dependencies": {
@@ -7384,14 +6627,14 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                 }
             }
         },
         "find": {
             "version": "0.1.7",
             "resolved": "https://registry.npmjs.org/find/-/find-0.1.7.tgz",
-            "integrity": "sha1-yGyHrxqxjyIrvjjeyGy8dg0Wpvs=",
+            "integrity": "sha512-jPrupTOe/pO//3a9Ty2o4NqQCp0L46UG+swUnfFtdmtQVN8pEltKpAqR7Nuf6vWn0GBXx5w+R1MyZzqwjEIqdA==",
             "requires": {
                 "traverse-chain": "~0.1.0"
             }
@@ -7399,12 +6642,81 @@
         "find-cache-dir": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
-            "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
+            "integrity": "sha512-46TFiBOzX7xq/PcSWfFwkyjpemdRnMe31UQF+os0y+1W3k95f6R4SEt02Hj4p3X0Mir9gfrkmOtshFidS0VPUg==",
             "dev": true,
             "requires": {
                 "commondir": "^1.0.1",
                 "make-dir": "^1.0.0",
                 "pkg-dir": "^2.0.0"
+            },
+            "dependencies": {
+                "find-up": {
+                    "version": "2.1.0",
+                    "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+                    "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
+                    "dev": true,
+                    "requires": {
+                        "locate-path": "^2.0.0"
+                    }
+                },
+                "locate-path": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+                    "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
+                    "dev": true,
+                    "requires": {
+                        "p-locate": "^2.0.0",
+                        "path-exists": "^3.0.0"
+                    }
+                },
+                "make-dir": {
+                    "version": "1.3.0",
+                    "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+                    "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+                    "dev": true,
+                    "requires": {
+                        "pify": "^3.0.0"
+                    }
+                },
+                "p-limit": {
+                    "version": "1.3.0",
+                    "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+                    "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+                    "dev": true,
+                    "requires": {
+                        "p-try": "^1.0.0"
+                    }
+                },
+                "p-locate": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+                    "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
+                    "dev": true,
+                    "requires": {
+                        "p-limit": "^1.1.0"
+                    }
+                },
+                "p-try": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+                    "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
+                    "dev": true
+                },
+                "pify": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+                    "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+                    "dev": true
+                },
+                "pkg-dir": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+                    "integrity": "sha512-ojakdnUgL5pzJYWw2AIDEupaQCX5OPbM688ZevubICjdIX01PRSYKqm33fJoCOJBRseYCTUlQRnBNX+Pchaejw==",
+                    "dev": true,
+                    "requires": {
+                        "find-up": "^2.1.0"
+                    }
+                }
             }
         },
         "find-in-files": {
@@ -7417,9 +6729,9 @@
             }
         },
         "find-parent-dir": {
-            "version": "0.3.0",
-            "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz",
-            "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ="
+            "version": "0.3.1",
+            "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.1.tgz",
+            "integrity": "sha512-o4UcykWV/XN9wm+jMEtWLPlV8RXCZnMhQI6F6OdHeSez7iiJWePw8ijOlskJZMsaQoGR/b7dH6lO02HhaTN7+A=="
         },
         "find-root": {
             "version": "1.1.0",
@@ -7440,9 +6752,9 @@
             "integrity": "sha512-Md3b3ReA/qJwwYvKXeHpOV1fhPqwhJ9/29zc9lfi8ijyg00J0S9C7+5XMZDFhlDAKbwOvVgBxVIG1EHoMSC3vw=="
         },
         "flat": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz",
-            "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==",
+            "version": "4.1.1",
+            "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz",
+            "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==",
             "requires": {
                 "is-buffer": "~2.0.3"
             }
@@ -7455,7 +6767,7 @@
         "fluent-ffmpeg": {
             "version": "2.1.2",
             "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz",
-            "integrity": "sha1-yVLeIkD4EuvaCqgAbXd27irPfXQ=",
+            "integrity": "sha512-IZTB4kq5GK0DPp7sGQ0q/BWurGHffRtQQwVkiqDgeO6wYJLLV5ZhgNOQ65loZxxuPMKZKZcICCUnaGtlxBiR0Q==",
             "requires": {
                 "async": ">=0.2.9",
                 "which": "^1.1.1"
@@ -7489,14 +6801,40 @@
             }
         },
         "follow-redirects": {
-            "version": "1.12.1",
-            "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.12.1.tgz",
-            "integrity": "sha512-tmRv0AVuR7ZyouUHLeNSiO6pqulF7dYa3s19c6t+wz9LD69/uSzdMxJ2S91nTI9U3rt/IldxpzMOFejp6f0hjg=="
+            "version": "1.5.10",
+            "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
+            "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
+            "requires": {
+                "debug": "=3.1.0"
+            },
+            "dependencies": {
+                "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"
+                    }
+                },
+                "ms": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+                }
+            }
+        },
+        "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"
+            }
         },
         "for-each-property": {
             "version": "0.0.4",
             "resolved": "https://registry.npmjs.org/for-each-property/-/for-each-property-0.0.4.tgz",
-            "integrity": "sha1-z6hXrsFCLh0Sb/CHhPz2Jim8g/Y=",
+            "integrity": "sha512-xYs28PM0CKXETFzuGC6ZooH0voZlsSDZwidJcy92flQJi3PK7i3gZx23xHXCPOaD4zmet3bDo+wS7E7SujrlCw==",
             "requires": {
                 "get-prototype-chain": "^1.0.1"
             }
@@ -7504,7 +6842,7 @@
         "for-each-property-deep": {
             "version": "0.0.3",
             "resolved": "https://registry.npmjs.org/for-each-property-deep/-/for-each-property-deep-0.0.3.tgz",
-            "integrity": "sha1-MTCaSvw4qcygbxsiP1PWSm0IP60=",
+            "integrity": "sha512-qzP8QkODWVVRPpWiBZacSbBl67cTTWoBfxMG0wE46AsS1yl7qv05sGN+dHvD4s4tnvl/goe6Sp4qBI+rlVBgNg==",
             "requires": {
                 "for-each-property": "0.0.4"
             }
@@ -7512,17 +6850,12 @@
         "for-in": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
-            "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
-        },
-        "foreach": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
-            "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
+            "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ=="
         },
         "forever-agent": {
             "version": "0.6.1",
             "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
-            "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+            "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw=="
         },
         "fork-ts-checker-webpack-plugin": {
             "version": "1.6.0",
@@ -7538,13 +6871,20 @@
                 "semver": "^5.6.0",
                 "tapable": "^1.0.0",
                 "worker-rpc": "^0.1.0"
+            },
+            "dependencies": {
+                "tapable": {
+                    "version": "1.1.3",
+                    "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+                    "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
+                    "dev": true
+                }
             }
         },
         "form-data": {
-            "version": "2.5.1",
-            "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
-            "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
-            "dev": true,
+            "version": "2.3.3",
+            "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+            "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
             "requires": {
                 "asynckit": "^0.4.0",
                 "combined-stream": "^1.0.6",
@@ -7569,7 +6909,7 @@
         "fragment-cache": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
-            "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+            "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==",
             "requires": {
                 "map-cache": "^0.2.2"
             }
@@ -7577,12 +6917,12 @@
         "fresh": {
             "version": "0.5.2",
             "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
-            "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+            "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
         },
         "from2": {
             "version": "2.3.0",
             "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
-            "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+            "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==",
             "dev": true,
             "requires": {
                 "inherits": "^2.0.1",
@@ -7606,10 +6946,40 @@
                 }
             }
         },
-        "fs-constants": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
-            "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
+        "fs-constants": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+            "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
+        },
+        "fs-extra": {
+            "version": "0.26.7",
+            "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz",
+            "integrity": "sha512-waKu+1KumRhYv8D8gMRCKJGAMI9pRnPuEb1mvgYD0f7wBscg+h6bW4FDTmEZhB9VKxvoTtxW+Y7bnIlB7zja6Q==",
+            "requires": {
+                "graceful-fs": "^4.1.2",
+                "jsonfile": "^2.1.0",
+                "klaw": "^1.0.0",
+                "path-is-absolute": "^1.0.0",
+                "rimraf": "^2.2.8"
+            },
+            "dependencies": {
+                "rimraf": {
+                    "version": "2.7.1",
+                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+                    "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+                    "requires": {
+                        "glob": "^7.1.3"
+                    }
+                }
+            }
+        },
+        "fs-minipass": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+            "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+            "requires": {
+                "minipass": "^3.0.0"
+            }
         },
         "fs-monkey": {
             "version": "1.0.3",
@@ -7619,7 +6989,7 @@
         "fs-write-stream-atomic": {
             "version": "1.0.10",
             "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
-            "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+            "integrity": "sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==",
             "dev": true,
             "requires": {
                 "graceful-fs": "^4.1.2",
@@ -7648,14 +7018,17 @@
         "fs.realpath": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-            "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+            "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==",
-            "dev": true,
-            "optional": true
+            "version": "1.2.13",
+            "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+            "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+            "optional": true,
+            "requires": {
+                "bindings": "^1.5.0",
+                "nan": "^2.12.1"
+            }
         },
         "fstream": {
             "version": "1.0.12",
@@ -7701,50 +7074,69 @@
                 "interval-arithmetic-eval": "^0.4.7"
             }
         },
+        "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=="
+        },
         "gauge": {
-            "version": "2.7.4",
-            "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
-            "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
+            "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
             "requires": {
-                "aproba": "^1.0.3",
+                "aproba": "^1.0.3 || ^2.0.0",
+                "color-support": "^1.1.2",
                 "console-control-strings": "^1.0.0",
-                "has-unicode": "^2.0.0",
-                "object-assign": "^4.1.0",
+                "has-unicode": "^2.0.1",
+                "object-assign": "^4.1.1",
                 "signal-exit": "^3.0.0",
-                "string-width": "^1.0.1",
-                "strip-ansi": "^3.0.1",
-                "wide-align": "^1.1.0"
+                "string-width": "^4.2.3",
+                "strip-ansi": "^6.0.1",
+                "wide-align": "^1.1.2"
             },
             "dependencies": {
                 "ansi-regex": {
-                    "version": "2.1.1",
-                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+                    "version": "5.0.1",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+                    "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+                },
+                "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=="
                 },
                 "is-fullwidth-code-point": {
-                    "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
-                    "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
-                    "requires": {
-                        "number-is-nan": "^1.0.0"
-                    }
+                    "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=="
                 },
                 "string-width": {
-                    "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
-                    "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+                    "version": "4.2.3",
+                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+                    "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
                     "requires": {
-                        "code-point-at": "^1.0.0",
-                        "is-fullwidth-code-point": "^1.0.0",
-                        "strip-ansi": "^3.0.0"
+                        "emoji-regex": "^8.0.0",
+                        "is-fullwidth-code-point": "^3.0.0",
+                        "strip-ansi": "^6.0.1"
                     }
                 },
                 "strip-ansi": {
-                    "version": "3.0.1",
-                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-                    "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+                    "version": "6.0.1",
+                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+                    "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
                     "requires": {
-                        "ansi-regex": "^2.0.0"
+                        "ansi-regex": "^5.0.1"
                     }
                 }
             }
@@ -7762,14 +7154,17 @@
             },
             "dependencies": {
                 "is-stream": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
-                    "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw=="
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+                    "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="
                 },
                 "node-fetch": {
-                    "version": "2.6.0",
-                    "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
-                    "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
+                    "version": "2.6.7",
+                    "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+                    "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+                    "requires": {
+                        "whatwg-url": "^5.0.0"
+                    }
                 }
             }
         },
@@ -7798,7 +7193,7 @@
         "get-func-name": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
-            "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE="
+            "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig=="
         },
         "get-intrinsic": {
             "version": "1.1.1",
@@ -7818,17 +7213,17 @@
         "get-prototype-chain": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/get-prototype-chain/-/get-prototype-chain-1.0.1.tgz",
-            "integrity": "sha1-oXGhFeoeSQbG7ThDofABwYUQQW8="
+            "integrity": "sha512-2m7WZ0jveIg/dAbCbpUxEToaJ8Dmti5EkgDP8YM3UpHUT6SAORjE2odP8XQGNVGXMHi8q8cCCoy3HTByTaTVTw=="
         },
         "get-stdin": {
             "version": "5.0.1",
             "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz",
-            "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="
+            "integrity": "sha512-jZV7n6jGE3Gt7fgSTJoz91Ak5MuTLwMwkoYdjxuJ/AmjIsE1UC03y/IWkZCQGEvVNS9qoRNwy5BCqxImv0FVeA=="
         },
         "get-stream": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
-            "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+            "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="
         },
         "get-symbol-description": {
             "version": "1.0.0",
@@ -7842,12 +7237,12 @@
         "get-value": {
             "version": "2.0.6",
             "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
-            "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
+            "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA=="
         },
         "getpass": {
             "version": "0.1.7",
             "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
-            "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+            "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
             "requires": {
                 "assert-plus": "^1.0.0"
             }
@@ -7855,17 +7250,17 @@
         "github-from-package": {
             "version": "0.0.0",
             "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
-            "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4="
+            "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
         },
         "glob": {
-            "version": "7.1.6",
-            "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
-            "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+            "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.0.4",
+                "minimatch": "^3.1.1",
                 "once": "^1.3.0",
                 "path-is-absolute": "^1.0.0"
             }
@@ -7873,7 +7268,7 @@
         "glob-parent": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
-            "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+            "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==",
             "requires": {
                 "is-glob": "^3.1.0",
                 "path-dirname": "^1.0.0"
@@ -7882,7 +7277,7 @@
                 "is-glob": {
                     "version": "3.1.0",
                     "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
-                    "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+                    "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==",
                     "requires": {
                         "is-extglob": "^2.1.0"
                     }
@@ -7898,7 +7293,7 @@
         "global-dirs": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
-            "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=",
+            "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==",
             "requires": {
                 "ini": "^1.3.4"
             }
@@ -7911,7 +7306,7 @@
         "globby": {
             "version": "7.1.1",
             "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
-            "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
+            "integrity": "sha512-yANWAN2DUcBtuus5Cpd+SKROzXHs2iVXFZt/Ykrfz6SAXqacLX25NZpltE+39ceMexYF4TtEadjuSTw8+3wX4g==",
             "dev": true,
             "requires": {
                 "array-union": "^1.0.1",
@@ -7925,25 +7320,48 @@
                 "pify": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-                    "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+                    "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
                     "dev": true
                 }
             }
         },
         "globule": {
-            "version": "1.3.1",
-            "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.1.tgz",
-            "integrity": "sha512-OVyWOHgw29yosRHCHo7NncwR1hW5ew0W/UrvtwvjefVJeQ26q4/8r8FmPsSF1hJ93IgWkyv16pCTz6WblMzm/g==",
+            "version": "1.3.3",
+            "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.3.tgz",
+            "integrity": "sha512-mb1aYtDbIjTu4ShMB85m3UzjX9BVKe9WCzsnfMSZk+K5GpIbBOexgg4PPCt5eHDEG5/ZQAUX2Kct02zfiPLsKg==",
             "requires": {
                 "glob": "~7.1.1",
-                "lodash": "~4.17.12",
+                "lodash": "~4.17.10",
                 "minimatch": "~3.0.2"
+            },
+            "dependencies": {
+                "glob": {
+                    "version": "7.1.7",
+                    "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+                    "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+                    "requires": {
+                        "fs.realpath": "^1.0.0",
+                        "inflight": "^1.0.4",
+                        "inherits": "2",
+                        "minimatch": "^3.0.4",
+                        "once": "^1.3.0",
+                        "path-is-absolute": "^1.0.0"
+                    }
+                },
+                "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"
+                    }
+                }
             }
         },
         "golden-layout": {
             "version": "1.5.9",
             "resolved": "https://registry.npmjs.org/golden-layout/-/golden-layout-1.5.9.tgz",
-            "integrity": "sha1-o5vB9qZ+b4hreXwBbdkk6UJrp38=",
+            "integrity": "sha512-iBXDQCXOTgUEQJo96zPbjDoy5bRIk9XW5l+q+pDgLnIyReqaa1aiQctNud4epsskyLt952BG521dew5Z1liSxA==",
             "requires": {
                 "jquery": "*"
             }
@@ -7951,7 +7369,7 @@
         "good-listener": {
             "version": "1.2.2",
             "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
-            "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
+            "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
             "requires": {
                 "delegate": "^3.1.2"
             }
@@ -7969,6 +7387,21 @@
                 "gtoken": "^3.0.0",
                 "jws": "^3.1.5",
                 "lru-cache": "^5.0.0"
+            },
+            "dependencies": {
+                "lru-cache": {
+                    "version": "5.1.1",
+                    "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+                    "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+                    "requires": {
+                        "yallist": "^3.0.2"
+                    }
+                },
+                "yallist": {
+                    "version": "3.1.1",
+                    "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+                    "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+                }
             }
         },
         "google-maps-react": {
@@ -7977,11 +7410,11 @@
             "integrity": "sha512-M8Eo9WndfQEfxcmm6yRq03qdJgw1x6rQmJ9DN+a+xPQ3K7yNDGkVDbinrf4/8vcox7nELbeopbm4bpefKewWfQ=="
         },
         "google-p12-pem": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.4.tgz",
-            "integrity": "sha512-S4blHBQWZRnEW44OcR7TL9WR+QCqByRvhNDZ/uuQfpxywfupikf/miba8js1jZi6ZOGv5slgSuoshCWh6EMDzg==",
+            "version": "2.0.5",
+            "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.5.tgz",
+            "integrity": "sha512-7RLkxwSsMsYh9wQ5Vb2zRtkAHvqPvfoMGag+nugl1noYO7gf0844Yr9TIFA5NEBMAeVt2Z+Imu7CQMp3oNatzQ==",
             "requires": {
-                "node-forge": "^0.9.0"
+                "node-forge": "^0.10.0"
             }
         },
         "googleapis": {
@@ -8007,9 +7440,12 @@
             },
             "dependencies": {
                 "qs": {
-                    "version": "6.9.3",
-                    "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz",
-                    "integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw=="
+                    "version": "6.10.3",
+                    "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
+                    "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
+                    "requires": {
+                        "side-channel": "^1.0.4"
+                    }
                 }
             }
         },
@@ -8024,11 +7460,11 @@
             }
         },
         "got": {
-            "version": "12.0.1",
-            "resolved": "https://registry.npmjs.org/got/-/got-12.0.1.tgz",
-            "integrity": "sha512-1Zhoh+lDej3t7Ks1BP/Jufn+rNqdiHQgUOcTxHzg2Dao1LQfp5S4Iq0T3iBxN4Zdo7QqCJL+WJUNzDX6rCP2Ew==",
+            "version": "12.1.0",
+            "resolved": "https://registry.npmjs.org/got/-/got-12.1.0.tgz",
+            "integrity": "sha512-hBv2ty9QN2RdbJJMK3hesmSkFTjVIHyIDDbssCKnSmq62edGgImJWD10Eb1k77TiV1bxloxqcFAVK8+9pkhOig==",
             "requires": {
-                "@sindresorhus/is": "^4.2.0",
+                "@sindresorhus/is": "^4.6.0",
                 "@szmarczak/http-timer": "^5.0.1",
                 "@types/cacheable-request": "^6.0.2",
                 "@types/responselike": "^1.0.0",
@@ -8037,7 +7473,7 @@
                 "decompress-response": "^6.0.0",
                 "form-data-encoder": "1.7.1",
                 "get-stream": "^6.0.1",
-                "http2-wrapper": "^2.1.9",
+                "http2-wrapper": "^2.1.10",
                 "lowercase-keys": "^3.0.0",
                 "p-cancelable": "^3.0.0",
                 "responselike": "^2.0.0"
@@ -8051,11 +7487,6 @@
                         "mimic-response": "^3.1.0"
                     }
                 },
-                "get-stream": {
-                    "version": "6.0.1",
-                    "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
-                    "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="
-                },
                 "mimic-response": {
                     "version": "3.1.0",
                     "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
@@ -8064,9 +7495,9 @@
             }
         },
         "graceful-fs": {
-            "version": "4.2.4",
-            "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
-            "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
+            "version": "4.2.10",
+            "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+            "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
         },
         "growl": {
             "version": "1.10.5",
@@ -8085,9 +7516,9 @@
             },
             "dependencies": {
                 "mime": {
-                    "version": "2.4.4",
-                    "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
-                    "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
+                    "version": "2.6.0",
+                    "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+                    "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg=="
                 }
             }
         },
@@ -8105,7 +7536,7 @@
         "har-schema": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
-            "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
+            "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q=="
         },
         "har-validator": {
             "version": "5.1.5",
@@ -8114,19 +7545,6 @@
             "requires": {
                 "ajv": "^6.12.3",
                 "har-schema": "^2.0.0"
-            },
-            "dependencies": {
-                "ajv": {
-                    "version": "6.12.6",
-                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
-                    "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
-                    "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"
-                    }
-                }
             }
         },
         "has": {
@@ -8140,7 +7558,7 @@
         "has-ansi": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
-            "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+            "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==",
             "requires": {
                 "ansi-regex": "^2.0.0"
             },
@@ -8148,14 +7566,14 @@
                 "ansi-regex": {
                     "version": "2.1.1",
                     "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+                    "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="
                 }
             }
         },
         "has-bigints": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
-            "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA=="
+            "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-binary2": {
             "version": "1.0.3",
@@ -8168,24 +7586,32 @@
                 "isarray": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
-                    "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
+                    "integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ=="
                 }
             }
         },
         "has-cors": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
-            "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk="
+            "integrity": "sha512-g5VNKdkFuUuVCP9gYfDJHjK2nqdQJ7aDLTnycnc2+RvsOQbuLdF5pm7vuE5J76SEBIQjs4kQY/BWq74JUmjbXA=="
         },
         "has-flag": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-            "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+            "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="
+        },
+        "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.1",
-            "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
-            "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
+            "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",
@@ -8193,24 +7619,17 @@
             "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
             "requires": {
                 "has-symbols": "^1.0.2"
-            },
-            "dependencies": {
-                "has-symbols": {
-                    "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
-                    "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
-                }
             }
         },
         "has-unicode": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
-            "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
+            "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
         },
         "has-value": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
-            "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+            "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==",
             "requires": {
                 "get-value": "^2.0.6",
                 "has-values": "^1.0.0",
@@ -8220,7 +7639,7 @@
         "has-values": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
-            "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+            "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==",
             "requires": {
                 "is-number": "^3.0.0",
                 "kind-of": "^4.0.0"
@@ -8234,7 +7653,7 @@
                 "kind-of": {
                     "version": "4.0.0",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
-                    "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+                    "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -8255,9 +7674,9 @@
             }
         },
         "hosted-git-info": {
-            "version": "2.8.8",
-            "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
-            "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg=="
+            "version": "2.8.9",
+            "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+            "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="
         },
         "howler": {
             "version": "2.2.3",
@@ -8267,7 +7686,7 @@
         "hpack.js": {
             "version": "2.1.6",
             "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
-            "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
+            "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==",
             "dev": true,
             "requires": {
                 "inherits": "^2.0.1",
@@ -8296,7 +7715,7 @@
         "html": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/html/-/html-1.0.0.tgz",
-            "integrity": "sha1-pUT6nqVJK/s6LMqCEKEL57WvH2E=",
+            "integrity": "sha512-lw/7YsdKiP3kk5PnR1INY17iJuzdAtJewxr14ozKJWbbR97znovZ0mh+WEMZ8rjc3lgTK+ID/htTjuyGKB52Kw==",
             "requires": {
                 "concat-stream": "^1.4.7"
             }
@@ -8328,26 +7747,6 @@
                 "param-case": "^3.0.4",
                 "relateurl": "^0.2.7",
                 "terser": "^5.10.0"
-            },
-            "dependencies": {
-                "clean-css": {
-                    "version": "5.2.4",
-                    "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz",
-                    "integrity": "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==",
-                    "requires": {
-                        "source-map": "~0.6.0"
-                    }
-                },
-                "commander": {
-                    "version": "8.3.0",
-                    "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
-                    "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="
-                },
-                "source-map": {
-                    "version": "0.6.1",
-                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-                    "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
-                }
             }
         },
         "html-to-image": {
@@ -8376,13 +7775,6 @@
                 "lodash": "^4.17.21",
                 "pretty-error": "^4.0.0",
                 "tapable": "^2.0.0"
-            },
-            "dependencies": {
-                "tapable": {
-                    "version": "2.2.1",
-                    "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
-                    "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="
-                }
             }
         },
         "htmlparser2": {
@@ -8401,7 +7793,7 @@
         "http-browserify": {
             "version": "1.7.0",
             "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz",
-            "integrity": "sha1-M3la3nLfiKz7/TZ3PO/tp2RzWyA=",
+            "integrity": "sha512-Irf/LJXmE3cBzU1eaR4+NEX6bmVLqt1wkmDiA7kBwH7zmb0D8kBAXsDmQ88hhj/qv9iEZKlyGx/hrMcFi8sOHw==",
             "requires": {
                 "Base64": "~0.2.0",
                 "inherits": "~2.0.1"
@@ -8415,25 +7807,25 @@
         "http-deceiver": {
             "version": "1.2.7",
             "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
-            "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
+            "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==",
             "dev": true
         },
         "http-errors": {
-            "version": "1.8.1",
-            "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
-            "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+            "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
             "requires": {
-                "depd": "~1.1.2",
+                "depd": "2.0.0",
                 "inherits": "2.0.4",
                 "setprototypeof": "1.2.0",
-                "statuses": ">= 1.5.0 < 2",
+                "statuses": "2.0.1",
                 "toidentifier": "1.0.1"
             }
         },
         "http-parser-js": {
-            "version": "0.5.5",
-            "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz",
-            "integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==",
+            "version": "0.5.6",
+            "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz",
+            "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==",
             "dev": true
         },
         "http-proxy": {
@@ -8462,7 +7854,7 @@
         "http-signature": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
-            "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+            "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
             "requires": {
                 "assert-plus": "^1.0.0",
                 "jsprim": "^1.2.2",
@@ -8470,9 +7862,9 @@
             }
         },
         "http2-wrapper": {
-            "version": "2.1.10",
-            "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.1.10.tgz",
-            "integrity": "sha512-QHgsdYkieKp+6JbXP25P+tepqiHYd+FVnDwXpxi/BlUcoIB0nsmTOymTNvETuTO+pDuwcSklPE72VR3DqV+Haw==",
+            "version": "2.1.11",
+            "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.1.11.tgz",
+            "integrity": "sha512-aNAk5JzLturWEUiuhAN73Jcbq96R7rTitAoXV54FYMatvihnpD2+6PUgU4ce3D/m5VDbw+F5CsyKSF176ptitQ==",
             "requires": {
                 "quick-lru": "^5.1.1",
                 "resolve-alpn": "^1.2.0"
@@ -8481,29 +7873,34 @@
         "https": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/https/-/https-1.0.0.tgz",
-            "integrity": "sha1-PDfHrhqO65ZpBKKtHpdaGUt+06Q="
+            "integrity": "sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg=="
         },
         "https-browserify": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
-            "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
+            "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg=="
         },
         "https-proxy-agent": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
-            "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+            "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
             "requires": {
                 "agent-base": "6",
                 "debug": "4"
             },
             "dependencies": {
                 "debug": {
-                    "version": "4.1.1",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+                    "version": "4.3.4",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+                    "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
                     "requires": {
-                        "ms": "^2.1.1"
+                        "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=="
                 }
             }
         },
@@ -8518,9 +7915,9 @@
             "integrity": "sha512-xjxyDLbVDdLgjPnl4NM+Iu6il3UPmk6PNCBXruQKeuKDc/HtaZx1hk1AtMgw3vsn9YnLZRfoBpPxYMXcoT5KAA=="
         },
         "hyphenate-style-name": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz",
-            "integrity": "sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ=="
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
+            "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
         },
         "i": {
             "version": "0.3.7",
@@ -8528,17 +7925,17 @@
             "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q=="
         },
         "iconv-lite": {
-            "version": "0.4.24",
-            "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
-            "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+            "version": "0.6.3",
+            "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+            "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
             "requires": {
-                "safer-buffer": ">= 2.1.2 < 3"
+                "safer-buffer": ">= 2.1.2 < 3.0.0"
             }
         },
         "icss-replace-symbols": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz",
-            "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=",
+            "integrity": "sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==",
             "dev": true
         },
         "icss-utils": {
@@ -8551,14 +7948,14 @@
             }
         },
         "ieee754": {
-            "version": "1.1.13",
-            "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
-            "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
+            "version": "1.2.1",
+            "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+            "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
         },
         "iferr": {
             "version": "0.1.5",
             "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
-            "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
+            "integrity": "sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==",
             "dev": true
         },
         "ignore": {
@@ -8570,7 +7967,7 @@
         "ignore-by-default": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
-            "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk="
+            "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA=="
         },
         "iink-js": {
             "version": "1.5.4",
@@ -8604,36 +8001,6 @@
                 "magicli": "0.0.8",
                 "mime-types": "^2.1.18",
                 "request": "^2.88.0"
-            },
-            "dependencies": {
-                "fs-extra": {
-                    "version": "0.26.7",
-                    "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz",
-                    "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=",
-                    "requires": {
-                        "graceful-fs": "^4.1.2",
-                        "jsonfile": "^2.1.0",
-                        "klaw": "^1.0.0",
-                        "path-is-absolute": "^1.0.0",
-                        "rimraf": "^2.2.8"
-                    }
-                },
-                "jsonfile": {
-                    "version": "2.4.0",
-                    "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
-                    "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
-                    "requires": {
-                        "graceful-fs": "^4.1.6"
-                    }
-                },
-                "rimraf": {
-                    "version": "2.7.1",
-                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-                    "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-                    "requires": {
-                        "glob": "^7.1.3"
-                    }
-                }
             }
         },
         "image-size": {
@@ -8644,21 +8011,20 @@
         "image-size-stream": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/image-size-stream/-/image-size-stream-1.1.0.tgz",
-            "integrity": "sha1-Ivou2mbG31AQh0bacUkmSy0l+Gs=",
+            "integrity": "sha512-N505B5FSy2Xf5l/Haef+99TwfJqTu40hnU560+rC0Cm6cxtwVz2yRFh9WpOk1YEjfv3dI0PgVYAH0hmXQmjDcw==",
             "requires": {
-                "image-size": "github:netroy/image-size#da2c863807a3e9602617bdd357b0de3ab4a064c1",
                 "readable-stream": "^1.0.33",
                 "tryit": "^1.0.1"
             },
             "dependencies": {
                 "image-size": {
-                    "version": "github:netroy/image-size#da2c863807a3e9602617bdd357b0de3ab4a064c1",
-                    "from": "github:netroy/image-size#da2c863807a3e9602617bdd357b0de3ab4a064c1"
+                    "version": "git+https://github.com/netroy/image-size.git#da2c863807a3e9602617bdd357b0de3ab4a064c1",
+                    "from": "git+https://github.com/netroy/image-size.git#da2c863807a3e9602617bdd357b0de3ab4a064c1"
                 },
                 "isarray": {
                     "version": "0.0.1",
                     "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
-                    "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+                    "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
                 },
                 "readable-stream": {
                     "version": "1.1.14",
@@ -8681,7 +8047,7 @@
         "immediate": {
             "version": "3.0.6",
             "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
-            "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
+            "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
         },
         "import-fresh": {
             "version": "3.3.0",
@@ -8695,33 +8061,21 @@
         "import-lazy": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
-            "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM="
+            "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A=="
         },
         "import-local": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
-            "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
-            "dev": true,
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+            "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
             "requires": {
-                "pkg-dir": "^3.0.0",
-                "resolve-cwd": "^2.0.0"
-            },
-            "dependencies": {
-                "pkg-dir": {
-                    "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
-                    "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
-                    "dev": true,
-                    "requires": {
-                        "find-up": "^3.0.0"
-                    }
-                }
+                "pkg-dir": "^4.2.0",
+                "resolve-cwd": "^3.0.0"
             }
         },
         "imurmurhash": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-            "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
+            "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="
         },
         "in-publish": {
             "version": "2.0.1",
@@ -8731,26 +8085,20 @@
         "indent-string": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
-            "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+            "integrity": "sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==",
             "requires": {
                 "repeating": "^2.0.0"
             }
         },
-        "indexes-of": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz",
-            "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=",
-            "dev": true
-        },
         "indexof": {
             "version": "0.0.1",
             "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
-            "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
+            "integrity": "sha512-i0G7hLJ1z0DE8dsqJa2rycj9dBmNKgXBvotXtZYXakU9oivfB9Uj2ZBC27qqef2U58/ZLwalxa1X/RDCdkHtVg=="
         },
         "inflight": {
             "version": "1.0.6",
             "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-            "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+            "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
             "requires": {
                 "once": "^1.3.0",
                 "wrappy": "1"
@@ -8767,7 +8115,7 @@
                 "camelcase": {
                     "version": "4.1.0",
                     "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-                    "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
+                    "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw=="
                 }
             }
         },
@@ -8777,14 +8125,14 @@
             "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
         },
         "ini": {
-            "version": "1.3.5",
-            "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
-            "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
+            "version": "1.3.8",
+            "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+            "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
         },
         "inline-style-prefixer": {
             "version": "3.0.8",
             "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-3.0.8.tgz",
-            "integrity": "sha1-hVG45bTVcyROZqNLBPfTIHaitTQ=",
+            "integrity": "sha512-ne8XIyyqkRaNJ1JfL1NYzNdCNxq+MCBQhC8NgOQlzNm2vv3XxlP0VSLQUbSRCF6KPEoveCVEpayHoHzcMyZsMQ==",
             "requires": {
                 "bowser": "^1.7.3",
                 "css-in-js-utils": "^2.0.0"
@@ -8793,7 +8141,7 @@
         "inspect-function": {
             "version": "0.2.2",
             "resolved": "https://registry.npmjs.org/inspect-function/-/inspect-function-0.2.2.tgz",
-            "integrity": "sha1-hdoMUli8TDMK4yg7Z0fgdZ2QpjU=",
+            "integrity": "sha512-becs5gzcHwPrlHawscYkyQ/ShiOiosrXPhA5RVZ3qyWH4aWdD52RnMfXq/dwQXciHwiieD8aIPwdIWYv6eL+sQ==",
             "requires": {
                 "split-skip": "0.0.1",
                 "unpack-string": "0.0.2"
@@ -8817,10 +8165,15 @@
                 "unpack-string": "0.0.2"
             },
             "dependencies": {
+                "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=="
+                },
                 "magicli": {
                     "version": "0.0.5",
                     "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
-                    "integrity": "sha1-zufQ+7THBRiqyxHsPrfiX/SaSSE=",
+                    "integrity": "sha512-wZbMtnl2v1b+Jp3xlqA9FU/O4I6YhGXR8xSY/eU2+gDAvut/F+W3gl4qs61iL4LELC7jqSAE6aAD5668EbmQHA==",
                     "requires": {
                         "commander": "^2.9.0",
                         "get-stdin": "^5.0.1",
@@ -8840,6 +8193,11 @@
                 "inspect-function": "^0.3.1"
             },
             "dependencies": {
+                "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=="
+                },
                 "inspect-function": {
                     "version": "0.3.4",
                     "resolved": "https://registry.npmjs.org/inspect-function/-/inspect-function-0.3.4.tgz",
@@ -8866,7 +8224,7 @@
                         "inspect-function": {
                             "version": "0.2.2",
                             "resolved": "https://registry.npmjs.org/inspect-function/-/inspect-function-0.2.2.tgz",
-                            "integrity": "sha1-hdoMUli8TDMK4yg7Z0fgdZ2QpjU=",
+                            "integrity": "sha512-becs5gzcHwPrlHawscYkyQ/ShiOiosrXPhA5RVZ3qyWH4aWdD52RnMfXq/dwQXciHwiieD8aIPwdIWYv6eL+sQ==",
                             "requires": {
                                 "split-skip": "0.0.1",
                                 "unpack-string": "0.0.2"
@@ -8882,7 +8240,7 @@
                         "magicli": {
                             "version": "0.0.5",
                             "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
-                            "integrity": "sha1-zufQ+7THBRiqyxHsPrfiX/SaSSE=",
+                            "integrity": "sha512-wZbMtnl2v1b+Jp3xlqA9FU/O4I6YhGXR8xSY/eU2+gDAvut/F+W3gl4qs61iL4LELC7jqSAE6aAD5668EbmQHA==",
                             "requires": {
                                 "commander": "^2.9.0",
                                 "get-stdin": "^5.0.1",
@@ -8963,15 +8321,15 @@
             }
         },
         "ip": {
-            "version": "1.1.5",
-            "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
-            "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
+            "version": "1.1.8",
+            "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz",
+            "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==",
             "dev": true
         },
         "ip-regex": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
-            "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=",
+            "integrity": "sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==",
             "dev": true
         },
         "ipaddr.js": {
@@ -8988,7 +8346,7 @@
         "is-accessor-descriptor": {
             "version": "0.1.6",
             "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-            "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+            "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==",
             "requires": {
                 "kind-of": "^3.0.2"
             },
@@ -9001,7 +8359,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -9020,7 +8378,7 @@
         "is-arrayish": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
-            "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
+            "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
         },
         "is-bigint": {
             "version": "1.0.4",
@@ -9033,7 +8391,7 @@
         "is-binary-path": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
-            "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+            "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==",
             "requires": {
                 "binary-extensions": "^1.0.0"
             }
@@ -9048,14 +8406,14 @@
             }
         },
         "is-buffer": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
-            "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A=="
+            "version": "2.0.5",
+            "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
+            "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ=="
         },
         "is-callable": {
-            "version": "1.1.5",
-            "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
-            "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q=="
+            "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-ci": {
             "version": "1.2.1",
@@ -9065,10 +8423,18 @@
                 "ci-info": "^1.5.0"
             }
         },
+        "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-data-descriptor": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-            "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+            "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==",
             "requires": {
                 "kind-of": "^3.0.2"
             },
@@ -9081,7 +8447,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -9089,9 +8455,12 @@
             }
         },
         "is-date-object": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
-            "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g=="
+            "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-descriptor": {
             "version": "0.1.6",
@@ -9113,12 +8482,12 @@
         "is-directory": {
             "version": "0.3.1",
             "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
-            "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
+            "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw=="
         },
         "is-expression": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz",
-            "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=",
+            "integrity": "sha512-vyMeQMq+AiH5uUnoBfMTwf18tO3bM6k1QXBE9D6ueAAquEfCZe3AJPtud9g6qS0+4X8xA7ndpZiDyeb2l2qOBw==",
             "requires": {
                 "acorn": "~4.0.2",
                 "object-assign": "^4.0.1"
@@ -9127,22 +8496,19 @@
                 "acorn": {
                     "version": "4.0.13",
                     "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
-                    "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c="
+                    "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"
-            }
+            "version": "0.1.1",
+            "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+            "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="
         },
         "is-extglob": {
             "version": "2.1.1",
             "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-            "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
+            "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
         },
         "is-finite": {
             "version": "1.1.0",
@@ -9152,7 +8518,7 @@
         "is-fullwidth-code-point": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-            "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+            "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w=="
         },
         "is-generator-function": {
             "version": "1.0.10",
@@ -9163,9 +8529,9 @@
             }
         },
         "is-glob": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
-            "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+            "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"
             }
@@ -9173,12 +8539,12 @@
         "is-in-browser": {
             "version": "1.1.3",
             "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz",
-            "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU="
+            "integrity": "sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g=="
         },
         "is-installed-globally": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz",
-            "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=",
+            "integrity": "sha512-ERNhMg+i/XgDwPIPF3u24qpajVreaiSuvpb1Uu0jugw7KKcxGyCX8cgp8P5fwTmAuXku6beDHHECdKArjlg7tw==",
             "requires": {
                 "global-dirs": "^0.1.0",
                 "is-path-inside": "^1.0.0"
@@ -9192,12 +8558,12 @@
         "is-npm": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
-            "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ="
+            "integrity": "sha512-9r39FIr3d+KD9SbX0sfMsHzb5PP3uimOiwr3YupUaUFG4W0l1U57Rx3utpttV7qz5U3jmrO5auUa04LU9pyHsg=="
         },
         "is-number": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
-            "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+            "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==",
             "requires": {
                 "kind-of": "^3.0.2"
             },
@@ -9210,7 +8576,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -9218,9 +8584,9 @@
             }
         },
         "is-number-object": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz",
-            "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==",
+            "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"
             }
@@ -9228,7 +8594,7 @@
         "is-obj": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
-            "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
+            "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg=="
         },
         "is-path-cwd": {
             "version": "2.2.0",
@@ -9259,7 +8625,7 @@
         "is-path-inside": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
-            "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+            "integrity": "sha512-qhsCR/Esx4U4hg/9I19OVUAJkGWtjRYHMRgUMZE2TDdj+Ag+kttZanLupfddNyglzz50cUlmWzUaI37GDfNx/g==",
             "requires": {
                 "path-is-inside": "^1.0.1"
             }
@@ -9280,14 +8646,15 @@
         "is-redirect": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
-            "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ="
+            "integrity": "sha512-cr/SlUEe5zOGmzvj9bUyC4LVvkNVAXu4GytXLNMr1pny+a65MpQ9IJzFHD5vi7FyJgb4qt27+eS3TuQnqB+RQw=="
         },
         "is-regex": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
-            "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+            "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
             "requires": {
-                "has": "^1.0.3"
+                "call-bind": "^1.0.2",
+                "has-tostringtag": "^1.0.0"
             }
         },
         "is-retry-allowed": {
@@ -9304,14 +8671,17 @@
             }
         },
         "is-shared-array-buffer": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz",
-            "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA=="
+            "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-stream": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
-            "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
+            "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="
         },
         "is-string": {
             "version": "1.0.7",
@@ -9322,116 +8692,34 @@
             }
         },
         "is-symbol": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
-            "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
+            "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.1"
+                "has-symbols": "^1.0.2"
             }
         },
         "is-typed-array": {
-            "version": "1.1.8",
-            "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz",
-            "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==",
+            "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.18.5",
-                "foreach": "^2.0.5",
+                "es-abstract": "^1.20.0",
+                "for-each": "^0.3.3",
                 "has-tostringtag": "^1.0.0"
-            },
-            "dependencies": {
-                "es-abstract": {
-                    "version": "1.19.1",
-                    "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz",
-                    "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==",
-                    "requires": {
-                        "call-bind": "^1.0.2",
-                        "es-to-primitive": "^1.2.1",
-                        "function-bind": "^1.1.1",
-                        "get-intrinsic": "^1.1.1",
-                        "get-symbol-description": "^1.0.0",
-                        "has": "^1.0.3",
-                        "has-symbols": "^1.0.2",
-                        "internal-slot": "^1.0.3",
-                        "is-callable": "^1.2.4",
-                        "is-negative-zero": "^2.0.1",
-                        "is-regex": "^1.1.4",
-                        "is-shared-array-buffer": "^1.0.1",
-                        "is-string": "^1.0.7",
-                        "is-weakref": "^1.0.1",
-                        "object-inspect": "^1.11.0",
-                        "object-keys": "^1.1.1",
-                        "object.assign": "^4.1.2",
-                        "string.prototype.trimend": "^1.0.4",
-                        "string.prototype.trimstart": "^1.0.4",
-                        "unbox-primitive": "^1.0.1"
-                    }
-                },
-                "has-symbols": {
-                    "version": "1.0.3",
-                    "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
-                    "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
-                },
-                "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-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"
-                    }
-                },
-                "object-inspect": {
-                    "version": "1.12.0",
-                    "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
-                    "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g=="
-                },
-                "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"
-                    }
-                },
-                "string.prototype.trimend": {
-                    "version": "1.0.4",
-                    "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
-                    "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
-                    "requires": {
-                        "call-bind": "^1.0.2",
-                        "define-properties": "^1.1.3"
-                    }
-                },
-                "string.prototype.trimstart": {
-                    "version": "1.0.4",
-                    "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
-                    "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
-                    "requires": {
-                        "call-bind": "^1.0.2",
-                        "define-properties": "^1.1.3"
-                    }
-                }
             }
         },
         "is-typedarray": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
-            "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+            "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
         },
         "is-utf8": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
-            "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI="
+            "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q=="
         },
         "is-weakref": {
             "version": "1.0.2",
@@ -9442,9 +8730,9 @@
             }
         },
         "is-what": {
-            "version": "3.10.0",
-            "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.10.0.tgz",
-            "integrity": "sha512-U4RYCXNOmATQHlOPlOCHCfXyKEFIPqvyaKDqYRuLbD6EYKcTTfc3YXkAYjzOVxO3zt34L+Wh2feIyWrYiZ7kng=="
+            "version": "3.14.1",
+            "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz",
+            "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA=="
         },
         "is-windows": {
             "version": "1.0.2",
@@ -9454,28 +8742,28 @@
         "is-wsl": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
-            "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
+            "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==",
             "dev": true
         },
         "isarray": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-            "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+            "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
         },
         "isexe": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-            "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+            "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
         },
         "isobject": {
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
-            "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+            "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="
         },
         "isomorphic-fetch": {
             "version": "2.2.1",
             "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
-            "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
+            "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==",
             "requires": {
                 "node-fetch": "^1.0.1",
                 "whatwg-fetch": ">=0.10.0"
@@ -9484,7 +8772,7 @@
         "isstream": {
             "version": "0.1.2",
             "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
-            "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+            "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
         },
         "its-set": {
             "version": "1.2.3",
@@ -9524,14 +8812,14 @@
             }
         },
         "jquery": {
-            "version": "3.5.1",
-            "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz",
-            "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg=="
+            "version": "3.6.0",
+            "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
+            "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
         },
         "js-base64": {
-            "version": "2.5.2",
-            "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.2.tgz",
-            "integrity": "sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ=="
+            "version": "2.6.4",
+            "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz",
+            "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ=="
         },
         "js-datepicker": {
             "version": "4.6.6",
@@ -9541,7 +8829,7 @@
         "js-stringify": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz",
-            "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds="
+            "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g=="
         },
         "js-tokens": {
             "version": "4.0.0",
@@ -9560,7 +8848,7 @@
         "jsbn": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
-            "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
+            "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="
         },
         "jsdom": {
             "version": "15.2.1",
@@ -9597,9 +8885,9 @@
             },
             "dependencies": {
                 "acorn": {
-                    "version": "7.1.1",
-                    "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz",
-                    "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==",
+                    "version": "7.4.1",
+                    "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+                    "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
                     "dev": true
                 },
                 "acorn-globals": {
@@ -9613,19 +8901,13 @@
                     },
                     "dependencies": {
                         "acorn": {
-                            "version": "6.4.1",
-                            "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
-                            "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
+                            "version": "6.4.2",
+                            "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
+                            "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==",
                             "dev": true
                         }
                     }
                 },
-                "parse5": {
-                    "version": "5.1.0",
-                    "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz",
-                    "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
-                    "dev": true
-                },
                 "tough-cookie": {
                     "version": "3.0.1",
                     "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz",
@@ -9636,6 +8918,32 @@
                         "psl": "^1.1.28",
                         "punycode": "^2.1.1"
                     }
+                },
+                "tr46": {
+                    "version": "1.0.1",
+                    "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
+                    "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
+                    "dev": true,
+                    "requires": {
+                        "punycode": "^2.1.0"
+                    }
+                },
+                "webidl-conversions": {
+                    "version": "4.0.2",
+                    "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
+                    "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
+                    "dev": true
+                },
+                "whatwg-url": {
+                    "version": "7.1.0",
+                    "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
+                    "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
+                    "dev": true,
+                    "requires": {
+                        "lodash.sortby": "^4.7.0",
+                        "tr46": "^1.0.1",
+                        "webidl-conversions": "^4.0.2"
+                    }
                 }
             }
         },
@@ -9645,11 +8953,11 @@
             "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="
         },
         "json-bigint": {
-            "version": "0.3.0",
-            "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.0.tgz",
-            "integrity": "sha1-DM2RLEuCcNBfBW+9E4FLU9OCWx4=",
+            "version": "0.3.1",
+            "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.1.tgz",
+            "integrity": "sha512-DGWnSzmusIreWlEupsUelHrhwmPPE+FiQvg+drKfk2p+bdEYa5mp4PJ8JsCWqae0M2jQNb0HPvnwvf1qOTThzQ==",
             "requires": {
-                "bignumber.js": "^7.0.0"
+                "bignumber.js": "^9.0.0"
             }
         },
         "json-buffer": {
@@ -9660,7 +8968,7 @@
         "json-css": {
             "version": "1.5.6",
             "resolved": "https://registry.npmjs.org/json-css/-/json-css-1.5.6.tgz",
-            "integrity": "sha1-65ZPg0ouTqobwvaY/12wB6JsfAA="
+            "integrity": "sha512-B/0T0OxZH9tSb93tXV6VOYtXqrPz/Vgz2QrCT/4NXen8HGElYkYr9V+8IrSVTMj/ftxa8cG1kcu7f3iAMlaFlQ=="
         },
         "json-parse-better-errors": {
             "version": "1.0.2",
@@ -9685,7 +8993,15 @@
         "json-stringify-safe": {
             "version": "5.0.1",
             "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
-            "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+            "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
+        },
+        "json5": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+            "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+            "requires": {
+                "minimist": "^1.2.0"
+            }
         },
         "jsondiffpatch": {
             "version": "0.4.1",
@@ -9696,10 +9012,18 @@
                 "diff-match-patch": "^1.0.0"
             }
         },
+        "jsonfile": {
+            "version": "2.4.0",
+            "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+            "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==",
+            "requires": {
+                "graceful-fs": "^4.1.6"
+            }
+        },
         "jsonschema": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.0.tgz",
-            "integrity": "sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw=="
+            "version": "1.4.1",
+            "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz",
+            "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ=="
         },
         "jsprim": {
             "version": "1.4.2",
@@ -9724,9 +9048,9 @@
             },
             "dependencies": {
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
                 }
             }
         },
@@ -9800,21 +9124,21 @@
         "jstransformer": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz",
-            "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=",
+            "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==",
             "requires": {
                 "is-promise": "^2.0.0",
                 "promise": "^7.0.1"
             }
         },
         "jszip": {
-            "version": "3.7.1",
-            "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz",
-            "integrity": "sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==",
+            "version": "3.10.0",
+            "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.0.tgz",
+            "integrity": "sha512-LDfVtOLtOxb9RXkYOwPyNBTQDL4eUbqahtoY6x07GiDJHwSYvn8sHHIw8wINImV3MqbMNve2gSuM1DDqEKk09Q==",
             "requires": {
                 "lie": "~3.3.0",
                 "pako": "~1.0.2",
                 "readable-stream": "~2.3.6",
-                "set-immediate-shim": "~1.0.1"
+                "setimmediate": "^1.0.5"
             },
             "dependencies": {
                 "readable-stream": {
@@ -9863,9 +9187,9 @@
             "integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew=="
         },
         "keycode": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz",
-            "integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ="
+            "version": "2.2.1",
+            "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.1.tgz",
+            "integrity": "sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg=="
         },
         "keygrip": {
             "version": "1.1.0",
@@ -9876,10 +9200,11 @@
             }
         },
         "keyv": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.1.1.tgz",
-            "integrity": "sha512-tGv1yP6snQVDSM4X6yxrv2zzq/EvpW+oYiUz6aueW1u9CtS8RzUQYxxmFwgZlO2jSgCxQbchhxaqXXp2hnKGpQ==",
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.3.0.tgz",
+            "integrity": "sha512-C30Un9+63J0CsR7Wka5quXKqYZsT6dcRQ2aOwGcSc3RiQ4HGWpTAHlCA+puNfw2jA/s11EsxA1nCXgZRuRKMQQ==",
             "requires": {
+                "compress-brotli": "^1.3.8",
                 "json-buffer": "3.0.1"
             }
         },
@@ -9897,7 +9222,7 @@
         "klaw": {
             "version": "1.3.1",
             "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
-            "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=",
+            "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==",
             "requires": {
                 "graceful-fs": "^4.1.9"
             }
@@ -9905,7 +9230,7 @@
         "latest-version": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz",
-            "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=",
+            "integrity": "sha512-Be1YRHWWlZaSsrz2U+VInk+tO0EwLIyV+23RhWLINJYwg/UIikxjlj3MhH37/6/EDCAusjajvMkMMUXRaMWl/w==",
             "requires": {
                 "package-json": "^4.0.0"
             }
@@ -9913,12 +9238,12 @@
         "lazy-cache": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
-            "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4="
+            "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ=="
         },
         "lazystream": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
-            "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=",
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz",
+            "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
             "requires": {
                 "readable-stream": "^2.0.5"
             },
@@ -9942,7 +9267,7 @@
         "levn": {
             "version": "0.3.0",
             "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
-            "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+            "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
             "dev": true,
             "requires": {
                 "prelude-ls": "~1.1.2",
@@ -9965,7 +9290,7 @@
         "load-json-file": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
-            "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+            "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==",
             "requires": {
                 "graceful-fs": "^4.1.2",
                 "parse-json": "^2.2.0",
@@ -9977,22 +9302,17 @@
                 "parse-json": {
                     "version": "2.2.0",
                     "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
-                    "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+                    "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==",
                     "requires": {
                         "error-ex": "^1.2.0"
                     }
-                },
-                "pify": {
-                    "version": "2.3.0",
-                    "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-                    "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
                 }
             }
         },
         "loader-runner": {
-            "version": "4.2.0",
-            "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz",
-            "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==",
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
+            "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
             "dev": true
         },
         "loader-utils": {
@@ -10003,16 +9323,6 @@
                 "big.js": "^5.2.2",
                 "emojis-list": "^3.0.0",
                 "json5": "^1.0.1"
-            },
-            "dependencies": {
-                "json5": {
-                    "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
-                    "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
-                    "requires": {
-                        "minimist": "^1.2.0"
-                    }
-                }
             }
         },
         "locate-path": {
@@ -10037,22 +9347,22 @@
         "lodash._getnative": {
             "version": "3.9.1",
             "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
-            "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U="
+            "integrity": "sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA=="
         },
         "lodash.chunk": {
             "version": "4.2.0",
             "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz",
-            "integrity": "sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw="
+            "integrity": "sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w=="
         },
         "lodash.curry": {
             "version": "4.1.1",
             "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz",
-            "integrity": "sha1-JI42By7ekGUB11lmIAqG2riyMXA="
+            "integrity": "sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA=="
         },
         "lodash.debounce": {
             "version": "3.1.1",
             "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-3.1.1.tgz",
-            "integrity": "sha1-gSIRw3ipTMKdWqTjNGzwv846ffU=",
+            "integrity": "sha512-lcmJwMpdPAtChA4hfiwxTtgFeNAaow701wWUgVUqeD0XJF7vMXIN+bu/2FJSGxT0NUbZy9g9VFrlOFfPjl+0Ew==",
             "requires": {
                 "lodash._getnative": "^3.0.0"
             }
@@ -10060,42 +9370,42 @@
         "lodash.defaults": {
             "version": "4.2.0",
             "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
-            "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw="
+            "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
         },
         "lodash.difference": {
             "version": "4.5.0",
             "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
-            "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw="
+            "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA=="
         },
         "lodash.flatten": {
             "version": "4.4.0",
             "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
-            "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8="
+            "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g=="
         },
         "lodash.flow": {
             "version": "3.5.0",
             "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz",
-            "integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o="
+            "integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw=="
         },
         "lodash.get": {
             "version": "4.4.2",
             "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
-            "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
+            "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ=="
         },
         "lodash.isequal": {
             "version": "4.5.0",
             "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
-            "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
+            "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
         },
         "lodash.isplainobject": {
             "version": "4.0.6",
             "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
-            "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
+            "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
         },
         "lodash.memoize": {
             "version": "4.1.2",
             "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
-            "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
+            "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag=="
         },
         "lodash.merge": {
             "version": "4.6.2",
@@ -10105,23 +9415,23 @@
         "lodash.padend": {
             "version": "4.6.1",
             "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz",
-            "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4="
+            "integrity": "sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw=="
         },
         "lodash.sortby": {
             "version": "4.7.0",
             "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
-            "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
+            "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==",
             "dev": true
         },
         "lodash.throttle": {
             "version": "4.1.1",
             "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
-            "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
+            "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="
         },
         "lodash.union": {
             "version": "4.6.0",
             "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
-            "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg="
+            "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw=="
         },
         "log-symbols": {
             "version": "2.2.0",
@@ -10132,9 +9442,9 @@
             }
         },
         "loglevel": {
-            "version": "1.6.8",
-            "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz",
-            "integrity": "sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA=="
+            "version": "1.8.0",
+            "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz",
+            "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA=="
         },
         "loglevelnext": {
             "version": "1.0.5",
@@ -10149,7 +9459,7 @@
         "longest": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
-            "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
+            "integrity": "sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg=="
         },
         "loose-envify": {
             "version": "1.4.0",
@@ -10162,7 +9472,7 @@
         "loud-rejection": {
             "version": "1.6.0",
             "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
-            "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+            "integrity": "sha512-RPNliZOFkqFumDhvYqOaNY4Uz9oJM2K9tC6JWsJJsNdhuONW4LQHRBpb0qf4pJApVffI5N39SwzWZJuEhfd7eQ==",
             "requires": {
                 "currently-unhandled": "^0.4.1",
                 "signal-exit": "^3.0.0"
@@ -10182,13 +9492,6 @@
             "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
             "requires": {
                 "tslib": "^2.0.3"
-            },
-            "dependencies": {
-                "tslib": {
-                    "version": "2.3.1",
-                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
-                    "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
-                }
             }
         },
         "lowercase-keys": {
@@ -10197,11 +9500,11 @@
             "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ=="
         },
         "lru-cache": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
-            "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+            "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
             "requires": {
-                "yallist": "^3.0.2"
+                "yallist": "^4.0.0"
             }
         },
         "magicli": {
@@ -10218,7 +9521,7 @@
                 "find-up": {
                     "version": "2.1.0",
                     "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
-                    "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+                    "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
                     "requires": {
                         "locate-path": "^2.0.0"
                     }
@@ -10226,7 +9529,7 @@
                 "locate-path": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
-                    "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+                    "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
                     "requires": {
                         "p-locate": "^2.0.0",
                         "path-exists": "^3.0.0"
@@ -10243,7 +9546,7 @@
                 "p-locate": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
-                    "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+                    "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
                     "requires": {
                         "p-limit": "^1.1.0"
                     }
@@ -10251,22 +9554,22 @@
                 "p-try": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
-                    "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
+                    "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww=="
                 }
             }
         },
         "make-dir": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
-            "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+            "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
             "requires": {
-                "pify": "^3.0.0"
+                "semver": "^6.0.0"
             },
             "dependencies": {
-                "pify": {
-                    "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-                    "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
+                "semver": {
+                    "version": "6.3.0",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+                    "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
                 }
             }
         },
@@ -10279,17 +9582,17 @@
         "map-cache": {
             "version": "0.2.2",
             "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
-            "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8="
+            "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg=="
         },
         "map-obj": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
-            "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0="
+            "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg=="
         },
         "map-visit": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
-            "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+            "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==",
             "requires": {
                 "object-visit": "^1.0.0"
             }
@@ -10334,7 +9637,7 @@
         "math-codegen": {
             "version": "0.3.5",
             "resolved": "https://registry.npmjs.org/math-codegen/-/math-codegen-0.3.5.tgz",
-            "integrity": "sha1-R5nuRnfe0Ud2bQA8ykt4ee3UDMo=",
+            "integrity": "sha512-SsFYMv33FxMKYxI1PBiaZT+8AeDITK+k/PKhbHNlOPHIz5FIPF4wy78yWqanN6luXdsXENUZgCIC6xH6bfUq1g==",
             "requires": {
                 "extend": "^3.0.0",
                 "mr-parser": "^0.2.1"
@@ -10343,7 +9646,7 @@
         "mathquill": {
             "version": "0.10.1-a",
             "resolved": "https://registry.npmjs.org/mathquill/-/mathquill-0.10.1-a.tgz",
-            "integrity": "sha1-vyylaQEAY6w0vNXVKa3Ag3zVPD8=",
+            "integrity": "sha512-snSAEwAtwdwBFSor+nVBnWWQtTw67kgAgKMyAIxuz4ZPboy0qkWZmd7BL3lfOXp/INihhRlU1PcfaAtDaRhmzA==",
             "requires": {
                 "jquery": "^1.12.3"
             },
@@ -10351,32 +9654,32 @@
                 "jquery": {
                     "version": "1.12.4",
                     "resolved": "https://registry.npmjs.org/jquery/-/jquery-1.12.4.tgz",
-                    "integrity": "sha1-AeHfuikP5z3rp3zurLD5ui/sngw="
+                    "integrity": "sha512-UEVp7PPK9xXYSk8xqXCJrkXnKZtlgWkd2GsAQbMRFK6S/ePU2JN5G2Zum8hIVjzR3CpdfSqdqAzId/xd4TJHeg=="
                 }
             }
         },
         "max-safe-integer": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/max-safe-integer/-/max-safe-integer-1.0.1.tgz",
-            "integrity": "sha1-84BgvixWPYwC5tSK85Ei/YO29BA="
+            "integrity": "sha512-CHZ/Nopqh46UtA0YvLclxj9F95qExLmTnMS5fnYlXvX4zj1RUOC3cPaGEOMhdPE8SSudSQ6wkQUJLA5E/WeL4A=="
         },
         "media-typer": {
             "version": "0.3.0",
             "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
-            "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+            "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
         },
         "memfs": {
-            "version": "3.4.1",
-            "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz",
-            "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==",
+            "version": "3.4.4",
+            "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.4.tgz",
+            "integrity": "sha512-W4gHNUE++1oSJVn8Y68jPXi+mkx3fXR5ITE/Ubz6EQ3xRpCN5k2CQ4AUR8094Z7211F876TyoBACGsIveqgiGA==",
             "requires": {
                 "fs-monkey": "1.0.3"
             }
         },
         "memoize-one": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz",
-            "integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA=="
+            "version": "5.2.1",
+            "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
+            "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
         },
         "memory-fs": {
             "version": "0.5.0",
@@ -10414,12 +9717,12 @@
         "memorystream": {
             "version": "0.3.1",
             "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
-            "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI="
+            "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw=="
         },
         "meow": {
             "version": "3.7.0",
             "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
-            "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+            "integrity": "sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==",
             "requires": {
                 "camelcase-keys": "^2.0.0",
                 "decamelize": "^1.1.2",
@@ -10444,7 +9747,7 @@
         "merge-descriptors": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
-            "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+            "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
         },
         "merge-stream": {
             "version": "2.0.0",
@@ -10454,7 +9757,7 @@
         "methods": {
             "version": "1.1.2",
             "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
-            "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+            "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
         },
         "microevent.ts": {
             "version": "0.1.1",
@@ -10488,16 +9791,16 @@
             "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
         },
         "mime-db": {
-            "version": "1.44.0",
-            "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
-            "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
+            "version": "1.52.0",
+            "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+            "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
         },
         "mime-types": {
-            "version": "2.1.27",
-            "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
-            "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
+            "version": "2.1.35",
+            "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+            "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
             "requires": {
-                "mime-db": "1.44.0"
+                "mime-db": "1.52.0"
             }
         },
         "mimic-fn": {
@@ -10517,17 +9820,34 @@
             "dev": true
         },
         "minimatch": {
-            "version": "3.0.4",
-            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-            "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+            "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.5",
-            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
-            "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+            "version": "1.2.6",
+            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+            "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
+        },
+        "minipass": {
+            "version": "3.1.6",
+            "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
+            "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
+            "requires": {
+                "yallist": "^4.0.0"
+            }
+        },
+        "minizlib": {
+            "version": "2.1.2",
+            "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+            "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+            "requires": {
+                "minipass": "^3.0.0",
+                "yallist": "^4.0.0"
+            }
         },
         "mississippi": {
             "version": "2.0.0",
@@ -10566,6 +9886,16 @@
             "requires": {
                 "for-in": "^1.0.2",
                 "is-extendable": "^1.0.1"
+            },
+            "dependencies": {
+                "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"
+                    }
+                }
             }
         },
         "mkdirp": {
@@ -10577,9 +9907,9 @@
             }
         },
         "mkdirp-classic": {
-            "version": "0.5.2",
-            "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.2.tgz",
-            "integrity": "sha512-ejdnDQcR75gwknmMw/tx02AuRs8jCtqFoFqDZMjiNxsu85sRIJVXDKHuLYvUUPRBUtV2FpSZa9bL1BUa3BdR2g=="
+            "version": "0.5.3",
+            "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+            "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
         },
         "mobile-detect": {
             "version": "1.4.5",
@@ -10661,19 +9991,28 @@
                 "he": {
                     "version": "1.1.1",
                     "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
-                    "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
+                    "integrity": "sha512-z/GDPjlRMNOa2XJiB4em8wJpuuBfrFOlYKTZxtpkdr1uPdibHI8rYA3MY0KDObpVyaes0e/aunid/t88ZI2EKA==",
                     "dev": true
                 },
+                "minimatch": {
+                    "version": "3.0.4",
+                    "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+                    "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+                    "dev": true,
+                    "requires": {
+                        "brace-expansion": "^1.1.7"
+                    }
+                },
                 "minimist": {
                     "version": "0.0.8",
                     "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
-                    "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+                    "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==",
                     "dev": true
                 },
                 "mkdirp": {
                     "version": "0.5.1",
                     "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
-                    "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+                    "integrity": "sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==",
                     "dev": true,
                     "requires": {
                         "minimist": "0.0.8"
@@ -10682,7 +10021,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
                     "dev": true
                 },
                 "supports-color": {
@@ -10723,14 +10062,6 @@
                     "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
                     "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg=="
                 },
-                "optional-require": {
-                    "version": "1.1.8",
-                    "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz",
-                    "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==",
-                    "requires": {
-                        "require-at": "^1.0.6"
-                    }
-                },
                 "readable-stream": {
                     "version": "2.3.7",
                     "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -10784,14 +10115,6 @@
                 "sliced": "1.0.1"
             },
             "dependencies": {
-                "@types/bson": {
-                    "version": "4.0.5",
-                    "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.5.tgz",
-                    "integrity": "sha512-vVLwMUqhYJSQ/WKcE60eFqcyuWse5fGH+NMAXHuKrUAPoryq3ATxk5o4bgYNtg5aOM4APVg7Hnb3ASqUYG0PKg==",
-                    "requires": {
-                        "@types/node": "*"
-                    }
-                },
                 "bson": {
                     "version": "1.1.6",
                     "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
@@ -10802,6 +10125,11 @@
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
                     "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
                 },
+                "optional-require": {
+                    "version": "1.0.3",
+                    "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz",
+                    "integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA=="
+                },
                 "safe-buffer": {
                     "version": "5.2.1",
                     "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -10817,7 +10145,7 @@
         "move-concurrently": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
-            "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+            "integrity": "sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==",
             "dev": true,
             "requires": {
                 "aproba": "^1.1.1",
@@ -10828,6 +10156,12 @@
                 "run-queue": "^1.0.3"
             },
             "dependencies": {
+                "aproba": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                    "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+                    "dev": true
+                },
                 "rimraf": {
                     "version": "2.7.1",
                     "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
@@ -10872,14 +10206,14 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                 }
             }
         },
         "mr-parser": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/mr-parser/-/mr-parser-0.2.1.tgz",
-            "integrity": "sha1-hhi5ukF+KOn0OaQcaVtVTq/u2Sc="
+            "integrity": "sha512-hug+mpbSSKnH13rFqy3zm+XiG+QTStiDAgMTHK355TIstQE0qBkBtSJsa5YHP94AuarVX9b/4dcebdTRZ9YiEw=="
         },
         "ms": {
             "version": "2.1.1",
@@ -10899,13 +10233,13 @@
         "multicast-dns-service-types": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
-            "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
+            "integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==",
             "dev": true
         },
         "nan": {
-            "version": "2.14.1",
-            "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
-            "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw=="
+            "version": "2.16.0",
+            "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz",
+            "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA=="
         },
         "nanoid": {
             "version": "2.1.11",
@@ -10938,7 +10272,7 @@
         "native-or-bluebird": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.2.0.tgz",
-            "integrity": "sha1-OcR7/Xgl0fuf+tMiEK4l2q3xAck="
+            "integrity": "sha512-0SH8UubxDfe382eYiwmd12qxAbiWGzlGZv6CkMA+DPojWa/Y0oH4hE0lRtFfFgJmPQFyKXeB8XxPbZz6TvvKaQ=="
         },
         "negotiator": {
             "version": "0.6.3",
@@ -10946,9 +10280,9 @@
             "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
         },
         "neo-async": {
-            "version": "2.6.1",
-            "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
-            "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
+            "version": "2.6.2",
+            "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+            "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
             "dev": true
         },
         "next-tick": {
@@ -10959,7 +10293,7 @@
         "nextafter": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/nextafter/-/nextafter-1.0.0.tgz",
-            "integrity": "sha1-t9d7U1MQ4+CX5gJauwqQNHfsGjo=",
+            "integrity": "sha512-7PO+A89Tll2rSEfyrjtqO0MaI37+nnxBdnQcPypfbEYYuGaJxWGCqaOwQX4a3GHNTS08l1kazuiLEWZniZjMUQ==",
             "requires": {
                 "double-bits": "^1.1.0"
             }
@@ -10977,19 +10311,12 @@
             "requires": {
                 "lower-case": "^2.0.2",
                 "tslib": "^2.0.3"
-            },
-            "dependencies": {
-                "tslib": {
-                    "version": "2.3.1",
-                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
-                    "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
-                }
             }
         },
         "node-abi": {
-            "version": "2.16.0",
-            "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.16.0.tgz",
-            "integrity": "sha512-+sa0XNlWDA6T+bDLmkCUYn6W5k5W6BPRL6mqzSCs6H/xUgtl4D5x2fORKDzopKiU6wsyn/+wXlRXwXeSp+mtoA==",
+            "version": "2.30.1",
+            "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz",
+            "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==",
             "requires": {
                 "semver": "^5.4.1"
             }
@@ -10997,7 +10324,7 @@
         "node-ensure": {
             "version": "0.0.0",
             "resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz",
-            "integrity": "sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc="
+            "integrity": "sha512-DRI60hzo2oKN1ma0ckc6nQWlHU69RH6xN0sjQTjMpChPfTYvKZdcQFfdYK2RWbJcKyUizSIy/l8OTGxMAM1QDw=="
         },
         "node-environment-flags": {
             "version": "1.0.5",
@@ -11018,9 +10345,9 @@
             }
         },
         "node-forge": {
-            "version": "0.9.1",
-            "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.1.tgz",
-            "integrity": "sha512-G6RlQt5Sb4GMBzXvhfkeFmbqR6MzhtnT7VTHuLadjkii3rdYHNdw0m8zA4BTxVIh68FicCQ2NSUANpsqkr9jvQ=="
+            "version": "0.10.0",
+            "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
+            "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA=="
         },
         "node-gyp": {
             "version": "3.8.0",
@@ -11041,14 +10368,81 @@
                 "which": "1"
             },
             "dependencies": {
+                "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=="
+                },
+                "aproba": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                    "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+                },
+                "are-we-there-yet": {
+                    "version": "1.1.7",
+                    "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
+                    "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
+                    "requires": {
+                        "delegates": "^1.0.0",
+                        "readable-stream": "^2.0.6"
+                    }
+                },
+                "gauge": {
+                    "version": "2.7.4",
+                    "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+                    "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==",
+                    "requires": {
+                        "aproba": "^1.0.3",
+                        "console-control-strings": "^1.0.0",
+                        "has-unicode": "^2.0.0",
+                        "object-assign": "^4.1.0",
+                        "signal-exit": "^3.0.0",
+                        "string-width": "^1.0.1",
+                        "strip-ansi": "^3.0.1",
+                        "wide-align": "^1.1.0"
+                    }
+                },
+                "is-fullwidth-code-point": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+                    "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==",
+                    "requires": {
+                        "number-is-nan": "^1.0.0"
+                    }
+                },
                 "nopt": {
                     "version": "3.0.6",
                     "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
-                    "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+                    "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==",
                     "requires": {
                         "abbrev": "1"
                     }
                 },
+                "npmlog": {
+                    "version": "4.1.2",
+                    "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+                    "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+                    "requires": {
+                        "are-we-there-yet": "~1.1.2",
+                        "console-control-strings": "~1.1.0",
+                        "gauge": "~2.7.3",
+                        "set-blocking": "~2.0.0"
+                    }
+                },
+                "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"
+                    }
+                },
                 "rimraf": {
                     "version": "2.7.1",
                     "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
@@ -11057,11 +10451,29 @@
                         "glob": "^7.1.3"
                     }
                 },
-                "semver": {
-                    "version": "5.3.0",
-                    "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
-                    "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
-                },
+                "semver": {
+                    "version": "5.3.0",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+                    "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
+                },
+                "string-width": {
+                    "version": "1.0.2",
+                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+                    "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+                    "requires": {
+                        "code-point-at": "^1.0.0",
+                        "is-fullwidth-code-point": "^1.0.0",
+                        "strip-ansi": "^3.0.0"
+                    }
+                },
+                "strip-ansi": {
+                    "version": "3.0.1",
+                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+                    "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+                    "requires": {
+                        "ansi-regex": "^2.0.0"
+                    }
+                },
                 "tar": {
                     "version": "2.2.2",
                     "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
@@ -11075,9 +10487,9 @@
             }
         },
         "node-releases": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz",
-            "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg=="
+            "version": "2.0.5",
+            "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz",
+            "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q=="
         },
         "node-sass": {
             "version": "4.14.1",
@@ -11106,17 +10518,31 @@
                 "ansi-regex": {
                     "version": "2.1.1",
                     "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+                    "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": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+                    "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA=="
+                },
+                "aproba": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                    "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+                },
+                "are-we-there-yet": {
+                    "version": "1.1.7",
+                    "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
+                    "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
+                    "requires": {
+                        "delegates": "^1.0.0",
+                        "readable-stream": "^2.0.6"
+                    }
                 },
                 "chalk": {
                     "version": "1.1.3",
                     "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-                    "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+                    "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
                     "requires": {
                         "ansi-styles": "^2.2.1",
                         "escape-string-regexp": "^1.0.2",
@@ -11125,10 +10551,68 @@
                         "supports-color": "^2.0.0"
                     }
                 },
+                "gauge": {
+                    "version": "2.7.4",
+                    "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+                    "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==",
+                    "requires": {
+                        "aproba": "^1.0.3",
+                        "console-control-strings": "^1.0.0",
+                        "has-unicode": "^2.0.0",
+                        "object-assign": "^4.1.0",
+                        "signal-exit": "^3.0.0",
+                        "string-width": "^1.0.1",
+                        "strip-ansi": "^3.0.1",
+                        "wide-align": "^1.1.0"
+                    }
+                },
                 "get-stdin": {
                     "version": "4.0.1",
                     "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
-                    "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4="
+                    "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw=="
+                },
+                "is-fullwidth-code-point": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+                    "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==",
+                    "requires": {
+                        "number-is-nan": "^1.0.0"
+                    }
+                },
+                "npmlog": {
+                    "version": "4.1.2",
+                    "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+                    "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+                    "requires": {
+                        "are-we-there-yet": "~1.1.2",
+                        "console-control-strings": "~1.1.0",
+                        "gauge": "~2.7.3",
+                        "set-blocking": "~2.0.0"
+                    }
+                },
+                "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"
+                    }
+                },
+                "string-width": {
+                    "version": "1.0.2",
+                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+                    "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+                    "requires": {
+                        "code-point-at": "^1.0.0",
+                        "is-fullwidth-code-point": "^1.0.0",
+                        "strip-ansi": "^3.0.0"
+                    }
                 },
                 "strip-ansi": {
                     "version": "3.0.1",
@@ -11183,7 +10667,15 @@
         "noop-logger": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
-            "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI="
+            "integrity": "sha512-6kM8CLXvuW5crTxsAtva2YLrRrDaiTIkIePWs9moLHqbFWT94WpNFjwS/5dfLfECg5i/lkmw3aoqVidxt23TEQ=="
+        },
+        "nopt": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
+            "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
+            "requires": {
+                "abbrev": "1"
+            }
         },
         "normalize-package-data": {
             "version": "2.5.0",
@@ -11212,9 +10704,9 @@
             "integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg=="
         },
         "npm": {
-            "version": "6.14.16",
-            "resolved": "https://registry.npmjs.org/npm/-/npm-6.14.16.tgz",
-            "integrity": "sha512-LMiLGYsVNJfVPlQg7v2NYjG7iRIapcLv+oMunlq7fkXVx0BATCjRu7XyWl0G+iuZzHy4CjtM32QB8ox8juTgaw==",
+            "version": "6.14.17",
+            "resolved": "https://registry.npmjs.org/npm/-/npm-6.14.17.tgz",
+            "integrity": "sha512-CxEDn1ydVRPDl4tHrlnq+WevYAhv4GF2AEHzJKQ4prZDZ96IS3Uo6t0Sy6O9kB6XzqkI+J00WfYCqqk0p6IJ1Q==",
             "requires": {
                 "JSONStream": "^1.3.5",
                 "abbrev": "~1.1.1",
@@ -11343,8 +10835,7 @@
             "dependencies": {
                 "JSONStream": {
                     "version": "1.3.5",
-                    "resolved": false,
-                    "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
+                    "bundled": true,
                     "requires": {
                         "jsonparse": "^1.2.0",
                         "through": ">=2.2.7 <3"
@@ -11352,70 +10843,59 @@
                 },
                 "abbrev": {
                     "version": "1.1.1",
-                    "resolved": false,
-                    "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+                    "bundled": true
                 },
                 "agent-base": {
                     "version": "4.3.0",
-                    "resolved": false,
-                    "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
+                    "bundled": true,
                     "requires": {
                         "es6-promisify": "^5.0.0"
                     }
                 },
                 "agentkeepalive": {
                     "version": "3.5.2",
-                    "resolved": false,
-                    "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==",
+                    "bundled": true,
                     "requires": {
                         "humanize-ms": "^1.2.1"
                     }
                 },
                 "ansi-align": {
                     "version": "2.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=",
+                    "bundled": true,
                     "requires": {
                         "string-width": "^2.0.0"
                     }
                 },
                 "ansi-regex": {
                     "version": "2.1.1",
-                    "resolved": false,
-                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+                    "bundled": true
                 },
                 "ansi-styles": {
                     "version": "3.2.1",
-                    "resolved": false,
-                    "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+                    "bundled": true,
                     "requires": {
                         "color-convert": "^1.9.0"
                     }
                 },
                 "ansicolors": {
                     "version": "0.3.2",
-                    "resolved": false,
-                    "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk="
+                    "bundled": true
                 },
                 "ansistyles": {
                     "version": "0.1.3",
-                    "resolved": false,
-                    "integrity": "sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk="
+                    "bundled": true
                 },
                 "aproba": {
                     "version": "2.0.0",
-                    "resolved": false,
-                    "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ=="
+                    "bundled": true
                 },
                 "archy": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA="
+                    "bundled": true
                 },
                 "are-we-there-yet": {
                     "version": "1.1.4",
-                    "resolved": false,
-                    "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
+                    "bundled": true,
                     "requires": {
                         "delegates": "^1.0.0",
                         "readable-stream": "^2.0.6"
@@ -11423,8 +10903,7 @@
                     "dependencies": {
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": false,
-                            "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+                            "bundled": true,
                             "requires": {
                                 "core-util-is": "~1.0.0",
                                 "inherits": "~2.0.3",
@@ -11437,8 +10916,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": false,
-                            "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+                            "bundled": true,
                             "requires": {
                                 "safe-buffer": "~5.1.0"
                             }
@@ -11447,46 +10925,38 @@
                 },
                 "asap": {
                     "version": "2.0.6",
-                    "resolved": false,
-                    "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
+                    "bundled": true
                 },
                 "asn1": {
                     "version": "0.2.4",
-                    "resolved": false,
-                    "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+                    "bundled": true,
                     "requires": {
                         "safer-buffer": "~2.1.0"
                     }
                 },
                 "assert-plus": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+                    "bundled": true
                 },
                 "asynckit": {
                     "version": "0.4.0",
-                    "resolved": false,
-                    "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+                    "bundled": true
                 },
                 "aws-sign2": {
                     "version": "0.7.0",
-                    "resolved": false,
-                    "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
+                    "bundled": true
                 },
                 "aws4": {
                     "version": "1.8.0",
-                    "resolved": false,
-                    "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
+                    "bundled": true
                 },
                 "balanced-match": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+                    "bundled": true
                 },
                 "bcrypt-pbkdf": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "tweetnacl": "^0.14.3"
@@ -11494,8 +10964,7 @@
                 },
                 "bin-links": {
                     "version": "1.1.8",
-                    "resolved": false,
-                    "integrity": "sha512-KgmVfx+QqggqP9dA3iIc5pA4T1qEEEL+hOhOhNPaUm77OTrJoOXE/C05SJLNJe6m/2wUK7F1tDSou7n5TfCDzQ==",
+                    "bundled": true,
                     "requires": {
                         "bluebird": "^3.5.3",
                         "cmd-shim": "^3.0.0",
@@ -11507,13 +10976,11 @@
                 },
                 "bluebird": {
                     "version": "3.5.5",
-                    "resolved": false,
-                    "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w=="
+                    "bundled": true
                 },
                 "boxen": {
                     "version": "1.3.0",
-                    "resolved": false,
-                    "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==",
+                    "bundled": true,
                     "requires": {
                         "ansi-align": "^2.0.0",
                         "camelcase": "^4.0.0",
@@ -11526,8 +10993,7 @@
                 },
                 "brace-expansion": {
                     "version": "1.1.11",
-                    "resolved": false,
-                    "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+                    "bundled": true,
                     "requires": {
                         "balanced-match": "^1.0.0",
                         "concat-map": "0.0.1"
@@ -11535,28 +11001,23 @@
                 },
                 "buffer-from": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA=="
+                    "bundled": true
                 },
                 "builtins": {
                     "version": "1.0.3",
-                    "resolved": false,
-                    "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og="
+                    "bundled": true
                 },
                 "byline": {
                     "version": "5.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE="
+                    "bundled": true
                 },
                 "byte-size": {
                     "version": "5.0.1",
-                    "resolved": false,
-                    "integrity": "sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw=="
+                    "bundled": true
                 },
                 "cacache": {
                     "version": "12.0.3",
-                    "resolved": false,
-                    "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==",
+                    "bundled": true,
                     "requires": {
                         "bluebird": "^3.5.5",
                         "chownr": "^1.1.1",
@@ -11577,28 +11038,23 @@
                 },
                 "call-limit": {
                     "version": "1.1.1",
-                    "resolved": false,
-                    "integrity": "sha512-5twvci5b9eRBw2wCfPtN0GmlR2/gadZqyFpPhOK6CvMFoFgA+USnZ6Jpu1lhG9h85pQ3Ouil3PfXWRD4EUaRiQ=="
+                    "bundled": true
                 },
                 "camelcase": {
                     "version": "4.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
+                    "bundled": true
                 },
                 "capture-stack-trace": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0="
+                    "bundled": true
                 },
                 "caseless": {
                     "version": "0.12.0",
-                    "resolved": false,
-                    "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
+                    "bundled": true
                 },
                 "chalk": {
                     "version": "2.4.1",
-                    "resolved": false,
-                    "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
+                    "bundled": true,
                     "requires": {
                         "ansi-styles": "^3.2.1",
                         "escape-string-regexp": "^1.0.5",
@@ -11607,31 +11063,26 @@
                 },
                 "chownr": {
                     "version": "1.1.4",
-                    "resolved": false,
-                    "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+                    "bundled": true
                 },
                 "ci-info": {
                     "version": "2.0.0",
-                    "resolved": false,
-                    "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="
+                    "bundled": true
                 },
                 "cidr-regex": {
                     "version": "2.0.10",
-                    "resolved": false,
-                    "integrity": "sha512-sB3ogMQXWvreNPbJUZMRApxuRYd+KoIo4RGQ81VatjmMW6WJPo+IJZ2846FGItr9VzKo5w7DXzijPLGtSd0N3Q==",
+                    "bundled": true,
                     "requires": {
                         "ip-regex": "^2.1.0"
                     }
                 },
                 "cli-boxes": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM="
+                    "bundled": true
                 },
                 "cli-columns": {
                     "version": "3.1.2",
-                    "resolved": false,
-                    "integrity": "sha1-ZzLZcpee/CrkRKHwjgj6E5yWoY4=",
+                    "bundled": true,
                     "requires": {
                         "string-width": "^2.0.0",
                         "strip-ansi": "^3.0.1"
@@ -11639,8 +11090,7 @@
                 },
                 "cli-table3": {
                     "version": "0.5.1",
-                    "resolved": false,
-                    "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==",
+                    "bundled": true,
                     "requires": {
                         "colors": "^1.1.2",
                         "object-assign": "^4.1.0",
@@ -11649,8 +11099,7 @@
                 },
                 "cliui": {
                     "version": "5.0.0",
-                    "resolved": false,
-                    "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+                    "bundled": true,
                     "requires": {
                         "string-width": "^3.1.0",
                         "strip-ansi": "^5.2.0",
@@ -11658,19 +11107,16 @@
                     },
                     "dependencies": {
                         "ansi-regex": {
-                            "version": "4.1.0",
-                            "resolved": false,
-                            "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+                            "version": "4.1.1",
+                            "bundled": true
                         },
                         "is-fullwidth-code-point": {
                             "version": "2.0.0",
-                            "resolved": false,
-                            "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+                            "bundled": true
                         },
                         "string-width": {
                             "version": "3.1.0",
-                            "resolved": false,
-                            "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+                            "bundled": true,
                             "requires": {
                                 "emoji-regex": "^7.0.1",
                                 "is-fullwidth-code-point": "^2.0.0",
@@ -11679,8 +11125,7 @@
                         },
                         "strip-ansi": {
                             "version": "5.2.0",
-                            "resolved": false,
-                            "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+                            "bundled": true,
                             "requires": {
                                 "ansi-regex": "^4.1.0"
                             }
@@ -11689,13 +11134,11 @@
                 },
                 "clone": {
                     "version": "1.0.4",
-                    "resolved": false,
-                    "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4="
+                    "bundled": true
                 },
                 "cmd-shim": {
                     "version": "3.0.3",
-                    "resolved": false,
-                    "integrity": "sha512-DtGg+0xiFhQIntSBRzL2fRQBnmtAVwXIDo4Qq46HPpObYquxMaZS4sb82U9nH91qJrlosC1wa9gwr0QyL/HypA==",
+                    "bundled": true,
                     "requires": {
                         "graceful-fs": "^4.1.2",
                         "mkdirp": "~0.5.0"
@@ -11703,32 +11146,27 @@
                 },
                 "code-point-at": {
                     "version": "1.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+                    "bundled": true
                 },
                 "color-convert": {
                     "version": "1.9.1",
-                    "resolved": false,
-                    "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==",
+                    "bundled": true,
                     "requires": {
                         "color-name": "^1.1.1"
                     }
                 },
                 "color-name": {
                     "version": "1.1.3",
-                    "resolved": false,
-                    "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+                    "bundled": true
                 },
                 "colors": {
                     "version": "1.3.3",
-                    "resolved": false,
-                    "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==",
+                    "bundled": true,
                     "optional": true
                 },
                 "columnify": {
                     "version": "1.5.4",
-                    "resolved": false,
-                    "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=",
+                    "bundled": true,
                     "requires": {
                         "strip-ansi": "^3.0.0",
                         "wcwidth": "^1.0.0"
@@ -11736,21 +11174,18 @@
                 },
                 "combined-stream": {
                     "version": "1.0.6",
-                    "resolved": false,
-                    "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
+                    "bundled": true,
                     "requires": {
                         "delayed-stream": "~1.0.0"
                     }
                 },
                 "concat-map": {
                     "version": "0.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+                    "bundled": true
                 },
                 "concat-stream": {
                     "version": "1.6.2",
-                    "resolved": false,
-                    "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+                    "bundled": true,
                     "requires": {
                         "buffer-from": "^1.0.0",
                         "inherits": "^2.0.3",
@@ -11760,8 +11195,7 @@
                     "dependencies": {
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": false,
-                            "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+                            "bundled": true,
                             "requires": {
                                 "core-util-is": "~1.0.0",
                                 "inherits": "~2.0.3",
@@ -11774,8 +11208,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": false,
-                            "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+                            "bundled": true,
                             "requires": {
                                 "safe-buffer": "~5.1.0"
                             }
@@ -11784,8 +11217,7 @@
                 },
                 "config-chain": {
                     "version": "1.1.12",
-                    "resolved": false,
-                    "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==",
+                    "bundled": true,
                     "requires": {
                         "ini": "^1.3.4",
                         "proto-list": "~1.2.1"
@@ -11793,8 +11225,7 @@
                 },
                 "configstore": {
                     "version": "3.1.5",
-                    "resolved": false,
-                    "integrity": "sha512-nlOhI4+fdzoK5xmJ+NY+1gZK56bwEaWZr8fYuXohZ9Vkc1o3a4T/R3M+yE/w7x/ZVJ1zF8c+oaOvF0dztdUgmA==",
+                    "bundled": true,
                     "requires": {
                         "dot-prop": "^4.2.1",
                         "graceful-fs": "^4.1.2",
@@ -11806,13 +11237,11 @@
                 },
                 "console-control-strings": {
                     "version": "1.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
+                    "bundled": true
                 },
                 "copy-concurrently": {
                     "version": "1.0.5",
-                    "resolved": false,
-                    "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
+                    "bundled": true,
                     "requires": {
                         "aproba": "^1.1.1",
                         "fs-write-stream-atomic": "^1.0.8",
@@ -11824,33 +11253,28 @@
                     "dependencies": {
                         "aproba": {
                             "version": "1.2.0",
-                            "resolved": false,
-                            "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+                            "bundled": true
                         },
                         "iferr": {
                             "version": "0.1.5",
-                            "resolved": false,
-                            "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE="
+                            "bundled": true
                         }
                     }
                 },
                 "core-util-is": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+                    "bundled": true
                 },
                 "create-error-class": {
                     "version": "3.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=",
+                    "bundled": true,
                     "requires": {
                         "capture-stack-trace": "^1.0.0"
                     }
                 },
                 "cross-spawn": {
                     "version": "5.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+                    "bundled": true,
                     "requires": {
                         "lru-cache": "^4.0.1",
                         "shebang-command": "^1.2.0",
@@ -11859,8 +11283,7 @@
                     "dependencies": {
                         "lru-cache": {
                             "version": "4.1.5",
-                            "resolved": false,
-                            "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+                            "bundled": true,
                             "requires": {
                                 "pseudomap": "^1.0.2",
                                 "yallist": "^2.1.2"
@@ -11868,104 +11291,87 @@
                         },
                         "yallist": {
                             "version": "2.1.2",
-                            "resolved": false,
-                            "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
+                            "bundled": true
                         }
                     }
                 },
                 "crypto-random-string": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4="
+                    "bundled": true
                 },
                 "cyclist": {
                     "version": "0.2.2",
-                    "resolved": false,
-                    "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA="
+                    "bundled": true
                 },
                 "dashdash": {
                     "version": "1.14.1",
-                    "resolved": false,
-                    "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+                    "bundled": true,
                     "requires": {
                         "assert-plus": "^1.0.0"
                     }
                 },
                 "debug": {
                     "version": "3.1.0",
-                    "resolved": false,
-                    "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+                    "bundled": true,
                     "requires": {
                         "ms": "2.0.0"
                     },
                     "dependencies": {
                         "ms": {
                             "version": "2.0.0",
-                            "resolved": false,
-                            "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                            "bundled": true
                         }
                     }
                 },
                 "debuglog": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI="
+                    "bundled": true
                 },
                 "decamelize": {
                     "version": "1.2.0",
-                    "resolved": false,
-                    "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+                    "bundled": true
                 },
                 "decode-uri-component": {
                     "version": "0.2.0",
-                    "resolved": false,
-                    "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
+                    "bundled": true
                 },
                 "deep-extend": {
                     "version": "0.6.0",
-                    "resolved": false,
-                    "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
+                    "bundled": true
                 },
                 "defaults": {
                     "version": "1.0.3",
-                    "resolved": false,
-                    "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
+                    "bundled": true,
                     "requires": {
                         "clone": "^1.0.2"
                     }
                 },
                 "define-properties": {
                     "version": "1.1.3",
-                    "resolved": false,
-                    "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+                    "bundled": true,
                     "requires": {
                         "object-keys": "^1.0.12"
                     }
                 },
                 "delayed-stream": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+                    "bundled": true
                 },
                 "delegates": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
+                    "bundled": true
                 },
                 "detect-indent": {
                     "version": "5.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50="
+                    "bundled": true
                 },
                 "detect-newline": {
                     "version": "2.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I="
+                    "bundled": true
                 },
                 "dezalgo": {
                     "version": "1.0.3",
-                    "resolved": false,
-                    "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=",
+                    "bundled": true,
                     "requires": {
                         "asap": "^2.0.0",
                         "wrappy": "1"
@@ -11973,26 +11379,22 @@
                 },
                 "dot-prop": {
                     "version": "4.2.1",
-                    "resolved": false,
-                    "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==",
+                    "bundled": true,
                     "requires": {
                         "is-obj": "^1.0.0"
                     }
                 },
                 "dotenv": {
                     "version": "5.0.1",
-                    "resolved": false,
-                    "integrity": "sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow=="
+                    "bundled": true
                 },
                 "duplexer3": {
                     "version": "0.1.4",
-                    "resolved": false,
-                    "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
+                    "bundled": true
                 },
                 "duplexify": {
                     "version": "3.6.0",
-                    "resolved": false,
-                    "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==",
+                    "bundled": true,
                     "requires": {
                         "end-of-stream": "^1.0.0",
                         "inherits": "^2.0.1",
@@ -12002,8 +11404,7 @@
                     "dependencies": {
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": false,
-                            "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+                            "bundled": true,
                             "requires": {
                                 "core-util-is": "~1.0.0",
                                 "inherits": "~2.0.3",
@@ -12016,8 +11417,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": false,
-                            "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+                            "bundled": true,
                             "requires": {
                                 "safe-buffer": "~5.1.0"
                             }
@@ -12026,8 +11426,7 @@
                 },
                 "ecc-jsbn": {
                     "version": "0.1.2",
-                    "resolved": false,
-                    "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "jsbn": "~0.1.0",
@@ -12036,52 +11435,44 @@
                 },
                 "editor": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-YMf4e9YrzGqJT6jM1q+3gjok90I="
+                    "bundled": true
                 },
                 "emoji-regex": {
                     "version": "7.0.3",
-                    "resolved": false,
-                    "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
+                    "bundled": true
                 },
                 "encoding": {
                     "version": "0.1.12",
-                    "resolved": false,
-                    "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
+                    "bundled": true,
                     "requires": {
                         "iconv-lite": "~0.4.13"
                     }
                 },
                 "end-of-stream": {
                     "version": "1.4.1",
-                    "resolved": false,
-                    "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
+                    "bundled": true,
                     "requires": {
                         "once": "^1.4.0"
                     }
                 },
                 "env-paths": {
                     "version": "2.2.0",
-                    "resolved": false,
-                    "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA=="
+                    "bundled": true
                 },
                 "err-code": {
                     "version": "1.1.2",
-                    "resolved": false,
-                    "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA="
+                    "bundled": true
                 },
                 "errno": {
                     "version": "0.1.7",
-                    "resolved": false,
-                    "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+                    "bundled": true,
                     "requires": {
                         "prr": "~1.0.1"
                     }
                 },
                 "es-abstract": {
                     "version": "1.12.0",
-                    "resolved": false,
-                    "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
+                    "bundled": true,
                     "requires": {
                         "es-to-primitive": "^1.1.1",
                         "function-bind": "^1.1.1",
@@ -12092,8 +11483,7 @@
                 },
                 "es-to-primitive": {
                     "version": "1.2.0",
-                    "resolved": false,
-                    "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+                    "bundled": true,
                     "requires": {
                         "is-callable": "^1.1.4",
                         "is-date-object": "^1.0.1",
@@ -12102,26 +11492,22 @@
                 },
                 "es6-promise": {
                     "version": "4.2.8",
-                    "resolved": false,
-                    "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
+                    "bundled": true
                 },
                 "es6-promisify": {
                     "version": "5.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
+                    "bundled": true,
                     "requires": {
                         "es6-promise": "^4.0.3"
                     }
                 },
                 "escape-string-regexp": {
                     "version": "1.0.5",
-                    "resolved": false,
-                    "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+                    "bundled": true
                 },
                 "execa": {
                     "version": "0.7.0",
-                    "resolved": false,
-                    "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+                    "bundled": true,
                     "requires": {
                         "cross-spawn": "^5.0.1",
                         "get-stream": "^3.0.0",
@@ -12134,40 +11520,33 @@
                     "dependencies": {
                         "get-stream": {
                             "version": "3.0.0",
-                            "resolved": false,
-                            "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
+                            "bundled": true
                         }
                     }
                 },
                 "extend": {
                     "version": "3.0.2",
-                    "resolved": false,
-                    "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+                    "bundled": true
                 },
                 "extsprintf": {
                     "version": "1.3.0",
-                    "resolved": false,
-                    "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
+                    "bundled": true
                 },
                 "fast-json-stable-stringify": {
                     "version": "2.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
+                    "bundled": true
                 },
                 "figgy-pudding": {
                     "version": "3.5.1",
-                    "resolved": false,
-                    "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w=="
+                    "bundled": true
                 },
                 "find-npm-prefix": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha512-KEftzJ+H90x6pcKtdXZEPsQse8/y/UnvzRKrOSQFprnrGaFuJ62fVkP34Iu2IYuMvyauCyoLTNkJZgrrGA2wkA=="
+                    "bundled": true
                 },
                 "flush-write-stream": {
                     "version": "1.0.3",
-                    "resolved": false,
-                    "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==",
+                    "bundled": true,
                     "requires": {
                         "inherits": "^2.0.1",
                         "readable-stream": "^2.0.4"
@@ -12175,8 +11554,7 @@
                     "dependencies": {
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": false,
-                            "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+                            "bundled": true,
                             "requires": {
                                 "core-util-is": "~1.0.0",
                                 "inherits": "~2.0.3",
@@ -12189,8 +11567,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": false,
-                            "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+                            "bundled": true,
                             "requires": {
                                 "safe-buffer": "~5.1.0"
                             }
@@ -12199,13 +11576,11 @@
                 },
                 "forever-agent": {
                     "version": "0.6.1",
-                    "resolved": false,
-                    "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+                    "bundled": true
                 },
                 "form-data": {
                     "version": "2.3.2",
-                    "resolved": false,
-                    "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
+                    "bundled": true,
                     "requires": {
                         "asynckit": "^0.4.0",
                         "combined-stream": "1.0.6",
@@ -12214,8 +11589,7 @@
                 },
                 "from2": {
                     "version": "2.3.0",
-                    "resolved": false,
-                    "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+                    "bundled": true,
                     "requires": {
                         "inherits": "^2.0.1",
                         "readable-stream": "^2.0.0"
@@ -12223,8 +11597,7 @@
                     "dependencies": {
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": false,
-                            "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+                            "bundled": true,
                             "requires": {
                                 "core-util-is": "~1.0.0",
                                 "inherits": "~2.0.3",
@@ -12237,8 +11610,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": false,
-                            "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+                            "bundled": true,
                             "requires": {
                                 "safe-buffer": "~5.1.0"
                             }
@@ -12247,16 +11619,14 @@
                 },
                 "fs-minipass": {
                     "version": "1.2.7",
-                    "resolved": false,
-                    "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
+                    "bundled": true,
                     "requires": {
                         "minipass": "^2.6.0"
                     },
                     "dependencies": {
                         "minipass": {
                             "version": "2.9.0",
-                            "resolved": false,
-                            "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
+                            "bundled": true,
                             "requires": {
                                 "safe-buffer": "^5.1.2",
                                 "yallist": "^3.0.0"
@@ -12266,8 +11636,7 @@
                 },
                 "fs-vacuum": {
                     "version": "1.2.10",
-                    "resolved": false,
-                    "integrity": "sha1-t2Kb7AekAxolSP35n17PHMizHjY=",
+                    "bundled": true,
                     "requires": {
                         "graceful-fs": "^4.1.2",
                         "path-is-inside": "^1.0.1",
@@ -12276,8 +11645,7 @@
                 },
                 "fs-write-stream-atomic": {
                     "version": "1.0.10",
-                    "resolved": false,
-                    "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+                    "bundled": true,
                     "requires": {
                         "graceful-fs": "^4.1.2",
                         "iferr": "^0.1.5",
@@ -12287,13 +11655,11 @@
                     "dependencies": {
                         "iferr": {
                             "version": "0.1.5",
-                            "resolved": false,
-                            "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE="
+                            "bundled": true
                         },
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": false,
-                            "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+                            "bundled": true,
                             "requires": {
                                 "core-util-is": "~1.0.0",
                                 "inherits": "~2.0.3",
@@ -12306,8 +11672,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": false,
-                            "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+                            "bundled": true,
                             "requires": {
                                 "safe-buffer": "~5.1.0"
                             }
@@ -12316,18 +11681,15 @@
                 },
                 "fs.realpath": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+                    "bundled": true
                 },
                 "function-bind": {
                     "version": "1.1.1",
-                    "resolved": false,
-                    "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+                    "bundled": true
                 },
                 "gauge": {
                     "version": "2.7.4",
-                    "resolved": false,
-                    "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+                    "bundled": true,
                     "requires": {
                         "aproba": "^1.0.3",
                         "console-control-strings": "^1.0.0",
@@ -12341,13 +11703,11 @@
                     "dependencies": {
                         "aproba": {
                             "version": "1.2.0",
-                            "resolved": false,
-                            "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+                            "bundled": true
                         },
                         "string-width": {
                             "version": "1.0.2",
-                            "resolved": false,
-                            "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+                            "bundled": true,
                             "requires": {
                                 "code-point-at": "^1.0.0",
                                 "is-fullwidth-code-point": "^1.0.0",
@@ -12358,13 +11718,11 @@
                 },
                 "genfun": {
                     "version": "5.0.0",
-                    "resolved": false,
-                    "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA=="
+                    "bundled": true
                 },
                 "gentle-fs": {
                     "version": "2.3.1",
-                    "resolved": false,
-                    "integrity": "sha512-OlwBBwqCFPcjm33rF2BjW+Pr6/ll2741l+xooiwTCeaX2CA1ZuclavyMBe0/KlR21/XGsgY6hzEQZ15BdNa13Q==",
+                    "bundled": true,
                     "requires": {
                         "aproba": "^1.1.2",
                         "chownr": "^1.1.2",
@@ -12381,41 +11739,35 @@
                     "dependencies": {
                         "aproba": {
                             "version": "1.2.0",
-                            "resolved": false,
-                            "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+                            "bundled": true
                         },
                         "iferr": {
                             "version": "0.1.5",
-                            "resolved": false,
-                            "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE="
+                            "bundled": true
                         }
                     }
                 },
                 "get-caller-file": {
                     "version": "2.0.5",
-                    "resolved": false,
-                    "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
+                    "bundled": true
                 },
                 "get-stream": {
                     "version": "4.1.0",
-                    "resolved": false,
-                    "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+                    "bundled": true,
                     "requires": {
                         "pump": "^3.0.0"
                     }
                 },
                 "getpass": {
                     "version": "0.1.7",
-                    "resolved": false,
-                    "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+                    "bundled": true,
                     "requires": {
                         "assert-plus": "^1.0.0"
                     }
                 },
                 "glob": {
                     "version": "7.1.6",
-                    "resolved": false,
-                    "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+                    "bundled": true,
                     "requires": {
                         "fs.realpath": "^1.0.0",
                         "inflight": "^1.0.4",
@@ -12427,16 +11779,14 @@
                 },
                 "global-dirs": {
                     "version": "0.1.1",
-                    "resolved": false,
-                    "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=",
+                    "bundled": true,
                     "requires": {
                         "ini": "^1.3.4"
                     }
                 },
                 "got": {
                     "version": "6.7.1",
-                    "resolved": false,
-                    "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
+                    "bundled": true,
                     "requires": {
                         "create-error-class": "^3.0.0",
                         "duplexer3": "^0.1.4",
@@ -12453,25 +11803,21 @@
                     "dependencies": {
                         "get-stream": {
                             "version": "3.0.0",
-                            "resolved": false,
-                            "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
+                            "bundled": true
                         }
                     }
                 },
                 "graceful-fs": {
                     "version": "4.2.4",
-                    "resolved": false,
-                    "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
+                    "bundled": true
                 },
                 "har-schema": {
                     "version": "2.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
+                    "bundled": true
                 },
                 "har-validator": {
                     "version": "5.1.5",
-                    "resolved": false,
-                    "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
+                    "bundled": true,
                     "requires": {
                         "ajv": "^6.12.3",
                         "har-schema": "^2.0.0"
@@ -12479,8 +11825,7 @@
                     "dependencies": {
                         "ajv": {
                             "version": "6.12.6",
-                            "resolved": false,
-                            "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+                            "bundled": true,
                             "requires": {
                                 "fast-deep-equal": "^3.1.1",
                                 "fast-json-stable-stringify": "^2.0.0",
@@ -12490,53 +11835,44 @@
                         },
                         "fast-deep-equal": {
                             "version": "3.1.3",
-                            "resolved": false,
-                            "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+                            "bundled": true
                         },
                         "json-schema-traverse": {
                             "version": "0.4.1",
-                            "resolved": false,
-                            "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+                            "bundled": true
                         }
                     }
                 },
                 "has": {
                     "version": "1.0.3",
-                    "resolved": false,
-                    "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+                    "bundled": true,
                     "requires": {
                         "function-bind": "^1.1.1"
                     }
                 },
                 "has-flag": {
                     "version": "3.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+                    "bundled": true
                 },
                 "has-symbols": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q="
+                    "bundled": true
                 },
                 "has-unicode": {
                     "version": "2.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
+                    "bundled": true
                 },
                 "hosted-git-info": {
                     "version": "2.8.9",
-                    "resolved": false,
-                    "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="
+                    "bundled": true
                 },
                 "http-cache-semantics": {
                     "version": "3.8.1",
-                    "resolved": false,
-                    "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w=="
+                    "bundled": true
                 },
                 "http-proxy-agent": {
                     "version": "2.1.0",
-                    "resolved": false,
-                    "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==",
+                    "bundled": true,
                     "requires": {
                         "agent-base": "4",
                         "debug": "3.1.0"
@@ -12544,8 +11880,7 @@
                 },
                 "http-signature": {
                     "version": "1.2.0",
-                    "resolved": false,
-                    "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+                    "bundled": true,
                     "requires": {
                         "assert-plus": "^1.0.0",
                         "jsprim": "^1.2.2",
@@ -12554,8 +11889,7 @@
                 },
                 "https-proxy-agent": {
                     "version": "2.2.4",
-                    "resolved": false,
-                    "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
+                    "bundled": true,
                     "requires": {
                         "agent-base": "^4.3.0",
                         "debug": "^3.1.0"
@@ -12563,52 +11897,44 @@
                 },
                 "humanize-ms": {
                     "version": "1.2.1",
-                    "resolved": false,
-                    "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=",
+                    "bundled": true,
                     "requires": {
                         "ms": "^2.0.0"
                     }
                 },
                 "iconv-lite": {
                     "version": "0.4.23",
-                    "resolved": false,
-                    "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
+                    "bundled": true,
                     "requires": {
                         "safer-buffer": ">= 2.1.2 < 3"
                     }
                 },
                 "iferr": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha512-9AfeLfji44r5TKInjhz3W9DyZI1zR1JAf2hVBMGhddAKPqBsupb89jGfbCTHIGZd6fGZl9WlHdn4AObygyMKwg=="
+                    "bundled": true
                 },
                 "ignore-walk": {
                     "version": "3.0.3",
-                    "resolved": false,
-                    "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
+                    "bundled": true,
                     "requires": {
                         "minimatch": "^3.0.4"
                     }
                 },
                 "import-lazy": {
                     "version": "2.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM="
+                    "bundled": true
                 },
                 "imurmurhash": {
                     "version": "0.1.4",
-                    "resolved": false,
-                    "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
+                    "bundled": true
                 },
                 "infer-owner": {
                     "version": "1.0.4",
-                    "resolved": false,
-                    "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A=="
+                    "bundled": true
                 },
                 "inflight": {
                     "version": "1.0.6",
-                    "resolved": false,
-                    "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+                    "bundled": true,
                     "requires": {
                         "once": "^1.3.0",
                         "wrappy": "1"
@@ -12616,18 +11942,15 @@
                 },
                 "inherits": {
                     "version": "2.0.4",
-                    "resolved": false,
-                    "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+                    "bundled": true
                 },
                 "ini": {
                     "version": "1.3.8",
-                    "resolved": false,
-                    "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
+                    "bundled": true
                 },
                 "init-package-json": {
                     "version": "1.10.3",
-                    "resolved": false,
-                    "integrity": "sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw==",
+                    "bundled": true,
                     "requires": {
                         "glob": "^7.1.1",
                         "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0",
@@ -12641,59 +11964,50 @@
                 },
                 "ip": {
                     "version": "1.1.5",
-                    "resolved": false,
-                    "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo="
+                    "bundled": true
                 },
                 "ip-regex": {
                     "version": "2.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk="
+                    "bundled": true
                 },
                 "is-callable": {
                     "version": "1.1.4",
-                    "resolved": false,
-                    "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA=="
+                    "bundled": true
                 },
                 "is-ci": {
                     "version": "1.2.1",
-                    "resolved": false,
-                    "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
+                    "bundled": true,
                     "requires": {
                         "ci-info": "^1.5.0"
                     },
                     "dependencies": {
                         "ci-info": {
                             "version": "1.6.0",
-                            "resolved": false,
-                            "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A=="
+                            "bundled": true
                         }
                     }
                 },
                 "is-cidr": {
                     "version": "3.0.0",
-                    "resolved": false,
-                    "integrity": "sha512-8Xnnbjsb0x462VoYiGlhEi+drY8SFwrHiSYuzc/CEwco55vkehTaxAyIjEdpi3EMvLPPJAJi9FlzP+h+03gp0Q==",
+                    "bundled": true,
                     "requires": {
                         "cidr-regex": "^2.0.10"
                     }
                 },
                 "is-date-object": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
+                    "bundled": true
                 },
                 "is-fullwidth-code-point": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+                    "bundled": true,
                     "requires": {
                         "number-is-nan": "^1.0.0"
                     }
                 },
                 "is-installed-globally": {
                     "version": "0.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=",
+                    "bundled": true,
                     "requires": {
                         "global-dirs": "^0.1.0",
                         "is-path-inside": "^1.0.0"
@@ -12701,103 +12015,85 @@
                 },
                 "is-npm": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ="
+                    "bundled": true
                 },
                 "is-obj": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
+                    "bundled": true
                 },
                 "is-path-inside": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+                    "bundled": true,
                     "requires": {
                         "path-is-inside": "^1.0.1"
                     }
                 },
                 "is-redirect": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ="
+                    "bundled": true
                 },
                 "is-regex": {
                     "version": "1.0.4",
-                    "resolved": false,
-                    "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+                    "bundled": true,
                     "requires": {
                         "has": "^1.0.1"
                     }
                 },
                 "is-retry-allowed": {
                     "version": "1.2.0",
-                    "resolved": false,
-                    "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg=="
+                    "bundled": true
                 },
                 "is-stream": {
                     "version": "1.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
+                    "bundled": true
                 },
                 "is-symbol": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+                    "bundled": true,
                     "requires": {
                         "has-symbols": "^1.0.0"
                     }
                 },
                 "is-typedarray": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+                    "bundled": true
                 },
                 "isarray": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+                    "bundled": true
                 },
                 "isexe": {
                     "version": "2.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+                    "bundled": true
                 },
                 "isstream": {
                     "version": "0.1.2",
-                    "resolved": false,
-                    "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+                    "bundled": true
                 },
                 "jsbn": {
                     "version": "0.1.1",
-                    "resolved": false,
-                    "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+                    "bundled": true,
                     "optional": true
                 },
                 "json-parse-better-errors": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
+                    "bundled": true
                 },
                 "json-schema": {
                     "version": "0.4.0",
-                    "resolved": false,
-                    "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
+                    "bundled": true
                 },
                 "json-stringify-safe": {
                     "version": "5.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+                    "bundled": true
                 },
                 "jsonparse": {
                     "version": "1.3.1",
-                    "resolved": false,
-                    "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA="
+                    "bundled": true
                 },
                 "jsprim": {
                     "version": "1.4.2",
-                    "resolved": false,
-                    "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
+                    "bundled": true,
                     "requires": {
                         "assert-plus": "1.0.0",
                         "extsprintf": "1.3.0",
@@ -12807,21 +12103,18 @@
                 },
                 "latest-version": {
                     "version": "3.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=",
+                    "bundled": true,
                     "requires": {
                         "package-json": "^4.0.0"
                     }
                 },
                 "lazy-property": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-hN3Es3Bnm6i9TNz6TAa0PVcREUc="
+                    "bundled": true
                 },
                 "libcipm": {
                     "version": "4.0.8",
-                    "resolved": false,
-                    "integrity": "sha512-IN3hh2yDJQtZZ5paSV4fbvJg4aHxCCg5tcZID/dSVlTuUiWktsgaldVljJv6Z5OUlYspx6xQkbR0efNodnIrOA==",
+                    "bundled": true,
                     "requires": {
                         "bin-links": "^1.1.2",
                         "bluebird": "^3.5.1",
@@ -12842,8 +12135,7 @@
                 },
                 "libnpm": {
                     "version": "3.0.1",
-                    "resolved": false,
-                    "integrity": "sha512-d7jU5ZcMiTfBqTUJVZ3xid44fE5ERBm9vBnmhp2ECD2Ls+FNXWxHSkO7gtvrnbLO78gwPdNPz1HpsF3W4rjkBQ==",
+                    "bundled": true,
                     "requires": {
                         "bin-links": "^1.1.2",
                         "bluebird": "^3.5.3",
@@ -12869,8 +12161,7 @@
                 },
                 "libnpmaccess": {
                     "version": "3.0.2",
-                    "resolved": false,
-                    "integrity": "sha512-01512AK7MqByrI2mfC7h5j8N9V4I7MHJuk9buo8Gv+5QgThpOgpjB7sQBDDkeZqRteFb1QM/6YNdHfG7cDvfAQ==",
+                    "bundled": true,
                     "requires": {
                         "aproba": "^2.0.0",
                         "get-stream": "^4.0.0",
@@ -12880,8 +12171,7 @@
                 },
                 "libnpmconfig": {
                     "version": "1.2.1",
-                    "resolved": false,
-                    "integrity": "sha512-9esX8rTQAHqarx6qeZqmGQKBNZR5OIbl/Ayr0qQDy3oXja2iFVQQI81R6GZ2a02bSNZ9p3YOGX1O6HHCb1X7kA==",
+                    "bundled": true,
                     "requires": {
                         "figgy-pudding": "^3.5.1",
                         "find-up": "^3.0.0",
@@ -12890,16 +12180,14 @@
                     "dependencies": {
                         "find-up": {
                             "version": "3.0.0",
-                            "resolved": false,
-                            "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+                            "bundled": true,
                             "requires": {
                                 "locate-path": "^3.0.0"
                             }
                         },
                         "locate-path": {
                             "version": "3.0.0",
-                            "resolved": false,
-                            "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+                            "bundled": true,
                             "requires": {
                                 "p-locate": "^3.0.0",
                                 "path-exists": "^3.0.0"
@@ -12907,31 +12195,27 @@
                         },
                         "p-limit": {
                             "version": "2.2.0",
-                            "resolved": false,
-                            "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
+                            "bundled": true,
                             "requires": {
                                 "p-try": "^2.0.0"
                             }
                         },
                         "p-locate": {
                             "version": "3.0.0",
-                            "resolved": false,
-                            "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+                            "bundled": true,
                             "requires": {
                                 "p-limit": "^2.0.0"
                             }
                         },
                         "p-try": {
                             "version": "2.2.0",
-                            "resolved": false,
-                            "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
+                            "bundled": true
                         }
                     }
                 },
                 "libnpmhook": {
                     "version": "5.0.3",
-                    "resolved": false,
-                    "integrity": "sha512-UdNLMuefVZra/wbnBXECZPefHMGsVDTq5zaM/LgKNE9Keyl5YXQTnGAzEo+nFOpdRqTWI9LYi4ApqF9uVCCtuA==",
+                    "bundled": true,
                     "requires": {
                         "aproba": "^2.0.0",
                         "figgy-pudding": "^3.4.1",
@@ -12941,8 +12225,7 @@
                 },
                 "libnpmorg": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha512-0sRUXLh+PLBgZmARvthhYXQAWn0fOsa6T5l3JSe2n9vKG/lCVK4nuG7pDsa7uMq+uTt2epdPK+a2g6btcY11Ww==",
+                    "bundled": true,
                     "requires": {
                         "aproba": "^2.0.0",
                         "figgy-pudding": "^3.4.1",
@@ -12952,8 +12235,7 @@
                 },
                 "libnpmpublish": {
                     "version": "1.1.2",
-                    "resolved": false,
-                    "integrity": "sha512-2yIwaXrhTTcF7bkJKIKmaCV9wZOALf/gsTDxVSu/Gu/6wiG3fA8ce8YKstiWKTxSFNC0R7isPUb6tXTVFZHt2g==",
+                    "bundled": true,
                     "requires": {
                         "aproba": "^2.0.0",
                         "figgy-pudding": "^3.5.1",
@@ -12968,8 +12250,7 @@
                 },
                 "libnpmsearch": {
                     "version": "2.0.2",
-                    "resolved": false,
-                    "integrity": "sha512-VTBbV55Q6fRzTdzziYCr64+f8AopQ1YZ+BdPOv16UegIEaE8C0Kch01wo4s3kRTFV64P121WZJwgmBwrq68zYg==",
+                    "bundled": true,
                     "requires": {
                         "figgy-pudding": "^3.5.1",
                         "get-stream": "^4.0.0",
@@ -12978,8 +12259,7 @@
                 },
                 "libnpmteam": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha512-p420vM28Us04NAcg1rzgGW63LMM6rwe+6rtZpfDxCcXxM0zUTLl7nPFEnRF3JfFBF5skF/yuZDUthTsHgde8QA==",
+                    "bundled": true,
                     "requires": {
                         "aproba": "^2.0.0",
                         "figgy-pudding": "^3.4.1",
@@ -12989,8 +12269,7 @@
                 },
                 "libnpx": {
                     "version": "10.2.4",
-                    "resolved": false,
-                    "integrity": "sha512-BPc0D1cOjBeS8VIBKUu5F80s6njm0wbVt7CsGMrIcJ+SI7pi7V0uVPGpEMH9H5L8csOcclTxAXFE2VAsJXUhfA==",
+                    "bundled": true,
                     "requires": {
                         "dotenv": "^5.0.1",
                         "npm-package-arg": "^6.0.0",
@@ -13004,8 +12283,7 @@
                 },
                 "lock-verify": {
                     "version": "2.1.0",
-                    "resolved": false,
-                    "integrity": "sha512-vcLpxnGvrqisKvLQ2C2v0/u7LVly17ak2YSgoK4PrdsYBXQIax19vhKiLfvKNFx7FRrpTnitrpzF/uuCMuorIg==",
+                    "bundled": true,
                     "requires": {
                         "npm-package-arg": "^6.1.0",
                         "semver": "^5.4.1"
@@ -13013,21 +12291,18 @@
                 },
                 "lockfile": {
                     "version": "1.0.4",
-                    "resolved": false,
-                    "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==",
+                    "bundled": true,
                     "requires": {
                         "signal-exit": "^3.0.2"
                     }
                 },
                 "lodash._baseindexof": {
                     "version": "3.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw="
+                    "bundled": true
                 },
                 "lodash._baseuniq": {
                     "version": "4.6.0",
-                    "resolved": false,
-                    "integrity": "sha1-DrtE5FaBSveQXGIS+iybLVG4Qeg=",
+                    "bundled": true,
                     "requires": {
                         "lodash._createset": "~4.0.0",
                         "lodash._root": "~3.0.0"
@@ -13035,87 +12310,72 @@
                 },
                 "lodash._bindcallback": {
                     "version": "3.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4="
+                    "bundled": true
                 },
                 "lodash._cacheindexof": {
                     "version": "3.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI="
+                    "bundled": true
                 },
                 "lodash._createcache": {
                     "version": "3.1.2",
-                    "resolved": false,
-                    "integrity": "sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=",
+                    "bundled": true,
                     "requires": {
                         "lodash._getnative": "^3.0.0"
                     }
                 },
                 "lodash._createset": {
                     "version": "4.0.3",
-                    "resolved": false,
-                    "integrity": "sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY="
+                    "bundled": true
                 },
                 "lodash._getnative": {
                     "version": "3.9.1",
-                    "resolved": false,
-                    "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U="
+                    "bundled": true
                 },
                 "lodash._root": {
                     "version": "3.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI="
+                    "bundled": true
                 },
                 "lodash.clonedeep": {
                     "version": "4.5.0",
-                    "resolved": false,
-                    "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8="
+                    "bundled": true
                 },
                 "lodash.restparam": {
                     "version": "3.6.1",
-                    "resolved": false,
-                    "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU="
+                    "bundled": true
                 },
                 "lodash.union": {
                     "version": "4.6.0",
-                    "resolved": false,
-                    "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg="
+                    "bundled": true
                 },
                 "lodash.uniq": {
                     "version": "4.5.0",
-                    "resolved": false,
-                    "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M="
+                    "bundled": true
                 },
                 "lodash.without": {
                     "version": "4.4.0",
-                    "resolved": false,
-                    "integrity": "sha1-PNRXSgC2e643OpS3SHcmQFB7eqw="
+                    "bundled": true
                 },
                 "lowercase-keys": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA=="
+                    "bundled": true
                 },
                 "lru-cache": {
                     "version": "5.1.1",
-                    "resolved": false,
-                    "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+                    "bundled": true,
                     "requires": {
                         "yallist": "^3.0.2"
                     }
                 },
                 "make-dir": {
                     "version": "1.3.0",
-                    "resolved": false,
-                    "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+                    "bundled": true,
                     "requires": {
                         "pify": "^3.0.0"
                     }
                 },
                 "make-fetch-happen": {
                     "version": "5.0.2",
-                    "resolved": false,
-                    "integrity": "sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==",
+                    "bundled": true,
                     "requires": {
                         "agentkeepalive": "^3.4.1",
                         "cacache": "^12.0.0",
@@ -13132,47 +12392,40 @@
                 },
                 "meant": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha512-KN+1uowN/NK+sT/Lzx7WSGIj2u+3xe5n2LbwObfjOhPZiA+cCfCm6idVl0RkEfjThkw5XJ96CyRcanq6GmKtUg=="
+                    "bundled": true
                 },
                 "mime-db": {
                     "version": "1.35.0",
-                    "resolved": false,
-                    "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg=="
+                    "bundled": true
                 },
                 "mime-types": {
                     "version": "2.1.19",
-                    "resolved": false,
-                    "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==",
+                    "bundled": true,
                     "requires": {
                         "mime-db": "~1.35.0"
                     }
                 },
                 "minimatch": {
                     "version": "3.0.4",
-                    "resolved": false,
-                    "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+                    "bundled": true,
                     "requires": {
                         "brace-expansion": "^1.1.7"
                     }
                 },
                 "minimist": {
-                    "version": "1.2.5",
-                    "resolved": false,
-                    "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+                    "version": "1.2.6",
+                    "bundled": true
                 },
                 "minizlib": {
                     "version": "1.3.3",
-                    "resolved": false,
-                    "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
+                    "bundled": true,
                     "requires": {
                         "minipass": "^2.9.0"
                     },
                     "dependencies": {
                         "minipass": {
                             "version": "2.9.0",
-                            "resolved": false,
-                            "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
+                            "bundled": true,
                             "requires": {
                                 "safe-buffer": "^5.1.2",
                                 "yallist": "^3.0.0"
@@ -13182,8 +12435,7 @@
                 },
                 "mississippi": {
                     "version": "3.0.0",
-                    "resolved": false,
-                    "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
+                    "bundled": true,
                     "requires": {
                         "concat-stream": "^1.5.0",
                         "duplexify": "^3.4.2",
@@ -13199,23 +12451,20 @@
                 },
                 "mkdirp": {
                     "version": "0.5.5",
-                    "resolved": false,
-                    "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+                    "bundled": true,
                     "requires": {
                         "minimist": "^1.2.5"
                     },
                     "dependencies": {
                         "minimist": {
-                            "version": "1.2.5",
-                            "resolved": false,
-                            "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+                            "version": "1.2.6",
+                            "bundled": true
                         }
                     }
                 },
                 "move-concurrently": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+                    "bundled": true,
                     "requires": {
                         "aproba": "^1.1.1",
                         "copy-concurrently": "^1.0.0",
@@ -13227,25 +12476,21 @@
                     "dependencies": {
                         "aproba": {
                             "version": "1.2.0",
-                            "resolved": false,
-                            "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+                            "bundled": true
                         }
                     }
                 },
                 "ms": {
                     "version": "2.1.1",
-                    "resolved": false,
-                    "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+                    "bundled": true
                 },
                 "mute-stream": {
                     "version": "0.0.7",
-                    "resolved": false,
-                    "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s="
+                    "bundled": true
                 },
                 "node-fetch-npm": {
                     "version": "2.0.2",
-                    "resolved": false,
-                    "integrity": "sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==",
+                    "bundled": true,
                     "requires": {
                         "encoding": "^0.1.11",
                         "json-parse-better-errors": "^1.0.0",
@@ -13254,8 +12499,7 @@
                 },
                 "node-gyp": {
                     "version": "5.1.0",
-                    "resolved": false,
-                    "integrity": "sha512-OUTryc5bt/P8zVgNUmC6xdXiDJxLMAW8cF5tLQOT9E5sOQj+UeQxnnPy74K3CLCa/SOjjBlbuzDLR8ANwA+wmw==",
+                    "bundled": true,
                     "requires": {
                         "env-paths": "^2.2.0",
                         "glob": "^7.1.4",
@@ -13272,8 +12516,7 @@
                 },
                 "nopt": {
                     "version": "4.0.3",
-                    "resolved": false,
-                    "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
+                    "bundled": true,
                     "requires": {
                         "abbrev": "1",
                         "osenv": "^0.1.4"
@@ -13281,8 +12524,7 @@
                 },
                 "normalize-package-data": {
                     "version": "2.5.0",
-                    "resolved": false,
-                    "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+                    "bundled": true,
                     "requires": {
                         "hosted-git-info": "^2.1.4",
                         "resolve": "^1.10.0",
@@ -13292,8 +12534,7 @@
                     "dependencies": {
                         "resolve": {
                             "version": "1.10.0",
-                            "resolved": false,
-                            "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==",
+                            "bundled": true,
                             "requires": {
                                 "path-parse": "^1.0.6"
                             }
@@ -13302,8 +12543,7 @@
                 },
                 "npm-audit-report": {
                     "version": "1.3.3",
-                    "resolved": false,
-                    "integrity": "sha512-8nH/JjsFfAWMvn474HB9mpmMjrnKb1Hx/oTAdjv4PT9iZBvBxiZ+wtDUapHCJwLqYGQVPaAfs+vL5+5k9QndXw==",
+                    "bundled": true,
                     "requires": {
                         "cli-table3": "^0.5.0",
                         "console-control-strings": "^1.1.0"
@@ -13311,29 +12551,25 @@
                 },
                 "npm-bundled": {
                     "version": "1.1.1",
-                    "resolved": false,
-                    "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
+                    "bundled": true,
                     "requires": {
                         "npm-normalize-package-bin": "^1.0.1"
                     }
                 },
                 "npm-cache-filename": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-3tMGxbC/yHCp6fr4I7xfKD4FrhE="
+                    "bundled": true
                 },
                 "npm-install-checks": {
                     "version": "3.0.2",
-                    "resolved": false,
-                    "integrity": "sha512-E4kzkyZDIWoin6uT5howP8VDvkM+E8IQDcHAycaAxMbwkqhIg5eEYALnXOl3Hq9MrkdQB/2/g1xwBINXdKSRkg==",
+                    "bundled": true,
                     "requires": {
                         "semver": "^2.3.0 || 3.x || 4 || 5"
                     }
                 },
                 "npm-lifecycle": {
                     "version": "3.1.5",
-                    "resolved": false,
-                    "integrity": "sha512-lDLVkjfZmvmfvpvBzA4vzee9cn+Me4orq0QF8glbswJVEbIcSNWib7qGOffolysc3teCqbbPZZkzbr3GQZTL1g==",
+                    "bundled": true,
                     "requires": {
                         "byline": "^5.0.0",
                         "graceful-fs": "^4.1.15",
@@ -13347,18 +12583,15 @@
                 },
                 "npm-logical-tree": {
                     "version": "1.2.1",
-                    "resolved": false,
-                    "integrity": "sha512-AJI/qxDB2PWI4LG1CYN579AY1vCiNyWfkiquCsJWqntRu/WwimVrC8yXeILBFHDwxfOejxewlmnvW9XXjMlYIg=="
+                    "bundled": true
                 },
                 "npm-normalize-package-bin": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA=="
+                    "bundled": true
                 },
                 "npm-package-arg": {
                     "version": "6.1.1",
-                    "resolved": false,
-                    "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==",
+                    "bundled": true,
                     "requires": {
                         "hosted-git-info": "^2.7.1",
                         "osenv": "^0.1.5",
@@ -13368,8 +12601,7 @@
                 },
                 "npm-packlist": {
                     "version": "1.4.8",
-                    "resolved": false,
-                    "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
+                    "bundled": true,
                     "requires": {
                         "ignore-walk": "^3.0.1",
                         "npm-bundled": "^1.0.1",
@@ -13378,8 +12610,7 @@
                 },
                 "npm-pick-manifest": {
                     "version": "3.0.2",
-                    "resolved": false,
-                    "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==",
+                    "bundled": true,
                     "requires": {
                         "figgy-pudding": "^3.5.1",
                         "npm-package-arg": "^6.0.0",
@@ -13388,8 +12619,7 @@
                 },
                 "npm-profile": {
                     "version": "4.0.4",
-                    "resolved": false,
-                    "integrity": "sha512-Ta8xq8TLMpqssF0H60BXS1A90iMoM6GeKwsmravJ6wYjWwSzcYBTdyWa3DZCYqPutacBMEm7cxiOkiIeCUAHDQ==",
+                    "bundled": true,
                     "requires": {
                         "aproba": "^1.1.2 || 2",
                         "figgy-pudding": "^3.4.1",
@@ -13398,8 +12628,7 @@
                 },
                 "npm-registry-fetch": {
                     "version": "4.0.7",
-                    "resolved": false,
-                    "integrity": "sha512-cny9v0+Mq6Tjz+e0erFAB+RYJ/AVGzkjnISiobqP8OWj9c9FLoZZu8/SPSKJWE17F1tk4018wfjV+ZbIbqC7fQ==",
+                    "bundled": true,
                     "requires": {
                         "JSONStream": "^1.3.4",
                         "bluebird": "^3.5.1",
@@ -13412,28 +12641,24 @@
                     "dependencies": {
                         "safe-buffer": {
                             "version": "5.2.1",
-                            "resolved": false,
-                            "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+                            "bundled": true
                         }
                     }
                 },
                 "npm-run-path": {
                     "version": "2.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+                    "bundled": true,
                     "requires": {
                         "path-key": "^2.0.0"
                     }
                 },
                 "npm-user-validate": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha512-uQwcd/tY+h1jnEaze6cdX/LrhWhoBxfSknxentoqmIuStxUExxjWd3ULMLFPiFUrZKbOVMowH6Jq2FRWfmhcEw=="
+                    "bundled": true
                 },
                 "npmlog": {
                     "version": "4.1.2",
-                    "resolved": false,
-                    "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+                    "bundled": true,
                     "requires": {
                         "are-we-there-yet": "~1.1.2",
                         "console-control-strings": "~1.1.0",
@@ -13443,28 +12668,23 @@
                 },
                 "number-is-nan": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+                    "bundled": true
                 },
                 "oauth-sign": {
                     "version": "0.9.0",
-                    "resolved": false,
-                    "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
+                    "bundled": true
                 },
                 "object-assign": {
                     "version": "4.1.1",
-                    "resolved": false,
-                    "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+                    "bundled": true
                 },
                 "object-keys": {
                     "version": "1.0.12",
-                    "resolved": false,
-                    "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag=="
+                    "bundled": true
                 },
                 "object.getownpropertydescriptors": {
                     "version": "2.0.3",
-                    "resolved": false,
-                    "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
+                    "bundled": true,
                     "requires": {
                         "define-properties": "^1.1.2",
                         "es-abstract": "^1.5.1"
@@ -13472,31 +12692,26 @@
                 },
                 "once": {
                     "version": "1.4.0",
-                    "resolved": false,
-                    "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+                    "bundled": true,
                     "requires": {
                         "wrappy": "1"
                     }
                 },
                 "opener": {
                     "version": "1.5.2",
-                    "resolved": false,
-                    "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A=="
+                    "bundled": true
                 },
                 "os-homedir": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
+                    "bundled": true
                 },
                 "os-tmpdir": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
+                    "bundled": true
                 },
                 "osenv": {
                     "version": "0.1.5",
-                    "resolved": false,
-                    "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+                    "bundled": true,
                     "requires": {
                         "os-homedir": "^1.0.0",
                         "os-tmpdir": "^1.0.0"
@@ -13504,13 +12719,11 @@
                 },
                 "p-finally": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
+                    "bundled": true
                 },
                 "package-json": {
                     "version": "4.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=",
+                    "bundled": true,
                     "requires": {
                         "got": "^6.7.1",
                         "registry-auth-token": "^3.0.1",
@@ -13520,8 +12733,7 @@
                 },
                 "pacote": {
                     "version": "9.5.12",
-                    "resolved": false,
-                    "integrity": "sha512-BUIj/4kKbwWg4RtnBncXPJd15piFSVNpTzY0rysSr3VnMowTYgkGKcaHrbReepAkjTr8lH2CVWRi58Spg2CicQ==",
+                    "bundled": true,
                     "requires": {
                         "bluebird": "^3.5.3",
                         "cacache": "^12.0.2",
@@ -13557,8 +12769,7 @@
                     "dependencies": {
                         "minipass": {
                             "version": "2.9.0",
-                            "resolved": false,
-                            "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
+                            "bundled": true,
                             "requires": {
                                 "safe-buffer": "^5.1.2",
                                 "yallist": "^3.0.0"
@@ -13568,8 +12779,7 @@
                 },
                 "parallel-transform": {
                     "version": "1.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=",
+                    "bundled": true,
                     "requires": {
                         "cyclist": "~0.2.2",
                         "inherits": "^2.0.3",
@@ -13578,8 +12788,7 @@
                     "dependencies": {
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": false,
-                            "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+                            "bundled": true,
                             "requires": {
                                 "core-util-is": "~1.0.0",
                                 "inherits": "~2.0.3",
@@ -13592,8 +12801,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": false,
-                            "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+                            "bundled": true,
                             "requires": {
                                 "safe-buffer": "~5.1.0"
                             }
@@ -13602,58 +12810,47 @@
                 },
                 "path-exists": {
                     "version": "3.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
+                    "bundled": true
                 },
                 "path-is-absolute": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+                    "bundled": true
                 },
                 "path-is-inside": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM="
+                    "bundled": true
                 },
                 "path-key": {
                     "version": "2.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
+                    "bundled": true
                 },
                 "path-parse": {
                     "version": "1.0.7",
-                    "resolved": false,
-                    "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+                    "bundled": true
                 },
                 "performance-now": {
                     "version": "2.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
+                    "bundled": true
                 },
                 "pify": {
                     "version": "3.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
+                    "bundled": true
                 },
                 "prepend-http": {
                     "version": "1.0.4",
-                    "resolved": false,
-                    "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
+                    "bundled": true
                 },
                 "process-nextick-args": {
                     "version": "2.0.0",
-                    "resolved": false,
-                    "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
+                    "bundled": true
                 },
                 "promise-inflight": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM="
+                    "bundled": true
                 },
                 "promise-retry": {
                     "version": "1.1.1",
-                    "resolved": false,
-                    "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=",
+                    "bundled": true,
                     "requires": {
                         "err-code": "^1.0.0",
                         "retry": "^0.10.0"
@@ -13661,51 +12858,43 @@
                     "dependencies": {
                         "retry": {
                             "version": "0.10.1",
-                            "resolved": false,
-                            "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q="
+                            "bundled": true
                         }
                     }
                 },
                 "promzard": {
                     "version": "0.3.0",
-                    "resolved": false,
-                    "integrity": "sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=",
+                    "bundled": true,
                     "requires": {
                         "read": "1"
                     }
                 },
                 "proto-list": {
                     "version": "1.2.4",
-                    "resolved": false,
-                    "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk="
+                    "bundled": true
                 },
                 "protoduck": {
                     "version": "5.0.1",
-                    "resolved": false,
-                    "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==",
+                    "bundled": true,
                     "requires": {
                         "genfun": "^5.0.0"
                     }
                 },
                 "prr": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY="
+                    "bundled": true
                 },
                 "pseudomap": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
+                    "bundled": true
                 },
                 "psl": {
                     "version": "1.1.29",
-                    "resolved": false,
-                    "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ=="
+                    "bundled": true
                 },
                 "pump": {
                     "version": "3.0.0",
-                    "resolved": false,
-                    "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+                    "bundled": true,
                     "requires": {
                         "end-of-stream": "^1.1.0",
                         "once": "^1.3.1"
@@ -13713,8 +12902,7 @@
                 },
                 "pumpify": {
                     "version": "1.5.1",
-                    "resolved": false,
-                    "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
+                    "bundled": true,
                     "requires": {
                         "duplexify": "^3.6.0",
                         "inherits": "^2.0.3",
@@ -13723,8 +12911,7 @@
                     "dependencies": {
                         "pump": {
                             "version": "2.0.1",
-                            "resolved": false,
-                            "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+                            "bundled": true,
                             "requires": {
                                 "end-of-stream": "^1.1.0",
                                 "once": "^1.3.1"
@@ -13734,23 +12921,19 @@
                 },
                 "punycode": {
                     "version": "1.4.1",
-                    "resolved": false,
-                    "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+                    "bundled": true
                 },
                 "qrcode-terminal": {
                     "version": "0.12.0",
-                    "resolved": false,
-                    "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ=="
+                    "bundled": true
                 },
                 "qs": {
                     "version": "6.5.2",
-                    "resolved": false,
-                    "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+                    "bundled": true
                 },
                 "query-string": {
                     "version": "6.8.2",
-                    "resolved": false,
-                    "integrity": "sha512-J3Qi8XZJXh93t2FiKyd/7Ec6GNifsjKXUsVFkSBj/kjLsDylWhnCz4NT1bkPcKotttPW+QbKGqqPH8OoI2pdqw==",
+                    "bundled": true,
                     "requires": {
                         "decode-uri-component": "^0.2.0",
                         "split-on-first": "^1.0.0",
@@ -13759,13 +12942,11 @@
                 },
                 "qw": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-77/cdA+a0FQwRCassYNBLMi5ltQ="
+                    "bundled": true
                 },
                 "rc": {
                     "version": "1.2.8",
-                    "resolved": false,
-                    "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+                    "bundled": true,
                     "requires": {
                         "deep-extend": "^0.6.0",
                         "ini": "~1.3.0",
@@ -13775,24 +12956,21 @@
                 },
                 "read": {
                     "version": "1.0.7",
-                    "resolved": false,
-                    "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=",
+                    "bundled": true,
                     "requires": {
                         "mute-stream": "~0.0.4"
                     }
                 },
                 "read-cmd-shim": {
                     "version": "1.0.5",
-                    "resolved": false,
-                    "integrity": "sha512-v5yCqQ/7okKoZZkBQUAfTsQ3sVJtXdNfbPnI5cceppoxEVLYA3k+VtV2omkeo8MS94JCy4fSiUwlRBAwCVRPUA==",
+                    "bundled": true,
                     "requires": {
                         "graceful-fs": "^4.1.2"
                     }
                 },
                 "read-installed": {
                     "version": "4.0.3",
-                    "resolved": false,
-                    "integrity": "sha1-/5uLZ/GH0eTCm5/rMfayI6zRkGc=",
+                    "bundled": true,
                     "requires": {
                         "debuglog": "^1.0.1",
                         "graceful-fs": "^4.1.2",
@@ -13805,8 +12983,7 @@
                 },
                 "read-package-json": {
                     "version": "2.1.1",
-                    "resolved": false,
-                    "integrity": "sha512-dAiqGtVc/q5doFz6096CcnXhpYk0ZN8dEKVkGLU0CsASt8SrgF6SF7OTKAYubfvFhWaqofl+Y8HK19GR8jwW+A==",
+                    "bundled": true,
                     "requires": {
                         "glob": "^7.1.1",
                         "graceful-fs": "^4.1.2",
@@ -13817,8 +12994,7 @@
                 },
                 "read-package-tree": {
                     "version": "5.3.1",
-                    "resolved": false,
-                    "integrity": "sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==",
+                    "bundled": true,
                     "requires": {
                         "read-package-json": "^2.0.0",
                         "readdir-scoped-modules": "^1.0.0",
@@ -13827,8 +13003,7 @@
                 },
                 "readable-stream": {
                     "version": "3.6.0",
-                    "resolved": false,
-                    "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+                    "bundled": true,
                     "requires": {
                         "inherits": "^2.0.3",
                         "string_decoder": "^1.1.1",
@@ -13837,8 +13012,7 @@
                 },
                 "readdir-scoped-modules": {
                     "version": "1.1.0",
-                    "resolved": false,
-                    "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==",
+                    "bundled": true,
                     "requires": {
                         "debuglog": "^1.0.1",
                         "dezalgo": "^1.0.0",
@@ -13848,8 +13022,7 @@
                 },
                 "registry-auth-token": {
                     "version": "3.4.0",
-                    "resolved": false,
-                    "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==",
+                    "bundled": true,
                     "requires": {
                         "rc": "^1.1.6",
                         "safe-buffer": "^5.0.1"
@@ -13857,16 +13030,14 @@
                 },
                 "registry-url": {
                     "version": "3.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=",
+                    "bundled": true,
                     "requires": {
                         "rc": "^1.0.1"
                     }
                 },
                 "request": {
                     "version": "2.88.0",
-                    "resolved": false,
-                    "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
+                    "bundled": true,
                     "requires": {
                         "aws-sign2": "~0.7.0",
                         "aws4": "^1.8.0",
@@ -13892,115 +13063,96 @@
                 },
                 "require-directory": {
                     "version": "2.1.1",
-                    "resolved": false,
-                    "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
+                    "bundled": true
                 },
                 "require-main-filename": {
                     "version": "2.0.0",
-                    "resolved": false,
-                    "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
+                    "bundled": true
                 },
                 "resolve-from": {
                     "version": "4.0.0",
-                    "resolved": false,
-                    "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="
+                    "bundled": true
                 },
                 "retry": {
                     "version": "0.12.0",
-                    "resolved": false,
-                    "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs="
+                    "bundled": true
                 },
                 "rimraf": {
                     "version": "2.7.1",
-                    "resolved": false,
-                    "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+                    "bundled": true,
                     "requires": {
                         "glob": "^7.1.3"
                     }
                 },
                 "run-queue": {
                     "version": "1.0.3",
-                    "resolved": false,
-                    "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
+                    "bundled": true,
                     "requires": {
                         "aproba": "^1.1.1"
                     },
                     "dependencies": {
                         "aproba": {
                             "version": "1.2.0",
-                            "resolved": false,
-                            "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+                            "bundled": true
                         }
                     }
                 },
                 "safe-buffer": {
                     "version": "5.1.2",
-                    "resolved": false,
-                    "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+                    "bundled": true
                 },
                 "safer-buffer": {
                     "version": "2.1.2",
-                    "resolved": false,
-                    "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+                    "bundled": true
                 },
                 "semver": {
                     "version": "5.7.1",
-                    "resolved": false,
-                    "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+                    "bundled": true
                 },
                 "semver-diff": {
                     "version": "2.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=",
+                    "bundled": true,
                     "requires": {
                         "semver": "^5.0.3"
                     }
                 },
                 "set-blocking": {
                     "version": "2.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
+                    "bundled": true
                 },
                 "sha": {
                     "version": "3.0.0",
-                    "resolved": false,
-                    "integrity": "sha512-DOYnM37cNsLNSGIG/zZWch5CKIRNoLdYUQTQlcgkRkoYIUwDYjqDyye16YcDZg/OPdcbUgTKMjc4SY6TB7ZAPw==",
+                    "bundled": true,
                     "requires": {
                         "graceful-fs": "^4.1.2"
                     }
                 },
                 "shebang-command": {
                     "version": "1.2.0",
-                    "resolved": false,
-                    "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+                    "bundled": true,
                     "requires": {
                         "shebang-regex": "^1.0.0"
                     }
                 },
                 "shebang-regex": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
+                    "bundled": true
                 },
                 "signal-exit": {
                     "version": "3.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
+                    "bundled": true
                 },
                 "slide": {
                     "version": "1.1.6",
-                    "resolved": false,
-                    "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc="
+                    "bundled": true
                 },
                 "smart-buffer": {
                     "version": "4.1.0",
-                    "resolved": false,
-                    "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw=="
+                    "bundled": true
                 },
                 "socks": {
                     "version": "2.3.3",
-                    "resolved": false,
-                    "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==",
+                    "bundled": true,
                     "requires": {
                         "ip": "1.1.5",
                         "smart-buffer": "^4.1.0"
@@ -14008,8 +13160,7 @@
                 },
                 "socks-proxy-agent": {
                     "version": "4.0.2",
-                    "resolved": false,
-                    "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==",
+                    "bundled": true,
                     "requires": {
                         "agent-base": "~4.2.1",
                         "socks": "~2.3.2"
@@ -14017,8 +13168,7 @@
                     "dependencies": {
                         "agent-base": {
                             "version": "4.2.1",
-                            "resolved": false,
-                            "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
+                            "bundled": true,
                             "requires": {
                                 "es6-promisify": "^5.0.0"
                             }
@@ -14027,13 +13177,11 @@
                 },
                 "sorted-object": {
                     "version": "2.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-fWMfS9OnmKJK8d/8+/6DM3pd9fw="
+                    "bundled": true
                 },
                 "sorted-union-stream": {
                     "version": "2.1.3",
-                    "resolved": false,
-                    "integrity": "sha1-x3lMfgd4gAUv9xqNSi27Sppjisc=",
+                    "bundled": true,
                     "requires": {
                         "from2": "^1.3.0",
                         "stream-iterate": "^1.1.0"
@@ -14041,8 +13189,7 @@
                     "dependencies": {
                         "from2": {
                             "version": "1.3.0",
-                            "resolved": false,
-                            "integrity": "sha1-iEE7qqX5pZfP3pIh2GmGzTwGHf0=",
+                            "bundled": true,
                             "requires": {
                                 "inherits": "~2.0.1",
                                 "readable-stream": "~1.1.10"
@@ -14050,13 +13197,11 @@
                         },
                         "isarray": {
                             "version": "0.0.1",
-                            "resolved": false,
-                            "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+                            "bundled": true
                         },
                         "readable-stream": {
                             "version": "1.1.14",
-                            "resolved": false,
-                            "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+                            "bundled": true,
                             "requires": {
                                 "core-util-is": "~1.0.0",
                                 "inherits": "~2.0.1",
@@ -14066,15 +13211,13 @@
                         },
                         "string_decoder": {
                             "version": "0.10.31",
-                            "resolved": false,
-                            "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+                            "bundled": true
                         }
                     }
                 },
                 "spdx-correct": {
                     "version": "3.0.0",
-                    "resolved": false,
-                    "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==",
+                    "bundled": true,
                     "requires": {
                         "spdx-expression-parse": "^3.0.0",
                         "spdx-license-ids": "^3.0.0"
@@ -14082,13 +13225,11 @@
                 },
                 "spdx-exceptions": {
                     "version": "2.1.0",
-                    "resolved": false,
-                    "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg=="
+                    "bundled": true
                 },
                 "spdx-expression-parse": {
                     "version": "3.0.0",
-                    "resolved": false,
-                    "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+                    "bundled": true,
                     "requires": {
                         "spdx-exceptions": "^2.1.0",
                         "spdx-license-ids": "^3.0.0"
@@ -14096,18 +13237,15 @@
                 },
                 "spdx-license-ids": {
                     "version": "3.0.5",
-                    "resolved": false,
-                    "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q=="
+                    "bundled": true
                 },
                 "split-on-first": {
                     "version": "1.1.0",
-                    "resolved": false,
-                    "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw=="
+                    "bundled": true
                 },
                 "sshpk": {
                     "version": "1.14.2",
-                    "resolved": false,
-                    "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
+                    "bundled": true,
                     "requires": {
                         "asn1": "~0.2.3",
                         "assert-plus": "^1.0.0",
@@ -14122,16 +13260,14 @@
                 },
                 "ssri": {
                     "version": "6.0.2",
-                    "resolved": false,
-                    "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==",
+                    "bundled": true,
                     "requires": {
                         "figgy-pudding": "^3.5.1"
                     }
                 },
                 "stream-each": {
                     "version": "1.2.2",
-                    "resolved": false,
-                    "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==",
+                    "bundled": true,
                     "requires": {
                         "end-of-stream": "^1.1.0",
                         "stream-shift": "^1.0.0"
@@ -14139,8 +13275,7 @@
                 },
                 "stream-iterate": {
                     "version": "1.2.0",
-                    "resolved": false,
-                    "integrity": "sha1-K9fHcpbBcCpGSIuK1B95hl7s1OE=",
+                    "bundled": true,
                     "requires": {
                         "readable-stream": "^2.1.5",
                         "stream-shift": "^1.0.0"
@@ -14148,8 +13283,7 @@
                     "dependencies": {
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": false,
-                            "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+                            "bundled": true,
                             "requires": {
                                 "core-util-is": "~1.0.0",
                                 "inherits": "~2.0.3",
@@ -14162,8 +13296,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": false,
-                            "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+                            "bundled": true,
                             "requires": {
                                 "safe-buffer": "~5.1.0"
                             }
@@ -14172,18 +13305,15 @@
                 },
                 "stream-shift": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI="
+                    "bundled": true
                 },
                 "strict-uri-encode": {
                     "version": "2.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY="
+                    "bundled": true
                 },
                 "string-width": {
                     "version": "2.1.1",
-                    "resolved": false,
-                    "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+                    "bundled": true,
                     "requires": {
                         "is-fullwidth-code-point": "^2.0.0",
                         "strip-ansi": "^4.0.0"
@@ -14191,18 +13321,15 @@
                     "dependencies": {
                         "ansi-regex": {
                             "version": "3.0.0",
-                            "resolved": false,
-                            "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
+                            "bundled": true
                         },
                         "is-fullwidth-code-point": {
                             "version": "2.0.0",
-                            "resolved": false,
-                            "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+                            "bundled": true
                         },
                         "strip-ansi": {
                             "version": "4.0.0",
-                            "resolved": false,
-                            "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+                            "bundled": true,
                             "requires": {
                                 "ansi-regex": "^3.0.0"
                             }
@@ -14211,54 +13338,46 @@
                 },
                 "string_decoder": {
                     "version": "1.3.0",
-                    "resolved": false,
-                    "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+                    "bundled": true,
                     "requires": {
                         "safe-buffer": "~5.2.0"
                     },
                     "dependencies": {
                         "safe-buffer": {
                             "version": "5.2.0",
-                            "resolved": false,
-                            "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
+                            "bundled": true
                         }
                     }
                 },
                 "stringify-package": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg=="
+                    "bundled": true
                 },
                 "strip-ansi": {
                     "version": "3.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+                    "bundled": true,
                     "requires": {
                         "ansi-regex": "^2.0.0"
                     }
                 },
                 "strip-eof": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
+                    "bundled": true
                 },
                 "strip-json-comments": {
                     "version": "2.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
+                    "bundled": true
                 },
                 "supports-color": {
                     "version": "5.4.0",
-                    "resolved": false,
-                    "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
+                    "bundled": true,
                     "requires": {
                         "has-flag": "^3.0.0"
                     }
                 },
                 "tar": {
                     "version": "4.4.19",
-                    "resolved": false,
-                    "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==",
+                    "bundled": true,
                     "requires": {
                         "chownr": "^1.1.4",
                         "fs-minipass": "^1.2.7",
@@ -14271,8 +13390,7 @@
                     "dependencies": {
                         "minipass": {
                             "version": "2.9.0",
-                            "resolved": false,
-                            "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
+                            "bundled": true,
                             "requires": {
                                 "safe-buffer": "^5.1.2",
                                 "yallist": "^3.0.0"
@@ -14280,38 +13398,32 @@
                         },
                         "safe-buffer": {
                             "version": "5.2.1",
-                            "resolved": false,
-                            "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+                            "bundled": true
                         },
                         "yallist": {
                             "version": "3.1.1",
-                            "resolved": false,
-                            "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+                            "bundled": true
                         }
                     }
                 },
                 "term-size": {
                     "version": "1.2.0",
-                    "resolved": false,
-                    "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=",
+                    "bundled": true,
                     "requires": {
                         "execa": "^0.7.0"
                     }
                 },
                 "text-table": {
                     "version": "0.2.0",
-                    "resolved": false,
-                    "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ="
+                    "bundled": true
                 },
                 "through": {
                     "version": "2.3.8",
-                    "resolved": false,
-                    "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
+                    "bundled": true
                 },
                 "through2": {
                     "version": "2.0.3",
-                    "resolved": false,
-                    "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
+                    "bundled": true,
                     "requires": {
                         "readable-stream": "^2.1.5",
                         "xtend": "~4.0.1"
@@ -14319,8 +13431,7 @@
                     "dependencies": {
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": false,
-                            "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+                            "bundled": true,
                             "requires": {
                                 "core-util-is": "~1.0.0",
                                 "inherits": "~2.0.3",
@@ -14333,8 +13444,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": false,
-                            "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+                            "bundled": true,
                             "requires": {
                                 "safe-buffer": "~5.1.0"
                             }
@@ -14343,18 +13453,15 @@
                 },
                 "timed-out": {
                     "version": "4.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8="
+                    "bundled": true
                 },
                 "tiny-relative-date": {
                     "version": "1.3.0",
-                    "resolved": false,
-                    "integrity": "sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A=="
+                    "bundled": true
                 },
                 "tough-cookie": {
                     "version": "2.4.3",
-                    "resolved": false,
-                    "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
+                    "bundled": true,
                     "requires": {
                         "psl": "^1.1.24",
                         "punycode": "^1.4.1"
@@ -14362,71 +13469,60 @@
                 },
                 "tunnel-agent": {
                     "version": "0.6.0",
-                    "resolved": false,
-                    "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+                    "bundled": true,
                     "requires": {
                         "safe-buffer": "^5.0.1"
                     }
                 },
                 "tweetnacl": {
                     "version": "0.14.5",
-                    "resolved": false,
-                    "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+                    "bundled": true,
                     "optional": true
                 },
                 "typedarray": {
                     "version": "0.0.6",
-                    "resolved": false,
-                    "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
+                    "bundled": true
                 },
                 "uid-number": {
                     "version": "0.0.6",
-                    "resolved": false,
-                    "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE="
+                    "bundled": true
                 },
                 "umask": {
                     "version": "1.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0="
+                    "bundled": true
                 },
                 "unique-filename": {
                     "version": "1.1.1",
-                    "resolved": false,
-                    "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
+                    "bundled": true,
                     "requires": {
                         "unique-slug": "^2.0.0"
                     }
                 },
                 "unique-slug": {
                     "version": "2.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=",
+                    "bundled": true,
                     "requires": {
                         "imurmurhash": "^0.1.4"
                     }
                 },
                 "unique-string": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=",
+                    "bundled": true,
                     "requires": {
                         "crypto-random-string": "^1.0.0"
                     }
                 },
                 "unpipe": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+                    "bundled": true
                 },
                 "unzip-response": {
                     "version": "2.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c="
+                    "bundled": true
                 },
                 "update-notifier": {
                     "version": "2.5.0",
-                    "resolved": false,
-                    "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==",
+                    "bundled": true,
                     "requires": {
                         "boxen": "^1.2.1",
                         "chalk": "^2.0.1",
@@ -14442,54 +13538,46 @@
                 },
                 "uri-js": {
                     "version": "4.4.0",
-                    "resolved": false,
-                    "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==",
+                    "bundled": true,
                     "requires": {
                         "punycode": "^2.1.0"
                     },
                     "dependencies": {
                         "punycode": {
                             "version": "2.1.1",
-                            "resolved": false,
-                            "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
+                            "bundled": true
                         }
                     }
                 },
                 "url-parse-lax": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=",
+                    "bundled": true,
                     "requires": {
                         "prepend-http": "^1.0.1"
                     }
                 },
                 "util-deprecate": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+                    "bundled": true
                 },
                 "util-extend": {
                     "version": "1.0.3",
-                    "resolved": false,
-                    "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8="
+                    "bundled": true
                 },
                 "util-promisify": {
                     "version": "2.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=",
+                    "bundled": true,
                     "requires": {
                         "object.getownpropertydescriptors": "^2.0.3"
                     }
                 },
                 "uuid": {
                     "version": "3.3.3",
-                    "resolved": false,
-                    "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
+                    "bundled": true
                 },
                 "validate-npm-package-license": {
                     "version": "3.0.4",
-                    "resolved": false,
-                    "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+                    "bundled": true,
                     "requires": {
                         "spdx-correct": "^3.0.0",
                         "spdx-expression-parse": "^3.0.0"
@@ -14497,16 +13585,14 @@
                 },
                 "validate-npm-package-name": {
                     "version": "3.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=",
+                    "bundled": true,
                     "requires": {
                         "builtins": "^1.0.3"
                     }
                 },
                 "verror": {
                     "version": "1.10.0",
-                    "resolved": false,
-                    "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+                    "bundled": true,
                     "requires": {
                         "assert-plus": "^1.0.0",
                         "core-util-is": "1.0.2",
@@ -14515,37 +13601,32 @@
                 },
                 "wcwidth": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
+                    "bundled": true,
                     "requires": {
                         "defaults": "^1.0.3"
                     }
                 },
                 "which": {
                     "version": "1.3.1",
-                    "resolved": false,
-                    "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+                    "bundled": true,
                     "requires": {
                         "isexe": "^2.0.0"
                     }
                 },
                 "which-module": {
                     "version": "2.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
+                    "bundled": true
                 },
                 "wide-align": {
                     "version": "1.1.2",
-                    "resolved": false,
-                    "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
+                    "bundled": true,
                     "requires": {
                         "string-width": "^1.0.2"
                     },
                     "dependencies": {
                         "string-width": {
                             "version": "1.0.2",
-                            "resolved": false,
-                            "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+                            "bundled": true,
                             "requires": {
                                 "code-point-at": "^1.0.0",
                                 "is-fullwidth-code-point": "^1.0.0",
@@ -14556,24 +13637,21 @@
                 },
                 "widest-line": {
                     "version": "2.0.1",
-                    "resolved": false,
-                    "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==",
+                    "bundled": true,
                     "requires": {
                         "string-width": "^2.1.1"
                     }
                 },
                 "worker-farm": {
                     "version": "1.7.0",
-                    "resolved": false,
-                    "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
+                    "bundled": true,
                     "requires": {
                         "errno": "~0.1.7"
                     }
                 },
                 "wrap-ansi": {
                     "version": "5.1.0",
-                    "resolved": false,
-                    "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+                    "bundled": true,
                     "requires": {
                         "ansi-styles": "^3.2.0",
                         "string-width": "^3.0.0",
@@ -14581,19 +13659,16 @@
                     },
                     "dependencies": {
                         "ansi-regex": {
-                            "version": "4.1.0",
-                            "resolved": false,
-                            "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+                            "version": "4.1.1",
+                            "bundled": true
                         },
                         "is-fullwidth-code-point": {
                             "version": "2.0.0",
-                            "resolved": false,
-                            "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+                            "bundled": true
                         },
                         "string-width": {
                             "version": "3.1.0",
-                            "resolved": false,
-                            "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+                            "bundled": true,
                             "requires": {
                                 "emoji-regex": "^7.0.1",
                                 "is-fullwidth-code-point": "^2.0.0",
@@ -14602,8 +13677,7 @@
                         },
                         "strip-ansi": {
                             "version": "5.2.0",
-                            "resolved": false,
-                            "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+                            "bundled": true,
                             "requires": {
                                 "ansi-regex": "^4.1.0"
                             }
@@ -14612,13 +13686,11 @@
                 },
                 "wrappy": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+                    "bundled": true
                 },
                 "write-file-atomic": {
                     "version": "2.4.3",
-                    "resolved": false,
-                    "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
+                    "bundled": true,
                     "requires": {
                         "graceful-fs": "^4.1.11",
                         "imurmurhash": "^0.1.4",
@@ -14627,28 +13699,23 @@
                 },
                 "xdg-basedir": {
                     "version": "3.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ="
+                    "bundled": true
                 },
                 "xtend": {
                     "version": "4.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
+                    "bundled": true
                 },
                 "y18n": {
                     "version": "4.0.1",
-                    "resolved": false,
-                    "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ=="
+                    "bundled": true
                 },
                 "yallist": {
                     "version": "3.0.3",
-                    "resolved": false,
-                    "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A=="
+                    "bundled": true
                 },
                 "yargs": {
                     "version": "14.2.3",
-                    "resolved": false,
-                    "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==",
+                    "bundled": true,
                     "requires": {
                         "cliui": "^5.0.0",
                         "decamelize": "^1.2.0",
@@ -14665,26 +13732,22 @@
                     "dependencies": {
                         "ansi-regex": {
                             "version": "4.1.0",
-                            "resolved": false,
-                            "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+                            "bundled": true
                         },
                         "find-up": {
                             "version": "3.0.0",
-                            "resolved": false,
-                            "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+                            "bundled": true,
                             "requires": {
                                 "locate-path": "^3.0.0"
                             }
                         },
                         "is-fullwidth-code-point": {
                             "version": "2.0.0",
-                            "resolved": false,
-                            "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+                            "bundled": true
                         },
                         "locate-path": {
                             "version": "3.0.0",
-                            "resolved": false,
-                            "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+                            "bundled": true,
                             "requires": {
                                 "p-locate": "^3.0.0",
                                 "path-exists": "^3.0.0"
@@ -14692,29 +13755,25 @@
                         },
                         "p-limit": {
                             "version": "2.3.0",
-                            "resolved": false,
-                            "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+                            "bundled": true,
                             "requires": {
                                 "p-try": "^2.0.0"
                             }
                         },
                         "p-locate": {
                             "version": "3.0.0",
-                            "resolved": false,
-                            "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+                            "bundled": true,
                             "requires": {
                                 "p-limit": "^2.0.0"
                             }
                         },
                         "p-try": {
                             "version": "2.2.0",
-                            "resolved": false,
-                            "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
+                            "bundled": true
                         },
                         "string-width": {
                             "version": "3.1.0",
-                            "resolved": false,
-                            "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+                            "bundled": true,
                             "requires": {
                                 "emoji-regex": "^7.0.1",
                                 "is-fullwidth-code-point": "^2.0.0",
@@ -14723,8 +13782,7 @@
                         },
                         "strip-ansi": {
                             "version": "5.2.0",
-                            "resolved": false,
-                            "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+                            "bundled": true,
                             "requires": {
                                 "ansi-regex": "^4.1.0"
                             }
@@ -14733,8 +13791,7 @@
                 },
                 "yargs-parser": {
                     "version": "15.0.1",
-                    "resolved": false,
-                    "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==",
+                    "bundled": true,
                     "requires": {
                         "camelcase": "^5.0.0",
                         "decamelize": "^1.2.0"
@@ -14742,8 +13799,7 @@
                     "dependencies": {
                         "camelcase": {
                             "version": "5.3.1",
-                            "resolved": false,
-                            "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
+                            "bundled": true
                         }
                     }
                 }
@@ -14752,26 +13808,26 @@
         "npm-run-path": {
             "version": "2.0.2",
             "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
-            "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+            "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==",
             "requires": {
                 "path-key": "^2.0.0"
             }
         },
         "npmlog": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
-            "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
+            "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
             "requires": {
-                "are-we-there-yet": "~1.1.2",
-                "console-control-strings": "~1.1.0",
-                "gauge": "~2.7.3",
-                "set-blocking": "~2.0.0"
+                "are-we-there-yet": "^2.0.0",
+                "console-control-strings": "^1.1.0",
+                "gauge": "^3.0.0",
+                "set-blocking": "^2.0.0"
             }
         },
         "nth-check": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
-            "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+            "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
             "requires": {
                 "boolbase": "^1.0.0"
             }
@@ -14779,7 +13835,7 @@
         "number-is-nan": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
-            "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+            "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ=="
         },
         "nwsapi": {
             "version": "2.2.0",
@@ -14790,7 +13846,7 @@
         "oauth": {
             "version": "0.9.15",
             "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz",
-            "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE="
+            "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA=="
         },
         "oauth-sign": {
             "version": "0.9.0",
@@ -14800,12 +13856,12 @@
         "object-assign": {
             "version": "4.1.1",
             "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-            "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+            "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
         },
         "object-copy": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
-            "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+            "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==",
             "requires": {
                 "copy-descriptor": "^0.1.0",
                 "define-property": "^0.2.5",
@@ -14815,7 +13871,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -14828,7 +13884,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -14836,9 +13892,9 @@
             }
         },
         "object-inspect": {
-            "version": "1.7.0",
-            "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
-            "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw=="
+            "version": "1.12.2",
+            "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
+            "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ=="
         },
         "object-is": {
             "version": "1.1.5",
@@ -14866,6 +13922,11 @@
                 "unpack-string": "0.0.2"
             },
             "dependencies": {
+                "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=="
+                },
                 "inspect-parameters-declaration": {
                     "version": "0.0.10",
                     "resolved": "https://registry.npmjs.org/inspect-parameters-declaration/-/inspect-parameters-declaration-0.0.10.tgz",
@@ -14880,7 +13941,7 @@
                 "magicli": {
                     "version": "0.0.5",
                     "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
-                    "integrity": "sha1-zufQ+7THBRiqyxHsPrfiX/SaSSE=",
+                    "integrity": "sha512-wZbMtnl2v1b+Jp3xlqA9FU/O4I6YhGXR8xSY/eU2+gDAvut/F+W3gl4qs61iL4LELC7jqSAE6aAD5668EbmQHA==",
                     "requires": {
                         "commander": "^2.9.0",
                         "get-stdin": "^5.0.1",
@@ -14893,7 +13954,7 @@
         "object-visit": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
-            "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+            "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==",
             "requires": {
                 "isobject": "^3.0.0"
             }
@@ -14910,18 +13971,20 @@
             }
         },
         "object.getownpropertydescriptors": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz",
-            "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==",
+            "version": "2.1.4",
+            "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.4.tgz",
+            "integrity": "sha512-sccv3L/pMModT6dJAYF3fzGMVcb38ysQ0tEE6ixv2yXJDtEIPph268OlAdJj5/qZMZDq2g/jqvwppt36uS/uQQ==",
             "requires": {
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.17.0-next.1"
+                "array.prototype.reduce": "^1.0.4",
+                "call-bind": "^1.0.2",
+                "define-properties": "^1.1.4",
+                "es-abstract": "^1.20.1"
             }
         },
         "object.pick": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
-            "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+            "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==",
             "requires": {
                 "isobject": "^3.0.1"
             }
@@ -14933,9 +13996,9 @@
             "dev": true
         },
         "on-finished": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
-            "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+            "version": "2.4.1",
+            "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+            "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
             "requires": {
                 "ee-first": "1.1.1"
             }
@@ -14948,7 +14011,7 @@
         "once": {
             "version": "1.4.0",
             "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-            "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+            "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
             "requires": {
                 "wrappy": "1"
             }
@@ -14980,9 +14043,12 @@
             }
         },
         "optional-require": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz",
-            "integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA=="
+            "version": "1.1.8",
+            "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz",
+            "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==",
+            "requires": {
+                "require-at": "^1.0.6"
+            }
         },
         "optionator": {
             "version": "0.8.3",
@@ -14999,28 +14065,19 @@
             }
         },
         "orderedmap": {
-            "version": "1.1.5",
-            "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-1.1.5.tgz",
-            "integrity": "sha512-/fzlCGKRmfayGoI9UUXvJfc2nMZlJHW30QqEvwPvlg8tsX7jyiUSomYie6mYqx7Z9bOMGoag0H/q1PS/0PjYkg=="
-        },
-        "original": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
-            "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==",
-            "dev": true,
-            "requires": {
-                "url-parse": "^1.4.3"
-            }
+            "version": "1.1.8",
+            "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-1.1.8.tgz",
+            "integrity": "sha512-eWEYOAggZZpZbJ9CTsqAKOTxlbBHdHZ8pzcfEvNTxGrjQ/m+Q25nSWUiMlT9MTbgpB6FOiBDKqsgJ2FlLDVNaw=="
         },
         "os-homedir": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
-            "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
+            "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ=="
         },
         "os-tmpdir": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
-            "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
+            "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="
         },
         "osenv": {
             "version": "0.1.5",
@@ -15039,12 +14096,12 @@
         "p-debounce": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/p-debounce/-/p-debounce-1.0.0.tgz",
-            "integrity": "sha1-y38svu/YegnrqGHhErZ1J+Yh4v0="
+            "integrity": "sha512-ttOxn4Yt0hzIsLLqKi/Ry9QRxW+UQKdoWHz7g99Ci57zPkqUU3kbWKAeHuv+HfRLe109acYLUY6kuVCOOqnt4g=="
         },
         "p-finally": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
-            "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
+            "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow=="
         },
         "p-limit": {
             "version": "2.3.0",
@@ -15085,7 +14142,7 @@
         "package-json": {
             "version": "4.0.1",
             "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz",
-            "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=",
+            "integrity": "sha512-q/R5GrMek0vzgoomq6rm9OX+3PQve8sLwTirmK30YB3Cu0Bbt9OX9M/SIUnroN5BGJkzwGsFwDaRGD9EwBOlCA==",
             "requires": {
                 "got": "^6.7.1",
                 "registry-auth-token": "^3.0.1",
@@ -15093,10 +14150,15 @@
                 "semver": "^5.1.0"
             },
             "dependencies": {
+                "get-stream": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+                    "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ=="
+                },
                 "got": {
                     "version": "6.7.1",
                     "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
-                    "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
+                    "integrity": "sha512-Y/K3EDuiQN9rTZhBvPRWMLXIKdeD1Rj0nzunfoi0Yyn5WBEbzxXKU9Ub2X41oZBagVWOBU3MuDonFMgPWQFnwg==",
                     "requires": {
                         "create-error-class": "^3.0.0",
                         "duplexer3": "^0.1.4",
@@ -15158,13 +14220,6 @@
             "requires": {
                 "dot-case": "^3.0.4",
                 "tslib": "^2.0.3"
-            },
-            "dependencies": {
-                "tslib": {
-                    "version": "2.3.1",
-                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
-                    "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
-                }
             }
         },
         "parent-module": {
@@ -15186,6 +14241,12 @@
                 "lines-and-columns": "^1.1.6"
             }
         },
+        "parse5": {
+            "version": "5.1.0",
+            "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz",
+            "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
+            "dev": true
+        },
         "parseqs": {
             "version": "0.0.6",
             "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz",
@@ -15208,19 +14269,12 @@
             "requires": {
                 "no-case": "^3.0.4",
                 "tslib": "^2.0.3"
-            },
-            "dependencies": {
-                "tslib": {
-                    "version": "2.3.1",
-                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
-                    "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
-                }
             }
         },
         "pascalcase": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
-            "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="
+            "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw=="
         },
         "passport": {
             "version": "0.4.1",
@@ -15242,15 +14296,15 @@
         "passport-local": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
-            "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=",
+            "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==",
             "requires": {
                 "passport-strategy": "1.x.x"
             }
         },
         "passport-oauth2": {
-            "version": "1.5.0",
-            "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.5.0.tgz",
-            "integrity": "sha512-kqBt6vR/5VlCK8iCx1/KpY42kQ+NEHZwsSyt4Y6STiNjU+wWICG1i8ucc1FapXDGO15C5O5VZz7+7vRzrDPXXQ==",
+            "version": "1.6.1",
+            "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.6.1.tgz",
+            "integrity": "sha512-ZbV43Hq9d/SBSYQ22GOiglFsjsD1YY/qdiptA+8ej+9C1dL1TVB+mBE5kDH/D4AJo50+2i8f4bx0vg4/yDDZCQ==",
             "requires": {
                 "base64url": "3.x.x",
                 "oauth": "0.9.x",
@@ -15262,7 +14316,7 @@
         "passport-strategy": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
-            "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ="
+            "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA=="
         },
         "path-browserify": {
             "version": "1.0.1",
@@ -15272,37 +14326,37 @@
         "path-dirname": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
-            "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA="
+            "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q=="
         },
         "path-exists": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
-            "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
+            "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="
         },
         "path-is-absolute": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-            "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+            "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
         },
         "path-is-inside": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
-            "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM="
+            "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w=="
         },
         "path-key": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
-            "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
+            "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="
         },
         "path-parse": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
-            "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
+            "version": "1.0.7",
+            "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+            "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
         },
         "path-to-regexp": {
             "version": "0.1.7",
             "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
-            "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+            "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
         },
         "path-type": {
             "version": "4.0.0",
@@ -15317,7 +14371,7 @@
         "pause": {
             "version": "0.0.1",
             "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
-            "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10="
+            "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg=="
         },
         "pdf-parse": {
             "version": "1.1.1",
@@ -15354,17 +14408,18 @@
             }
         },
         "pdfjs-dist": {
-            "version": "2.13.216",
-            "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.13.216.tgz",
-            "integrity": "sha512-qn/9a/3IHIKZarTK6ajeeFXBkG15Lg1Fx99PxU09PAU2i874X8mTcHJYyDJxu7WDfNhV6hM7bRQBZU384anoqQ==",
+            "version": "2.14.305",
+            "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.14.305.tgz",
+            "integrity": "sha512-5f7i25J1dKIBczhgfxEgNxfYNIxXEdxqo6Qb4ehY7Ja+p6AI4uUmk/OcVGXfRGm2ys5iaJJhJUwBFwv6Jl/Qww==",
             "requires": {
-                "web-streams-polyfill": "^3.2.0"
+                "dommatrix": "^1.0.1",
+                "web-streams-polyfill": "^3.2.1"
             }
         },
         "pend": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
-            "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
+            "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="
         },
         "perfect-scrollbar": {
             "version": "1.5.5",
@@ -15374,7 +14429,7 @@
         "performance-now": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
-            "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
+            "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
         },
         "picocolors": {
             "version": "1.0.0",
@@ -15384,24 +14439,22 @@
         "picomatch": {
             "version": "2.3.1",
             "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
-            "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-            "dev": true
+            "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
         },
         "pify": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
-            "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
-            "dev": true
+            "version": "2.3.0",
+            "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+            "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="
         },
         "pinkie": {
             "version": "2.0.4",
             "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
-            "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
+            "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg=="
         },
         "pinkie-promise": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
-            "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+            "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==",
             "requires": {
                 "pinkie": "^2.0.0"
             }
@@ -15412,56 +14465,42 @@
             "integrity": "sha512-6Rtbp7criZRwedlvWbUYxqlqJoAlMvYHo2UcRWq79xZ54vZcaNHpVBOcWkX3ErT2aUA69tv+uiv4zKJbhD/Wgg=="
         },
         "pkg-dir": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
-            "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
-            "dev": true,
+            "version": "4.2.0",
+            "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+            "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
             "requires": {
-                "find-up": "^2.1.0"
+                "find-up": "^4.0.0"
             },
             "dependencies": {
                 "find-up": {
-                    "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
-                    "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
-                    "dev": true,
+                    "version": "4.1.0",
+                    "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+                    "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
                     "requires": {
-                        "locate-path": "^2.0.0"
+                        "locate-path": "^5.0.0",
+                        "path-exists": "^4.0.0"
                     }
                 },
                 "locate-path": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
-                    "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
-                    "dev": true,
-                    "requires": {
-                        "p-locate": "^2.0.0",
-                        "path-exists": "^3.0.0"
-                    }
-                },
-                "p-limit": {
-                    "version": "1.3.0",
-                    "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
-                    "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
-                    "dev": true,
+                    "version": "5.0.0",
+                    "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+                    "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
                     "requires": {
-                        "p-try": "^1.0.0"
+                        "p-locate": "^4.1.0"
                     }
                 },
                 "p-locate": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
-                    "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
-                    "dev": true,
+                    "version": "4.1.0",
+                    "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+                    "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
                     "requires": {
-                        "p-limit": "^1.1.0"
+                        "p-limit": "^2.2.0"
                     }
                 },
-                "p-try": {
-                    "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
-                    "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
-                    "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=="
                 }
             }
         },
@@ -15476,7 +14515,7 @@
         "plist": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/plist/-/plist-1.2.0.tgz",
-            "integrity": "sha1-CEtQk93JJQbiWfh0uNmxr7jHlZM=",
+            "integrity": "sha512-dL9Xc2Aj3YyBnwvCNuHmFl2LWvQacm/HEAsoVwLiuu0POboMChETt5wexpU1P6F6MnibIucXlVsMFFgNUT2IyA==",
             "requires": {
                 "base64-js": "0.0.8",
                 "util-deprecate": "1.0.2",
@@ -15487,7 +14526,7 @@
                 "base64-js": {
                     "version": "0.0.8",
                     "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
-                    "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg="
+                    "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw=="
                 }
             }
         },
@@ -15514,12 +14553,12 @@
             },
             "dependencies": {
                 "mkdirp": {
-                    "version": "0.5.5",
-                    "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
-                    "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+                    "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.5"
+                        "minimist": "^1.2.6"
                     }
                 }
             }
@@ -15527,33 +14566,29 @@
         "posix-character-classes": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
-            "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
+            "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg=="
         },
         "postcss": {
-            "version": "7.0.27",
-            "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz",
-            "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==",
+            "version": "7.0.39",
+            "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+            "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
             "dev": true,
             "requires": {
-                "chalk": "^2.4.2",
-                "source-map": "^0.6.1",
-                "supports-color": "^6.1.0"
+                "picocolors": "^0.2.1",
+                "source-map": "^0.6.1"
             },
             "dependencies": {
+                "picocolors": {
+                    "version": "0.2.1",
+                    "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+                    "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+                    "dev": true
+                },
                 "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
-                },
-                "supports-color": {
-                    "version": "6.1.0",
-                    "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
-                    "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
-                    "dev": true,
-                    "requires": {
-                        "has-flag": "^3.0.0"
-                    }
                 }
             }
         },
@@ -15598,14 +14633,13 @@
             }
         },
         "postcss-selector-parser": {
-            "version": "6.0.2",
-            "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz",
-            "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==",
+            "version": "6.0.10",
+            "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
+            "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
             "dev": true,
             "requires": {
                 "cssesc": "^3.0.0",
-                "indexes-of": "^1.0.1",
-                "uniq": "^1.0.1"
+                "util-deprecate": "^1.0.2"
             }
         },
         "postcss-value-parser": {
@@ -15614,15 +14648,15 @@
             "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="
         },
         "prebuild-install": {
-            "version": "5.3.3",
-            "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.3.tgz",
-            "integrity": "sha512-GV+nsUXuPW2p8Zy7SarF/2W/oiK8bFQgJcncoJ0d7kRpekEA0ftChjfEaF9/Y+QJEc/wFR7RAEa8lYByuUIe2g==",
+            "version": "5.3.6",
+            "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz",
+            "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==",
             "requires": {
                 "detect-libc": "^1.0.3",
                 "expand-template": "^2.0.3",
                 "github-from-package": "0.0.0",
-                "minimist": "^1.2.0",
-                "mkdirp": "^0.5.1",
+                "minimist": "^1.2.3",
+                "mkdirp-classic": "^0.5.3",
                 "napi-build-utils": "^1.0.1",
                 "node-abi": "^2.7.0",
                 "noop-logger": "^0.1.1",
@@ -15633,18 +14667,110 @@
                 "tar-fs": "^2.0.0",
                 "tunnel-agent": "^0.6.0",
                 "which-pm-runs": "^1.0.0"
+            },
+            "dependencies": {
+                "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=="
+                },
+                "aproba": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                    "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+                },
+                "are-we-there-yet": {
+                    "version": "1.1.7",
+                    "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
+                    "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
+                    "requires": {
+                        "delegates": "^1.0.0",
+                        "readable-stream": "^2.0.6"
+                    }
+                },
+                "detect-libc": {
+                    "version": "1.0.3",
+                    "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+                    "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="
+                },
+                "gauge": {
+                    "version": "2.7.4",
+                    "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+                    "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==",
+                    "requires": {
+                        "aproba": "^1.0.3",
+                        "console-control-strings": "^1.0.0",
+                        "has-unicode": "^2.0.0",
+                        "object-assign": "^4.1.0",
+                        "signal-exit": "^3.0.0",
+                        "string-width": "^1.0.1",
+                        "strip-ansi": "^3.0.1",
+                        "wide-align": "^1.1.0"
+                    }
+                },
+                "is-fullwidth-code-point": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+                    "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==",
+                    "requires": {
+                        "number-is-nan": "^1.0.0"
+                    }
+                },
+                "npmlog": {
+                    "version": "4.1.2",
+                    "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+                    "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+                    "requires": {
+                        "are-we-there-yet": "~1.1.2",
+                        "console-control-strings": "~1.1.0",
+                        "gauge": "~2.7.3",
+                        "set-blocking": "~2.0.0"
+                    }
+                },
+                "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"
+                    }
+                },
+                "string-width": {
+                    "version": "1.0.2",
+                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+                    "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+                    "requires": {
+                        "code-point-at": "^1.0.0",
+                        "is-fullwidth-code-point": "^1.0.0",
+                        "strip-ansi": "^3.0.0"
+                    }
+                },
+                "strip-ansi": {
+                    "version": "3.0.1",
+                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+                    "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+                    "requires": {
+                        "ansi-regex": "^2.0.0"
+                    }
+                }
             }
         },
         "prelude-ls": {
             "version": "1.1.2",
             "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
-            "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+            "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
             "dev": true
         },
         "prepend-http": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
-            "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
+            "integrity": "sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg=="
         },
         "pretty-error": {
             "version": "4.0.0",
@@ -15678,7 +14804,7 @@
         "process": {
             "version": "0.11.10",
             "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
-            "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
+            "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="
         },
         "process-nextick-args": {
             "version": "2.0.1",
@@ -15701,23 +14827,23 @@
         "promise-inflight": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
-            "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
+            "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
             "dev": true
         },
         "prop-types": {
-            "version": "15.7.2",
-            "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
-            "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
+            "version": "15.8.1",
+            "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+            "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
             "requires": {
                 "loose-envify": "^1.4.0",
                 "object-assign": "^4.1.1",
-                "react-is": "^16.8.1"
+                "react-is": "^16.13.1"
             }
         },
         "prosemirror-commands": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.2.1.tgz",
-            "integrity": "sha512-S/IkpXfpuLFsRynC2HQ5iYROUPiZskKS1+ClcWycGJvj4HMb/mVfeEkQrixYxgTl96EAh+RZQNWPC06GZXk5tQ==",
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.3.0.tgz",
+            "integrity": "sha512-BwBbZ5OAScPcm0x7H8SPbqjuEJnCU2RJT9LDyOiiIl/3NbL1nJZI4SFNHwU2e/tRr2Xe7JsptpzseqvZvToLBQ==",
             "requires": {
                 "prosemirror-model": "^1.0.0",
                 "prosemirror-state": "^1.0.0",
@@ -15747,12 +14873,12 @@
         "prosemirror-find-replace": {
             "version": "0.9.0",
             "resolved": "https://registry.npmjs.org/prosemirror-find-replace/-/prosemirror-find-replace-0.9.0.tgz",
-            "integrity": "sha1-QgsENNF5xdBJD44hSNhVGpVJY4I="
+            "integrity": "sha512-LfhQ/Zr0PkkJpCsr9vTJ5ZPYh49mSVVG+hHJ6djT+chlCW+t2ilSxBpBG+2IeE/I5nlbcvuLLAbxeI1g3pTCpA=="
         },
         "prosemirror-history": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.2.0.tgz",
-            "integrity": "sha512-B9v9xtf4fYbKxQwIr+3wtTDNLDZcmMMmGiI3TAPShnUzvo+Rmv1GiUrsQChY1meetHl7rhML2cppF3FTs7f7UQ==",
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.3.0.tgz",
+            "integrity": "sha512-qo/9Wn4B/Bq89/YD+eNWFbAytu6dmIM85EhID+fz9Jcl9+DfGEo8TTSrRhP15+fFEoaPqpHSxlvSzSEbmlxlUA==",
             "requires": {
                 "prosemirror-state": "^1.2.2",
                 "prosemirror-transform": "^1.0.0",
@@ -15760,61 +14886,62 @@
             }
         },
         "prosemirror-inputrules": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.1.3.tgz",
-            "integrity": "sha512-ZaHCLyBtvbyIHv0f5p6boQTIJjlD6o2NPZiEaZWT2DA+j591zS29QQEMT4lBqwcLW3qRSf7ZvoKNbf05YrsStw==",
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.2.0.tgz",
+            "integrity": "sha512-eAW/M/NTSSzpCOxfR8Abw6OagdG0MiDAiWHQMQveIsZtoKVYzm0AflSPq/ymqJd56/Su1YPbwy9lM13wgHOFmQ==",
             "requires": {
                 "prosemirror-state": "^1.0.0",
                 "prosemirror-transform": "^1.0.0"
             }
         },
         "prosemirror-keymap": {
-            "version": "1.1.5",
-            "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.1.5.tgz",
-            "integrity": "sha512-8SZgPH3K+GLsHL2wKuwBD9rxhsbnVBTwpHCO4VUO5GmqUQlxd/2GtBVWTsyLq4Dp3N9nGgPd3+lZFKUDuVp+Vw==",
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.0.tgz",
+            "integrity": "sha512-TdSfu+YyLDd54ufN/ZeD1VtBRYpgZnTPnnbY+4R08DDgs84KrIPEPbJL8t1Lm2dkljFx6xeBE26YWH3aIzkPKg==",
             "requires": {
                 "prosemirror-state": "^1.0.0",
                 "w3c-keyname": "^2.2.0"
             }
         },
         "prosemirror-model": {
-            "version": "1.16.1",
-            "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.16.1.tgz",
-            "integrity": "sha512-r1/w0HDU40TtkXp0DyKBnFPYwd8FSlUSJmGCGFv4DeynfeSlyQF2FD0RQbVEMOe6P3PpUSXM6LZBV7W/YNZ4mA==",
+            "version": "1.17.0",
+            "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.17.0.tgz",
+            "integrity": "sha512-RJBDgZs/W26yyx1itrk5b3H9FxIro3K7Xjc2QWJI99Gu1nxYAnIggqI3fIOD8Jd/6QZfM+t6elZFJPycVexMTA==",
             "requires": {
                 "orderedmap": "^1.1.0"
             }
         },
         "prosemirror-schema-list": {
-            "version": "1.1.6",
-            "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.1.6.tgz",
-            "integrity": "sha512-aFGEdaCWmJzouZ8DwedmvSsL50JpRkqhQ6tcpThwJONVVmCgI36LJHtoQ4VGZbusMavaBhXXr33zyD2IVsTlkw==",
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.2.0.tgz",
+            "integrity": "sha512-8PT/9xOx1HHdC7fDNNfhQ50Z8Mzu7nKyA1KCDltSpcZVZIbB0k7KtsHrnXyuIhbLlScoymBiLZ00c5MH6wdFsA==",
             "requires": {
                 "prosemirror-model": "^1.0.0",
+                "prosemirror-state": "^1.0.0",
                 "prosemirror-transform": "^1.0.0"
             }
         },
         "prosemirror-state": {
-            "version": "1.3.4",
-            "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.3.4.tgz",
-            "integrity": "sha512-Xkkrpd1y/TQ6HKzN3agsQIGRcLckUMA9u3j207L04mt8ToRgpGeyhbVv0HI7omDORIBHjR29b7AwlATFFf2GLA==",
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.0.tgz",
+            "integrity": "sha512-mVDZdjNX/YT5FvypiwbphJe9psA5h+j9apsSszVRFc6oKFoIInvzdujh8QW9f9lwHtSYajLxNiM1hPhd0Sl1XA==",
             "requires": {
                 "prosemirror-model": "^1.0.0",
                 "prosemirror-transform": "^1.0.0"
             }
         },
         "prosemirror-transform": {
-            "version": "1.3.4",
-            "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.3.4.tgz",
-            "integrity": "sha512-gTsg3UIeaFuEY6+YmNPMgTpEkCKPedkFIUnsPpOMbclU701fEVI/e4VOXACXh3BO5rZJaBbEBwrnzB0mLp6eBA==",
+            "version": "1.6.0",
+            "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.6.0.tgz",
+            "integrity": "sha512-MAp7AjsjEGEqQY0sSMufNIUuEyB1ZR9Fqlm8dTwwWwpEJRv/plsKjWXBbx52q3Ml8MtaMcd7ic14zAHVB3WaMw==",
             "requires": {
                 "prosemirror-model": "^1.0.0"
             }
         },
         "prosemirror-view": {
-            "version": "1.23.7",
-            "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.23.7.tgz",
-            "integrity": "sha512-ugY+g/4UI2Ree1zzdvbyQWF2KpbFa7kxKMLHaEJcxiPaErnZiD5wZFqIgFinc7fY2v/QM3DLnJ++2I45ULRdrg==",
+            "version": "1.25.0",
+            "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.25.0.tgz",
+            "integrity": "sha512-9eJ7VYOqUl/l2P3Q126PoUhfrWAGF0GU4zHXZssbVnhqLZBKpHTcTYx1W9DMg1PCuS69sHLMJdm3UFHmD5SGdw==",
             "requires": {
                 "prosemirror-model": "^1.16.0",
                 "prosemirror-state": "^1.0.0",
@@ -15838,13 +14965,13 @@
         "prr": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
-            "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
+            "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==",
             "dev": true
         },
         "pseudomap": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
-            "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
+            "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ=="
         },
         "psl": {
             "version": "1.8.0",
@@ -15852,9 +14979,9 @@
             "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
         },
         "pstree.remy": {
-            "version": "1.1.7",
-            "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.7.tgz",
-            "integrity": "sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A=="
+            "version": "1.1.8",
+            "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
+            "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w=="
         },
         "pug": {
             "version": "2.0.4",
@@ -15882,9 +15009,9 @@
             }
         },
         "pug-code-gen": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.2.tgz",
-            "integrity": "sha512-kROFWv/AHx/9CRgoGJeRSm+4mLWchbgpRzTEn8XCiwwOy6Vh0gAClS8Vh5TEJ9DBjaP8wCjS3J6HKsEsYdvaCw==",
+            "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",
@@ -15913,6 +15040,21 @@
                 "pug-walk": "^1.1.8",
                 "resolve": "^1.1.6",
                 "uglify-js": "^2.6.1"
+            },
+            "dependencies": {
+                "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"
+                    }
+                },
+                "source-map": {
+                    "version": "0.6.1",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+                    "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+                }
             }
         },
         "pug-lexer": {
@@ -16030,11 +15172,11 @@
                     "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g=="
                 },
                 "debug": {
-                    "version": "4.1.1",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+                    "version": "4.3.4",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+                    "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
                     "requires": {
-                        "ms": "^2.1.1"
+                        "ms": "2.1.2"
                     }
                 },
                 "https-proxy-agent": {
@@ -16047,21 +15189,26 @@
                     }
                 },
                 "mime": {
-                    "version": "2.4.6",
-                    "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz",
-                    "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA=="
+                    "version": "2.6.0",
+                    "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+                    "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg=="
+                },
+                "ms": {
+                    "version": "2.1.2",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+                    "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
                 }
             }
         },
         "pure-color": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz",
-            "integrity": "sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4="
+            "integrity": "sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA=="
         },
         "q": {
             "version": "1.5.1",
             "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
-            "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc="
+            "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw=="
         },
         "qs": {
             "version": "6.5.3",
@@ -16082,7 +15229,7 @@
         "querystring": {
             "version": "0.2.0",
             "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
-            "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
+            "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==",
             "dev": true
         },
         "querystringify": {
@@ -16104,7 +15251,7 @@
         "random-bytes": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
-            "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
+            "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ=="
         },
         "randombytes": {
             "version": "2.1.0",
@@ -16121,14 +15268,24 @@
             "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
         },
         "raw-body": {
-            "version": "2.4.3",
-            "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz",
-            "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==",
+            "version": "2.5.1",
+            "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
+            "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
             "requires": {
                 "bytes": "3.1.2",
-                "http-errors": "1.8.1",
+                "http-errors": "2.0.0",
                 "iconv-lite": "0.4.24",
                 "unpipe": "1.0.0"
+            },
+            "dependencies": {
+                "iconv-lite": {
+                    "version": "0.4.24",
+                    "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+                    "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+                    "requires": {
+                        "safer-buffer": ">= 2.1.2 < 3"
+                    }
+                }
             }
         },
         "raw-loader": {
@@ -16138,18 +15295,6 @@
             "requires": {
                 "loader-utils": "^1.1.0",
                 "schema-utils": "^1.0.0"
-            },
-            "dependencies": {
-                "schema-utils": {
-                    "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
-                    "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
-                    "requires": {
-                        "ajv": "^6.1.0",
-                        "ajv-errors": "^1.0.0",
-                        "ajv-keywords": "^3.1.0"
-                    }
-                }
             }
         },
         "rc": {
@@ -16256,6 +15401,13 @@
                 "d3-array": "^1.2.4",
                 "prop-types": "^15.7.2",
                 "warning": "^3.0.0"
+            },
+            "dependencies": {
+                "d3-array": {
+                    "version": "1.2.4",
+                    "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
+                    "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
+                }
             }
         },
         "react-datepicker": {
@@ -16302,12 +15454,12 @@
             }
         },
         "react-draggable": {
-            "version": "4.4.3",
-            "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.3.tgz",
-            "integrity": "sha512-jV4TE59MBuWm7gb6Ns3Q1mxX8Azffb7oTtDtBgFkxRvhDp38YAARmRplrj0+XGkhOJB5XziArX+4HUUABtyZ0w==",
+            "version": "4.4.5",
+            "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.5.tgz",
+            "integrity": "sha512-OMHzJdyJbYTZo4uQE393fHcqqPYsEtkjfMgvCHr6rejT+Ezn4OZbNyGH50vv+SunC1RMvwOTSWkEODQLzw1M9g==",
             "requires": {
-                "classnames": "^2.2.5",
-                "prop-types": "^15.6.0"
+                "clsx": "^1.1.1",
+                "prop-types": "^15.8.1"
             }
         },
         "react-event-listener": {
@@ -16343,9 +15495,9 @@
             }
         },
         "react-icons": {
-            "version": "4.3.1",
-            "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.3.1.tgz",
-            "integrity": "sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ=="
+            "version": "4.4.0",
+            "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.4.0.tgz",
+            "integrity": "sha512-fSbvHeVYo/B5/L4VhB7sBA1i2tS8MkT0Hb9t2H1AVPkwGfVHLJCqyr2Py9dKMxsyM63Eng1GkdZfbWj+Fmv8Rg=="
         },
         "react-image-lightbox-with-rotate": {
             "version": "5.1.1",
@@ -16395,9 +15547,9 @@
             },
             "dependencies": {
                 "@types/react": {
-                    "version": "17.0.39",
-                    "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz",
-                    "integrity": "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==",
+                    "version": "17.0.45",
+                    "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.45.tgz",
+                    "integrity": "sha512-YfhQ22Lah2e3CHPsb93tRwIGNiSwkuz1/blk4e6QrWS0jQzCSNbGLtOEYhPg02W0yGTTmpajp7dCTbBAMN3qsg==",
                     "optional": true,
                     "requires": {
                         "@types/prop-types": "*",
@@ -16406,28 +15558,23 @@
                     }
                 },
                 "@types/react-dom": {
-                    "version": "17.0.11",
-                    "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz",
-                    "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==",
+                    "version": "17.0.17",
+                    "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.17.tgz",
+                    "integrity": "sha512-VjnqEmqGnasQKV0CWLevqMTXBYG9GbwuE6x3VetERLh0cq2LTptFE73MrQi2S7GkKXCf2GgwItB/melLnxfnsg==",
                     "optional": true,
                     "requires": {
-                        "@types/react": "*"
+                        "@types/react": "^17"
                     }
                 },
-                "acorn": {
-                    "version": "8.7.0",
-                    "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
-                    "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ=="
-                },
                 "core-js": {
-                    "version": "3.21.1",
-                    "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz",
-                    "integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig=="
+                    "version": "3.22.8",
+                    "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.8.tgz",
+                    "integrity": "sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA=="
                 },
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==",
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==",
                     "optional": true
                 }
             }
@@ -16459,12 +15606,12 @@
             "integrity": "sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ=="
         },
         "react-modal": {
-            "version": "3.11.2",
-            "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.11.2.tgz",
-            "integrity": "sha512-o8gvvCOFaG1T7W6JUvsYjRjMVToLZgLIsi5kdhFIQCtHxDkA47LznX62j+l6YQkpXDbvQegsDyxe/+JJsFQN7w==",
+            "version": "3.15.1",
+            "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.15.1.tgz",
+            "integrity": "sha512-duB9bxOaYg7Zt6TMFldIFxQRtSP+Dg3F1ZX3FXxSUn+3tZZ/9JCgeAQKDg7rhZSAqopq8TFRw3yIbnx77gyFTw==",
             "requires": {
                 "exenv": "^1.2.0",
-                "prop-types": "^15.5.10",
+                "prop-types": "^15.7.2",
                 "react-lifecycles-compat": "^3.0.0",
                 "warning": "^4.0.3"
             },
@@ -16524,9 +15671,9 @@
             }
         },
         "react-redux": {
-            "version": "7.2.6",
-            "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.6.tgz",
-            "integrity": "sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ==",
+            "version": "7.2.8",
+            "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.8.tgz",
+            "integrity": "sha512-6+uDjhs3PSIclqoCk0kd6iX74gzrGc3W5zcAjbrFgEdIjRSQObdIwfx80unTkVUYvbQ95Y8Av3OvFHq1w5EOUw==",
             "requires": {
                 "@babel/runtime": "^7.15.4",
                 "@types/react-redux": "^7.1.20",
@@ -16536,14 +15683,6 @@
                 "react-is": "^17.0.2"
             },
             "dependencies": {
-                "@babel/runtime": {
-                    "version": "7.17.2",
-                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz",
-                    "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==",
-                    "requires": {
-                        "regenerator-runtime": "^0.13.4"
-                    }
-                },
                 "react-is": {
                     "version": "17.0.2",
                     "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -16552,9 +15691,9 @@
             }
         },
         "react-refresh-typescript": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/react-refresh-typescript/-/react-refresh-typescript-2.0.3.tgz",
-            "integrity": "sha512-CnR+UkpCFUIxW3u+KPxc6UhSO3M3aQxd9XCvgdry4a22LFwwITnjbANFUKtPGxA/Skw3PbZJrLiZ08UQnpXprQ=="
+            "version": "2.0.5",
+            "resolved": "https://registry.npmjs.org/react-refresh-typescript/-/react-refresh-typescript-2.0.5.tgz",
+            "integrity": "sha512-TlcxF9VMBBS8dHvMD+3dklgArXeIhjbtT7R09ycsXvhPPYmv70J67kiGT8mxe6/tYzkql9aCHaZAY6QYdutLdw=="
         },
         "react-resizable": {
             "version": "1.11.1",
@@ -16604,9 +15743,9 @@
                     }
                 },
                 "csstype": {
-                    "version": "3.0.10",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
-                    "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
                 },
                 "dom-helpers": {
                     "version": "5.2.1",
@@ -16651,7 +15790,7 @@
                 "object-assign": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
-                    "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I="
+                    "integrity": "sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ=="
                 }
             }
         },
@@ -16700,17 +15839,12 @@
                 "path-type": {
                     "version": "1.1.0",
                     "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
-                    "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+                    "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==",
                     "requires": {
                         "graceful-fs": "^4.1.2",
                         "pify": "^2.0.0",
                         "pinkie-promise": "^2.0.0"
                     }
-                },
-                "pify": {
-                    "version": "2.3.0",
-                    "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-                    "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
                 }
             }
         },
@@ -16726,7 +15860,7 @@
                 "find-up": {
                     "version": "1.1.2",
                     "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
-                    "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+                    "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==",
                     "requires": {
                         "path-exists": "^2.0.0",
                         "pinkie-promise": "^2.0.0"
@@ -16735,7 +15869,7 @@
                 "path-exists": {
                     "version": "2.1.0",
                     "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
-                    "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+                    "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==",
                     "requires": {
                         "pinkie-promise": "^2.0.0"
                     }
@@ -16824,17 +15958,17 @@
             "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc="
         },
         "redux": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz",
-            "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==",
+            "version": "4.2.0",
+            "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz",
+            "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==",
             "requires": {
                 "@babel/runtime": "^7.9.2"
             }
         },
         "regenerator-runtime": {
-            "version": "0.13.5",
-            "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
-            "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA=="
+            "version": "0.13.9",
+            "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
+            "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
         },
         "regex-not": {
             "version": "1.0.2",
@@ -16851,12 +15985,13 @@
             "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw=="
         },
         "regexp.prototype.flags": {
-            "version": "1.4.1",
-            "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz",
-            "integrity": "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==",
+            "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"
+                "define-properties": "^1.1.3",
+                "functions-have-names": "^1.2.2"
             }
         },
         "registry-auth-token": {
@@ -16904,9 +16039,9 @@
                     "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
                 },
                 "dom-serializer": {
-                    "version": "1.3.2",
-                    "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
-                    "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
+                    "version": "1.4.1",
+                    "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
+                    "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
                     "requires": {
                         "domelementtype": "^2.0.1",
                         "domhandler": "^4.2.0",
@@ -16914,14 +16049,14 @@
                     }
                 },
                 "domelementtype": {
-                    "version": "2.2.0",
-                    "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
-                    "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
+                    "version": "2.3.0",
+                    "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+                    "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
                 },
                 "domhandler": {
-                    "version": "4.3.0",
-                    "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
-                    "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
+                    "version": "4.3.1",
+                    "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
+                    "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
                     "requires": {
                         "domelementtype": "^2.2.0"
                     }
@@ -16963,9 +16098,9 @@
             }
         },
         "repeat-element": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
-            "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g=="
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz",
+            "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ=="
         },
         "repeat-string": {
             "version": "1.6.1",
@@ -17007,16 +16142,6 @@
                 "uuid": "^3.3.2"
             },
             "dependencies": {
-                "form-data": {
-                    "version": "2.3.3",
-                    "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
-                    "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
-                    "requires": {
-                        "asynckit": "^0.4.0",
-                        "combined-stream": "^1.0.6",
-                        "mime-types": "^2.1.12"
-                    }
-                },
                 "tough-cookie": {
                     "version": "2.5.0",
                     "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
@@ -17039,14 +16164,6 @@
                 "tough-cookie": "^2.3.3"
             },
             "dependencies": {
-                "request-promise-core": {
-                    "version": "1.1.4",
-                    "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
-                    "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
-                    "requires": {
-                        "lodash": "^4.17.19"
-                    }
-                },
                 "tough-cookie": {
                     "version": "2.5.0",
                     "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
@@ -17059,21 +16176,20 @@
             }
         },
         "request-promise-core": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz",
-            "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==",
-            "dev": true,
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
+            "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
             "requires": {
-                "lodash": "^4.17.15"
+                "lodash": "^4.17.19"
             }
         },
         "request-promise-native": {
-            "version": "1.0.8",
-            "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz",
-            "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==",
+            "version": "1.0.9",
+            "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz",
+            "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==",
             "dev": true,
             "requires": {
-                "request-promise-core": "1.1.3",
+                "request-promise-core": "1.1.4",
                 "stealthy-require": "^1.1.1",
                 "tough-cookie": "^2.3.3"
             },
@@ -17143,11 +16259,13 @@
             "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
         },
         "resolve": {
-            "version": "1.17.0",
-            "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
-            "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+            "version": "1.22.0",
+            "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
+            "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
             "requires": {
-                "path-parse": "^1.0.6"
+                "is-core-module": "^2.8.1",
+                "path-parse": "^1.0.7",
+                "supports-preserve-symlinks-flag": "^1.0.0"
             }
         },
         "resolve-alpn": {
@@ -17156,19 +16274,17 @@
             "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="
         },
         "resolve-cwd": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
-            "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
-            "dev": true,
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+            "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
             "requires": {
-                "resolve-from": "^3.0.0"
+                "resolve-from": "^5.0.0"
             },
             "dependencies": {
                 "resolve-from": {
-                    "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
-                    "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
-                    "dev": true
+                    "version": "5.0.0",
+                    "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+                    "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="
                 }
             }
         },
@@ -17209,9 +16325,9 @@
             "dev": true
         },
         "reveal.js": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/reveal.js/-/reveal.js-4.3.0.tgz",
-            "integrity": "sha512-KzZxJjj1gmxVNyplY6g9MiGwtDvZJiYkMvG1Qmaita7vWT/8eoTEK+RuIPLvxDeyxOtTz56u2wrOETVO79qL4A=="
+            "version": "4.3.1",
+            "resolved": "https://registry.npmjs.org/reveal.js/-/reveal.js-4.3.1.tgz",
+            "integrity": "sha512-1kyEnWeUkaCdBdX//XXq9dtBK95ppvIlSwlHelrP8/wrX6LcsYp4HT9WTFoFEOUBfVqkm8C2aHQ367o+UKfcxw=="
         },
         "right-align": {
             "version": "0.1.3",
@@ -17230,9 +16346,9 @@
             }
         },
         "rope-sequence": {
-            "version": "1.3.2",
-            "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.2.tgz",
-            "integrity": "sha512-ku6MFrwEVSVmXLvy3dYph3LAMNS0890K7fabn+0YIRQ2T96T9F4gkFf0vf0WW0JUraNWwGRtInEpH7yO4tbQZg=="
+            "version": "1.3.3",
+            "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.3.tgz",
+            "integrity": "sha512-85aZYCxweiD5J8yTEbw+E6A27zSnLPNDL0WfPdw3YYodq7WjnTKo0q4dtyQ2gz23iPT8Q9CUyJtAaUNcTxRf5Q=="
         },
         "rtcpeerconnection-shim": {
             "version": "1.2.15",
@@ -17249,6 +16365,14 @@
             "dev": true,
             "requires": {
                 "aproba": "^1.1.1"
+            },
+            "dependencies": {
+                "aproba": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                    "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+                    "dev": true
+                }
             }
         },
         "safe-buffer": {
@@ -17302,6 +16426,12 @@
                 "semver": "^6.3.0"
             },
             "dependencies": {
+                "pify": {
+                    "version": "4.0.1",
+                    "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+                    "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+                    "dev": true
+                },
                 "semver": {
                     "version": "6.3.0",
                     "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -17332,7 +16462,6 @@
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
             "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
-            "dev": true,
             "requires": {
                 "ajv": "^6.1.0",
                 "ajv-errors": "^1.0.0",
@@ -17392,14 +16521,6 @@
             "dev": true,
             "requires": {
                 "node-forge": "^0.10.0"
-            },
-            "dependencies": {
-                "node-forge": {
-                    "version": "0.10.0",
-                    "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
-                    "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==",
-                    "dev": true
-                }
             }
         },
         "semver": {
@@ -17421,23 +16542,23 @@
             }
         },
         "send": {
-            "version": "0.17.2",
-            "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz",
-            "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==",
+            "version": "0.18.0",
+            "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
+            "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
             "requires": {
                 "debug": "2.6.9",
-                "depd": "~1.1.2",
-                "destroy": "~1.0.4",
+                "depd": "2.0.0",
+                "destroy": "1.2.0",
                 "encodeurl": "~1.0.2",
                 "escape-html": "~1.0.3",
                 "etag": "~1.8.1",
                 "fresh": "0.5.2",
-                "http-errors": "1.8.1",
+                "http-errors": "2.0.0",
                 "mime": "1.6.0",
                 "ms": "2.1.3",
-                "on-finished": "~2.3.0",
+                "on-finished": "2.4.1",
                 "range-parser": "~1.2.1",
-                "statuses": "~1.5.0"
+                "statuses": "2.0.1"
             },
             "dependencies": {
                 "debug": {
@@ -17451,7 +16572,7 @@
                         "ms": {
                             "version": "2.0.0",
                             "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                            "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                            "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                         }
                     }
                 },
@@ -17463,10 +16584,13 @@
             }
         },
         "serialize-javascript": {
-            "version": "1.9.1",
-            "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz",
-            "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==",
-            "dev": true
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+            "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+            "dev": true,
+            "requires": {
+                "randombytes": "^2.1.0"
+            }
         },
         "serializr": {
             "version": "1.5.4",
@@ -17497,10 +16621,16 @@
                         "ms": "2.0.0"
                     }
                 },
+                "depd": {
+                    "version": "1.1.2",
+                    "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+                    "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
+                    "dev": true
+                },
                 "http-errors": {
                     "version": "1.6.3",
                     "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
-                    "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+                    "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
                     "dev": true,
                     "requires": {
                         "depd": "~1.1.2",
@@ -17512,13 +16642,13 @@
                 "inherits": {
                     "version": "2.0.3",
                     "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
-                    "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+                    "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
                     "dev": true
                 },
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
                     "dev": true
                 },
                 "setprototypeof": {
@@ -17526,18 +16656,24 @@
                     "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
                     "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
                     "dev": true
+                },
+                "statuses": {
+                    "version": "1.5.0",
+                    "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+                    "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
+                    "dev": true
                 }
             }
         },
         "serve-static": {
-            "version": "1.14.2",
-            "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz",
-            "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==",
+            "version": "1.15.0",
+            "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
+            "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
             "requires": {
                 "encodeurl": "~1.0.2",
                 "escape-html": "~1.0.3",
                 "parseurl": "~1.3.3",
-                "send": "0.17.2"
+                "send": "0.18.0"
             }
         },
         "set-blocking": {
@@ -17545,11 +16681,6 @@
             "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
             "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
         },
-        "set-immediate-shim": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
-            "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E="
-        },
         "set-value": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
@@ -17564,15 +16695,10 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
-                },
-                "is-extendable": {
-                    "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-                    "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
                 }
             }
         },
@@ -17615,29 +16741,89 @@
                 "tunnel-agent": "^0.6.0"
             },
             "dependencies": {
-                "fs-minipass": {
-                    "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
-                    "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+                "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=="
+                },
+                "aproba": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                    "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+                },
+                "are-we-there-yet": {
+                    "version": "1.1.7",
+                    "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
+                    "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
                     "requires": {
-                        "minipass": "^3.0.0"
+                        "delegates": "^1.0.0",
+                        "readable-stream": "^2.0.6"
                     }
                 },
-                "minipass": {
-                    "version": "3.1.1",
-                    "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.1.tgz",
-                    "integrity": "sha512-UFqVihv6PQgwj8/yTGvl9kPz7xIAY+R5z6XYjRInD3Gk3qx6QGSD6zEcpeG4Dy/lQnv1J6zv8ejV90hyYIKf3w==",
+                "chownr": {
+                    "version": "1.1.4",
+                    "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+                    "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+                },
+                "detect-libc": {
+                    "version": "1.0.3",
+                    "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+                    "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="
+                },
+                "gauge": {
+                    "version": "2.7.4",
+                    "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+                    "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==",
                     "requires": {
-                        "yallist": "^4.0.0"
+                        "aproba": "^1.0.3",
+                        "console-control-strings": "^1.0.0",
+                        "has-unicode": "^2.0.0",
+                        "object-assign": "^4.1.0",
+                        "signal-exit": "^3.0.0",
+                        "string-width": "^1.0.1",
+                        "strip-ansi": "^3.0.1",
+                        "wide-align": "^1.1.0"
                     }
                 },
-                "minizlib": {
-                    "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.0.tgz",
-                    "integrity": "sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA==",
+                "is-fullwidth-code-point": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+                    "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==",
                     "requires": {
-                        "minipass": "^3.0.0",
-                        "yallist": "^4.0.0"
+                        "number-is-nan": "^1.0.0"
+                    }
+                },
+                "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"
+                    }
+                },
+                "npmlog": {
+                    "version": "4.1.2",
+                    "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+                    "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+                    "requires": {
+                        "are-we-there-yet": "~1.1.2",
+                        "console-control-strings": "~1.1.0",
+                        "gauge": "~2.7.3",
+                        "set-blocking": "~2.0.0"
+                    }
+                },
+                "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"
                     }
                 },
                 "semver": {
@@ -17645,23 +16831,36 @@
                     "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
                     "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
                 },
+                "string-width": {
+                    "version": "1.0.2",
+                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+                    "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+                    "requires": {
+                        "code-point-at": "^1.0.0",
+                        "is-fullwidth-code-point": "^1.0.0",
+                        "strip-ansi": "^3.0.0"
+                    }
+                },
+                "strip-ansi": {
+                    "version": "3.0.1",
+                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+                    "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+                    "requires": {
+                        "ansi-regex": "^2.0.0"
+                    }
+                },
                 "tar": {
-                    "version": "5.0.5",
-                    "resolved": "https://registry.npmjs.org/tar/-/tar-5.0.5.tgz",
-                    "integrity": "sha512-MNIgJddrV2TkuwChwcSNds/5E9VijOiw7kAc1y5hTNJoLDSuIyid2QtLYiCYNnICebpuvjhPQZsXwUL0O3l7OQ==",
-                    "requires": {
-                        "chownr": "^1.1.3",
-                        "fs-minipass": "^2.0.0",
-                        "minipass": "^3.0.0",
-                        "minizlib": "^2.1.0",
-                        "mkdirp": "^0.5.0",
+                    "version": "5.0.11",
+                    "resolved": "https://registry.npmjs.org/tar/-/tar-5.0.11.tgz",
+                    "integrity": "sha512-E6q48d5y4XSCD+Xmwc0yc8lXuyDK38E0FB8N4S/drQRtXOMUhfhDxbB0xr2KKDhNfO51CFmoa6Oz00nAkWsjnA==",
+                    "requires": {
+                        "chownr": "^1.1.4",
+                        "fs-minipass": "^2.1.0",
+                        "minipass": "^3.1.3",
+                        "minizlib": "^2.1.2",
+                        "mkdirp": "^0.5.5",
                         "yallist": "^4.0.0"
                     }
-                },
-                "yallist": {
-                    "version": "4.0.0",
-                    "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-                    "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
                 }
             }
         },
@@ -17696,13 +16895,6 @@
                 "call-bind": "^1.0.0",
                 "get-intrinsic": "^1.0.2",
                 "object-inspect": "^1.9.0"
-            },
-            "dependencies": {
-                "object-inspect": {
-                    "version": "1.12.0",
-                    "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
-                    "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g=="
-                }
             }
         },
         "sift": {
@@ -17711,9 +16903,9 @@
             "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA=="
         },
         "signal-exit": {
-            "version": "3.0.3",
-            "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
-            "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
+            "version": "3.0.7",
+            "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+            "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
         },
         "simple-assign": {
             "version": "0.1.0",
@@ -17721,14 +16913,14 @@
             "integrity": "sha1-F/0wZqXz13OPUDIbsPFMooHMS6o="
         },
         "simple-concat": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz",
-            "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY="
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+            "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="
         },
         "simple-get": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz",
-            "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==",
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz",
+            "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
             "requires": {
                 "decompress-response": "^4.2.0",
                 "once": "^1.3.1",
@@ -17750,11 +16942,6 @@
                 }
             }
         },
-        "skmeans": {
-            "version": "0.9.7",
-            "resolved": "https://registry.npmjs.org/skmeans/-/skmeans-0.9.7.tgz",
-            "integrity": "sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg=="
-        },
         "slash": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
@@ -17792,7 +16979,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -17800,20 +16987,15 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
                 },
-                "is-extendable": {
-                    "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-                    "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
-                },
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                 }
             }
         },
@@ -17830,7 +17012,7 @@
                 "define-property": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-                    "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+                    "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
                     "requires": {
                         "is-descriptor": "^1.0.0"
                     }
@@ -17879,7 +17061,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -17899,11 +17081,6 @@
                 "socket.io-parser": "~3.4.0"
             },
             "dependencies": {
-                "component-emitter": {
-                    "version": "1.2.1",
-                    "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
-                    "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
-                },
                 "debug": {
                     "version": "4.1.1",
                     "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
@@ -17911,21 +17088,6 @@
                     "requires": {
                         "ms": "^2.1.1"
                     }
-                },
-                "isarray": {
-                    "version": "2.0.1",
-                    "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
-                    "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
-                },
-                "socket.io-parser": {
-                    "version": "3.4.1",
-                    "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz",
-                    "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==",
-                    "requires": {
-                        "component-emitter": "1.2.1",
-                        "debug": "~4.1.0",
-                        "isarray": "2.0.1"
-                    }
                 }
             }
         },
@@ -17963,12 +17125,12 @@
                 "isarray": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
-                    "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
+                    "integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ=="
                 },
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                 },
                 "socket.io-parser": {
                     "version": "3.3.2",
@@ -17983,29 +17145,32 @@
             }
         },
         "socket.io-parser": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.1.2.tgz",
-            "integrity": "sha512-j3kk71QLJuyQ/hh5F/L2t1goqzdTL0gvDzuhTuNSwihfuFUrcSji0qFZmJJPtG6Rmug153eOPsUizeirf1IIog==",
-            "dev": true,
+            "version": "3.4.1",
+            "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz",
+            "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==",
             "requires": {
-                "@socket.io/component-emitter": "~3.0.0",
-                "debug": "~4.3.1"
+                "component-emitter": "1.2.1",
+                "debug": "~4.1.0",
+                "isarray": "2.0.1"
             },
             "dependencies": {
+                "component-emitter": {
+                    "version": "1.2.1",
+                    "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+                    "integrity": "sha512-jPatnhd33viNplKjqXKRkGU345p263OIWzDL2wH3LGIGp5Kojo+uXizHmOADRvhGFFTnJqX3jBAKP6vvmSDKcA=="
+                },
                 "debug": {
-                    "version": "4.3.3",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
-                    "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
-                    "dev": true,
+                    "version": "4.1.1",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
                     "requires": {
-                        "ms": "2.1.2"
+                        "ms": "^2.1.1"
                     }
                 },
-                "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
+                "isarray": {
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+                    "integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ=="
                 }
             }
         },
@@ -18029,13 +17194,13 @@
             }
         },
         "sockjs-client": {
-            "version": "1.6.0",
-            "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.6.0.tgz",
-            "integrity": "sha512-qVHJlyfdHFht3eBFZdKEXKTlb7I4IV41xnVNo8yUKA1UHcPJwgW2SvTq9LhnjjCywSkSK7c/e4nghU0GOoMCRQ==",
+            "version": "1.6.1",
+            "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.6.1.tgz",
+            "integrity": "sha512-2g0tjOR+fRs0amxENLi/q5TiJTqY+WXFOzb5UwXndlK6TO3U/mirZznpx6w34HVMoc3g7cY24yC/ZMIYnDlfkw==",
             "dev": true,
             "requires": {
                 "debug": "^3.2.7",
-                "eventsource": "^1.1.0",
+                "eventsource": "^2.0.2",
                 "faye-websocket": "^0.11.4",
                 "inherits": "^2.0.4",
                 "url-parse": "^1.5.10"
@@ -18063,9 +17228,12 @@
             },
             "dependencies": {
                 "node-fetch": {
-                    "version": "2.6.0",
-                    "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
-                    "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
+                    "version": "2.6.7",
+                    "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+                    "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+                    "requires": {
+                        "whatwg-url": "^5.0.0"
+                    }
                 }
             }
         },
@@ -18087,10 +17255,9 @@
             }
         },
         "source-map-support": {
-            "version": "0.5.19",
-            "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
-            "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
-            "dev": true,
+            "version": "0.5.21",
+            "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+            "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
             "requires": {
                 "buffer-from": "^1.0.0",
                 "source-map": "^0.6.0"
@@ -18099,15 +17266,14 @@
                 "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
+                    "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
                 }
             }
         },
         "source-map-url": {
-            "version": "0.4.0",
-            "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
-            "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM="
+            "version": "0.4.1",
+            "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz",
+            "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw=="
         },
         "sparse-bitfield": {
             "version": "3.0.3",
@@ -18119,9 +17285,9 @@
             }
         },
         "spdx-correct": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
-            "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+            "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
             "requires": {
                 "spdx-expression-parse": "^3.0.0",
                 "spdx-license-ids": "^3.0.0"
@@ -18133,18 +17299,18 @@
             "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A=="
         },
         "spdx-expression-parse": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
-            "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+            "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
             "requires": {
                 "spdx-exceptions": "^2.1.0",
                 "spdx-license-ids": "^3.0.0"
             }
         },
         "spdx-license-ids": {
-            "version": "3.0.5",
-            "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
-            "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q=="
+            "version": "3.0.11",
+            "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz",
+            "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g=="
         },
         "spdy": {
             "version": "4.0.2",
@@ -18160,9 +17326,9 @@
             },
             "dependencies": {
                 "debug": {
-                    "version": "4.3.3",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
-                    "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+                    "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"
@@ -18191,9 +17357,9 @@
             },
             "dependencies": {
                 "debug": {
-                    "version": "4.3.3",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
-                    "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+                    "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"
@@ -18280,7 +17446,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -18288,9 +17454,9 @@
             }
         },
         "statuses": {
-            "version": "1.5.0",
-            "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
-            "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+            "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
         },
         "stdout-stream": {
             "version": "1.4.1",
@@ -18359,7 +17525,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                 }
             }
         },
@@ -18389,41 +17555,23 @@
             "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg=="
         },
         "string.prototype.trimend": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
-            "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
-            "requires": {
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.17.5"
-            }
-        },
-        "string.prototype.trimleft": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz",
-            "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==",
-            "requires": {
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.17.5",
-                "string.prototype.trimstart": "^1.0.0"
-            }
-        },
-        "string.prototype.trimright": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz",
-            "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==",
+            "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": {
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.17.5",
-                "string.prototype.trimend": "^1.0.0"
+                "call-bind": "^1.0.2",
+                "define-properties": "^1.1.4",
+                "es-abstract": "^1.19.5"
             }
         },
         "string.prototype.trimstart": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
-            "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
+            "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": {
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.17.5"
+                "call-bind": "^1.0.2",
+                "define-properties": "^1.1.4",
+                "es-abstract": "^1.19.5"
             }
         },
         "string_decoder": {
@@ -18443,10 +17591,15 @@
                 "unpack-string": "0.0.2"
             },
             "dependencies": {
+                "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=="
+                },
                 "magicli": {
                     "version": "0.0.5",
                     "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
-                    "integrity": "sha1-zufQ+7THBRiqyxHsPrfiX/SaSSE=",
+                    "integrity": "sha512-wZbMtnl2v1b+Jp3xlqA9FU/O4I6YhGXR8xSY/eU2+gDAvut/F+W3gl4qs61iL4LELC7jqSAE6aAD5668EbmQHA==",
                     "requires": {
                         "commander": "^2.9.0",
                         "get-stdin": "^5.0.1",
@@ -18493,7 +17646,7 @@
                 "get-stdin": {
                     "version": "4.0.1",
                     "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
-                    "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4="
+                    "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw=="
                 }
             }
         },
@@ -18510,19 +17663,6 @@
             "requires": {
                 "loader-utils": "^1.1.0",
                 "schema-utils": "^1.0.0"
-            },
-            "dependencies": {
-                "schema-utils": {
-                    "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
-                    "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
-                    "dev": true,
-                    "requires": {
-                        "ajv": "^6.1.0",
-                        "ajv-errors": "^1.0.0",
-                        "ajv-keywords": "^3.1.0"
-                    }
-                }
             }
         },
         "styled-components": {
@@ -18543,12 +17683,27 @@
                 "stylis": "^3.5.0",
                 "stylis-rule-sheet": "^0.0.10",
                 "supports-color": "^5.5.0"
+            },
+            "dependencies": {
+                "@emotion/is-prop-valid": {
+                    "version": "0.8.8",
+                    "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
+                    "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
+                    "requires": {
+                        "@emotion/memoize": "0.7.4"
+                    }
+                },
+                "stylis": {
+                    "version": "3.5.4",
+                    "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz",
+                    "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q=="
+                }
             }
         },
         "stylis": {
-            "version": "3.5.4",
-            "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz",
-            "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q=="
+            "version": "4.0.13",
+            "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz",
+            "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
         },
         "stylis-rule-sheet": {
             "version": "0.0.10",
@@ -18556,9 +17711,9 @@
             "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw=="
         },
         "supercluster": {
-            "version": "7.1.4",
-            "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-7.1.4.tgz",
-            "integrity": "sha512-GhKkRM1jMR6WUwGPw05fs66pOFWhf59lXq+Q3J3SxPvhNcmgOtLRV6aVQPMRsmXdpaeFJGivt+t7QXUPL3ff4g==",
+            "version": "7.1.5",
+            "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-7.1.5.tgz",
+            "integrity": "sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg==",
             "requires": {
                 "kdbush": "^3.0.0"
             }
@@ -18571,6 +17726,11 @@
                 "has-flag": "^3.0.0"
             }
         },
+        "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=="
+        },
         "symbol-observable": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
@@ -18595,28 +17755,54 @@
             }
         },
         "tapable": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
-            "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
-            "dev": true
+            "version": "2.2.1",
+            "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+            "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="
+        },
+        "tar": {
+            "version": "6.1.11",
+            "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
+            "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
+            "requires": {
+                "chownr": "^2.0.0",
+                "fs-minipass": "^2.0.0",
+                "minipass": "^3.0.0",
+                "minizlib": "^2.1.1",
+                "mkdirp": "^1.0.3",
+                "yallist": "^4.0.0"
+            },
+            "dependencies": {
+                "mkdirp": {
+                    "version": "1.0.4",
+                    "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+                    "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
+                }
+            }
         },
         "tar-fs": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.1.tgz",
-            "integrity": "sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA==",
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
+            "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
             "requires": {
                 "chownr": "^1.1.1",
                 "mkdirp-classic": "^0.5.2",
                 "pump": "^3.0.0",
-                "tar-stream": "^2.0.0"
+                "tar-stream": "^2.1.4"
+            },
+            "dependencies": {
+                "chownr": {
+                    "version": "1.1.4",
+                    "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+                    "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+                }
             }
         },
         "tar-stream": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.2.tgz",
-            "integrity": "sha512-UaF6FoJ32WqALZGOIAApXx+OdxhekNMChu6axLJR85zMMjXKWFGjbIRe+J6P4UnRGg9rAwWvbTT0oI7hD/Un7Q==",
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+            "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
             "requires": {
-                "bl": "^4.0.1",
+                "bl": "^4.0.3",
                 "end-of-stream": "^1.4.1",
                 "fs-constants": "^1.0.0",
                 "inherits": "^2.0.3",
@@ -18646,75 +17832,36 @@
             }
         },
         "terser": {
-            "version": "5.12.0",
-            "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.0.tgz",
-            "integrity": "sha512-R3AUhNBGWiFc77HXag+1fXpAxTAFRQTJemlJKjAgD9r8xXTpjNKqIXwHM/o7Rh+O0kUJtS3WQVdBeMKFk5sw9A==",
+            "version": "5.14.0",
+            "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.0.tgz",
+            "integrity": "sha512-JC6qfIEkPBd9j1SMO3Pfn+A6w2kQV54tv+ABQLgZr7dA3k/DL/OBoYSWxzVpZev3J+bUHXfr55L8Mox7AaNo6g==",
             "requires": {
+                "@jridgewell/source-map": "^0.3.2",
                 "acorn": "^8.5.0",
                 "commander": "^2.20.0",
-                "source-map": "~0.7.2",
                 "source-map-support": "~0.5.20"
             },
             "dependencies": {
-                "acorn": {
-                    "version": "8.7.0",
-                    "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
-                    "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ=="
-                },
-                "source-map": {
-                    "version": "0.7.3",
-                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
-                    "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ=="
-                },
-                "source-map-support": {
-                    "version": "0.5.21",
-                    "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
-                    "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
-                    "requires": {
-                        "buffer-from": "^1.0.0",
-                        "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=="
-                        }
-                    }
+                "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=="
                 }
             }
         },
         "terser-webpack-plugin": {
-            "version": "5.3.1",
-            "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz",
-            "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==",
+            "version": "5.3.3",
+            "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.3.tgz",
+            "integrity": "sha512-Fx60G5HNYknNTNQnzQ1VePRuu89ZVYWfjRAeT5rITuCY/1b08s49e5kSQwHDirKZWuoKOBRFS98EUUoZ9kLEwQ==",
             "dev": true,
             "requires": {
+                "@jridgewell/trace-mapping": "^0.3.7",
                 "jest-worker": "^27.4.5",
                 "schema-utils": "^3.1.1",
                 "serialize-javascript": "^6.0.0",
-                "source-map": "^0.6.1",
                 "terser": "^5.7.2"
             },
             "dependencies": {
-                "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"
-                    }
-                },
-                "ajv-keywords": {
-                    "version": "3.5.2",
-                    "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
-                    "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
-                    "dev": true
-                },
                 "schema-utils": {
                     "version": "3.1.1",
                     "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
@@ -18725,21 +17872,6 @@
                         "ajv": "^6.12.5",
                         "ajv-keywords": "^3.5.2"
                     }
-                },
-                "serialize-javascript": {
-                    "version": "6.0.0",
-                    "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
-                    "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
-                    "dev": true,
-                    "requires": {
-                        "randombytes": "^2.1.0"
-                    }
-                },
-                "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
                 }
             }
         },
@@ -18847,7 +17979,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -18895,7 +18027,7 @@
                 "nopt": {
                     "version": "1.0.10",
                     "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
-                    "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
+                    "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
                     "requires": {
                         "abbrev": "1"
                     }
@@ -18913,13 +18045,9 @@
             }
         },
         "tr46": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
-            "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
-            "dev": true,
-            "requires": {
-                "punycode": "^2.1.0"
-            }
+            "version": "0.0.3",
+            "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+            "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
         },
         "translate-google-api": {
             "version": "1.0.4",
@@ -18936,6 +18064,11 @@
                     "requires": {
                         "follow-redirects": "^1.10.0"
                     }
+                },
+                "follow-redirects": {
+                    "version": "1.15.1",
+                    "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
+                    "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA=="
                 }
             }
         },
@@ -18979,6 +18112,25 @@
                 "loader-utils": "^1.0.2",
                 "micromatch": "^3.1.4",
                 "semver": "^5.0.1"
+            },
+            "dependencies": {
+                "enhanced-resolve": {
+                    "version": "4.5.0",
+                    "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz",
+                    "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==",
+                    "dev": true,
+                    "requires": {
+                        "graceful-fs": "^4.1.2",
+                        "memory-fs": "^0.5.0",
+                        "tapable": "^1.0.0"
+                    }
+                },
+                "tapable": {
+                    "version": "1.1.3",
+                    "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+                    "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
+                    "dev": true
+                }
             }
         },
         "ts-node": {
@@ -19000,7 +18152,7 @@
                 "arrify": {
                     "version": "1.0.1",
                     "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
-                    "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+                    "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==",
                     "dev": true
                 }
             }
@@ -19079,6 +18231,13 @@
                         "to-regex-range": "^5.0.1"
                     }
                 },
+                "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
+                },
                 "glob-parent": {
                     "version": "5.1.2",
                     "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
@@ -19179,10 +18338,9 @@
             }
         },
         "tslib": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
-            "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==",
-            "dev": true
+            "version": "2.4.0",
+            "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+            "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
         },
         "tslint": {
             "version": "5.20.1",
@@ -19205,11 +18363,29 @@
                 "tsutils": "^2.29.0"
             },
             "dependencies": {
+                "builtin-modules": {
+                    "version": "1.1.1",
+                    "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+                    "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==",
+                    "dev": true
+                },
+                "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
+                },
                 "diff": {
                     "version": "4.0.2",
                     "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
                     "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
                     "dev": true
+                },
+                "tslib": {
+                    "version": "1.14.1",
+                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+                    "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+                    "dev": true
                 }
             }
         },
@@ -19249,6 +18425,14 @@
             "dev": true,
             "requires": {
                 "tslib": "^1.8.1"
+            },
+            "dependencies": {
+                "tslib": {
+                    "version": "1.14.1",
+                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+                    "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+                    "dev": true
+                }
             }
         },
         "tunnel-agent": {
@@ -19264,12 +18448,6 @@
             "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
             "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
         },
-        "type": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
-            "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
-            "dev": true
-        },
         "type-check": {
             "version": "0.3.2",
             "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
@@ -19304,9 +18482,9 @@
             "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
         },
         "typescript": {
-            "version": "4.6.2",
-            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz",
-            "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==",
+            "version": "4.7.3",
+            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz",
+            "integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==",
             "dev": true
         },
         "typescript-collections": {
@@ -19328,6 +18506,11 @@
                 "vscode-uri": "^1.0.5"
             },
             "dependencies": {
+                "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=="
+                },
                 "fs-extra": {
                     "version": "7.0.1",
                     "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
@@ -19341,7 +18524,7 @@
                 "jsonfile": {
                     "version": "4.0.0",
                     "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
-                    "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+                    "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
                     "requires": {
                         "graceful-fs": "^4.1.6"
                     }
@@ -19354,9 +18537,9 @@
             "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0="
         },
         "ua-parser-js": {
-            "version": "0.7.21",
-            "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz",
-            "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ=="
+            "version": "0.7.31",
+            "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz",
+            "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ=="
         },
         "uglify-js": {
             "version": "2.8.29",
@@ -19371,12 +18554,12 @@
                 "camelcase": {
                     "version": "1.2.1",
                     "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
-                    "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
+                    "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g=="
                 },
                 "cliui": {
                     "version": "2.1.0",
                     "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
-                    "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+                    "integrity": "sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==",
                     "requires": {
                         "center-align": "^0.1.1",
                         "right-align": "^0.1.1",
@@ -19411,26 +18594,19 @@
             }
         },
         "uid2": {
-            "version": "0.0.3",
-            "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz",
-            "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I="
+            "version": "0.0.4",
+            "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz",
+            "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA=="
         },
         "unbox-primitive": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
-            "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+            "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
             "requires": {
-                "function-bind": "^1.1.1",
-                "has-bigints": "^1.0.1",
-                "has-symbols": "^1.0.2",
-                "which-boxed-primitive": "^1.0.2"
-            },
-            "dependencies": {
-                "has-symbols": {
-                    "version": "1.0.3",
-                    "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
-                    "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
-                }
+                "call-bind": "^1.0.2",
+                "has-bigints": "^1.0.2",
+                "has-symbols": "^1.0.3",
+                "which-boxed-primitive": "^1.0.2"
             }
         },
         "unbzip2-stream": {
@@ -19443,32 +18619,14 @@
             }
         },
         "undefsafe": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz",
-            "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==",
-            "requires": {
-                "debug": "^2.2.0"
-            },
-            "dependencies": {
-                "debug": {
-                    "version": "2.6.9",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-                    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-                    "requires": {
-                        "ms": "2.0.0"
-                    }
-                },
-                "ms": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
-                }
-            }
+            "version": "2.0.5",
+            "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
+            "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA=="
         },
         "underscore": {
-            "version": "1.10.2",
-            "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz",
-            "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg=="
+            "version": "1.13.4",
+            "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.4.tgz",
+            "integrity": "sha512-BQFnUDuAQ4Yf/cYY5LNrK9NCJFKriaRbD9uR1fTeXnBeoa97W0i41qkZfGO9pSo8I5KzjAcSY2XYtdf0oKd7KQ=="
         },
         "unicode-trie": {
             "version": "0.3.1",
@@ -19482,7 +18640,7 @@
                 "pako": {
                     "version": "0.2.9",
                     "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
-                    "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU="
+                    "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA=="
                 }
             }
         },
@@ -19495,21 +18653,8 @@
                 "get-value": "^2.0.6",
                 "is-extendable": "^0.1.1",
                 "set-value": "^2.0.1"
-            },
-            "dependencies": {
-                "is-extendable": {
-                    "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-                    "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
-                }
             }
         },
-        "uniq": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz",
-            "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=",
-            "dev": true
-        },
         "unique-filename": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
@@ -19568,7 +18713,7 @@
                 "has-value": {
                     "version": "0.3.1",
                     "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
-                    "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+                    "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==",
                     "requires": {
                         "get-value": "^2.0.3",
                         "has-values": "^0.1.4",
@@ -19578,7 +18723,7 @@
                         "isobject": {
                             "version": "2.1.0",
                             "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
-                            "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+                            "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==",
                             "requires": {
                                 "isarray": "1.0.0"
                             }
@@ -19588,7 +18733,7 @@
                 "has-values": {
                     "version": "0.1.4",
                     "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
-                    "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E="
+                    "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ=="
                 }
             }
         },
@@ -19635,9 +18780,9 @@
             }
         },
         "uri-js": {
-            "version": "4.2.2",
-            "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
-            "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+            "version": "4.4.1",
+            "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+            "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
             "requires": {
                 "punycode": "^2.1.0"
             }
@@ -19660,7 +18805,7 @@
                 "punycode": {
                     "version": "1.3.2",
                     "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
-                    "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
+                    "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==",
                     "dev": true
                 }
             }
@@ -19676,19 +18821,9 @@
             },
             "dependencies": {
                 "mime": {
-                    "version": "2.4.4",
-                    "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
-                    "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
-                },
-                "schema-utils": {
-                    "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
-                    "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
-                    "requires": {
-                        "ajv": "^6.1.0",
-                        "ajv-errors": "^1.0.0",
-                        "ajv-keywords": "^3.1.0"
-                    }
+                    "version": "2.6.0",
+                    "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+                    "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg=="
                 }
             }
         },
@@ -19726,13 +18861,6 @@
             "integrity": "sha512-7/hqDrWa0iMnCoET9W1T07EmD4Eg/Wmoj/X8TGBc++ECRK4m5yTsjP4O6s0yagbxfqIOuUkIxe2/sA+VR2GxZA==",
             "requires": {
                 "fast-deep-equal": "^3.1.3"
-            },
-            "dependencies": {
-                "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=="
-                }
             }
         },
         "use-memo-one": {
@@ -19815,6 +18943,13 @@
                 "assert-plus": "^1.0.0",
                 "core-util-is": "1.0.2",
                 "extsprintf": "^1.2.0"
+            },
+            "dependencies": {
+                "core-util-is": {
+                    "version": "1.0.2",
+                    "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+                    "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="
+                }
             }
         },
         "void-elements": {
@@ -19823,9 +18958,9 @@
             "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w="
         },
         "vscode-jsonrpc": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz",
-            "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A=="
+            "version": "8.0.1",
+            "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.1.tgz",
+            "integrity": "sha512-N/WKvghIajmEvXpatSzvTvOIz61ZSmOSa4BRA4pTLi+1+jozquQKP/MkaylP9iB68k73Oua1feLQvH3xQuigiQ=="
         },
         "vscode-languageserver": {
             "version": "5.3.0-next.10",
@@ -19837,18 +18972,18 @@
             }
         },
         "vscode-languageserver-protocol": {
-            "version": "3.15.3",
-            "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz",
-            "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==",
+            "version": "3.17.1",
+            "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.1.tgz",
+            "integrity": "sha512-BNlAYgQoYwlSgDLJhSG+DeA8G1JyECqRzM2YO6tMmMji3Ad9Mw6AW7vnZMti90qlAKb0LqAlJfSVGEdqMMNzKg==",
             "requires": {
-                "vscode-jsonrpc": "^5.0.1",
-                "vscode-languageserver-types": "3.15.1"
+                "vscode-jsonrpc": "8.0.1",
+                "vscode-languageserver-types": "3.17.1"
             }
         },
         "vscode-languageserver-types": {
-            "version": "3.15.1",
-            "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz",
-            "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ=="
+            "version": "3.17.1",
+            "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.1.tgz",
+            "integrity": "sha512-K3HqVRPElLZVVPtMeKlsyL9aK0GxGQpvtAUTfX4k7+iJ4mc1M+JM+zQwkgGy2LzY0f0IAafe8MKqIkJrxfGGjQ=="
         },
         "vscode-textbuffer": {
             "version": "1.0.0",
@@ -19861,9 +18996,9 @@
             "integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ=="
         },
         "vue-template-compiler": {
-            "version": "2.6.11",
-            "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz",
-            "integrity": "sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA==",
+            "version": "2.6.14",
+            "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz",
+            "integrity": "sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g==",
             "requires": {
                 "de-indent": "^1.0.2",
                 "he": "^1.1.0"
@@ -19892,6 +19027,14 @@
                 "domexception": "^1.0.1",
                 "webidl-conversions": "^4.0.2",
                 "xml-name-validator": "^3.0.0"
+            },
+            "dependencies": {
+                "webidl-conversions": {
+                    "version": "4.0.2",
+                    "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
+                    "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
+                    "dev": true
+                }
             }
         },
         "walkdir": {
@@ -19908,9 +19051,9 @@
             }
         },
         "watchpack": {
-            "version": "2.3.1",
-            "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz",
-            "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==",
+            "version": "2.4.0",
+            "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
+            "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
             "dev": true,
             "requires": {
                 "glob-to-regexp": "^0.4.1",
@@ -19935,20 +19078,19 @@
             }
         },
         "web-streams-polyfill": {
-            "version": "3.2.0",
-            "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz",
-            "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA=="
+            "version": "3.2.1",
+            "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
+            "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q=="
         },
         "webidl-conversions": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
-            "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
-            "dev": true
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+            "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
         },
         "webpack": {
-            "version": "5.69.1",
-            "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.69.1.tgz",
-            "integrity": "sha512-+VyvOSJXZMT2V5vLzOnDuMz5GxEqLk7hKWQ56YxPW/PQRUuKimPqmEIJOx8jHYeyo65pKbapbW464mvsKbaj4A==",
+            "version": "5.73.0",
+            "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz",
+            "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==",
             "dev": true,
             "requires": {
                 "@types/eslint-scope": "^3.7.3",
@@ -19960,13 +19102,13 @@
                 "acorn-import-assertions": "^1.7.6",
                 "browserslist": "^4.14.5",
                 "chrome-trace-event": "^1.0.2",
-                "enhanced-resolve": "^5.8.3",
+                "enhanced-resolve": "^5.9.3",
                 "es-module-lexer": "^0.9.0",
                 "eslint-scope": "5.1.1",
                 "events": "^3.2.0",
                 "glob-to-regexp": "^0.4.1",
                 "graceful-fs": "^4.2.9",
-                "json-parse-better-errors": "^1.0.2",
+                "json-parse-even-better-errors": "^2.3.1",
                 "loader-runner": "^4.2.0",
                 "mime-types": "^2.1.27",
                 "neo-async": "^2.6.2",
@@ -19977,52 +19119,6 @@
                 "webpack-sources": "^3.2.3"
             },
             "dependencies": {
-                "acorn": {
-                    "version": "8.7.0",
-                    "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
-                    "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
-                    "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"
-                    }
-                },
-                "ajv-keywords": {
-                    "version": "3.5.2",
-                    "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
-                    "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
-                    "dev": true
-                },
-                "enhanced-resolve": {
-                    "version": "5.9.1",
-                    "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.1.tgz",
-                    "integrity": "sha512-jdyZMwCQ5Oj4c5+BTnkxPgDZO/BJzh/ADDmKebayyzNwjVX1AFCeGkOfxNx0mHi2+8BKC5VxUYiw3TIvoT7vhw==",
-                    "dev": true,
-                    "requires": {
-                        "graceful-fs": "^4.2.4",
-                        "tapable": "^2.2.0"
-                    }
-                },
-                "graceful-fs": {
-                    "version": "4.2.9",
-                    "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
-                    "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
-                    "dev": true
-                },
-                "neo-async": {
-                    "version": "2.6.2",
-                    "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
-                    "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
-                    "dev": true
-                },
                 "schema-utils": {
                     "version": "3.1.1",
                     "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
@@ -20033,12 +19129,6 @@
                         "ajv": "^6.12.5",
                         "ajv-keywords": "^3.5.2"
                     }
-                },
-                "tapable": {
-                    "version": "2.2.1",
-                    "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
-                    "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
-                    "dev": true
                 }
             }
         },
@@ -20092,29 +19182,6 @@
                         "strip-final-newline": "^2.0.0"
                     }
                 },
-                "find-up": {
-                    "version": "4.1.0",
-                    "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
-                    "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
-                    "requires": {
-                        "locate-path": "^5.0.0",
-                        "path-exists": "^4.0.0"
-                    }
-                },
-                "get-stream": {
-                    "version": "6.0.1",
-                    "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
-                    "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="
-                },
-                "import-local": {
-                    "version": "3.1.0",
-                    "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
-                    "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
-                    "requires": {
-                        "pkg-dir": "^4.2.0",
-                        "resolve-cwd": "^3.0.0"
-                    }
-                },
                 "interpret": {
                     "version": "2.2.0",
                     "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz",
@@ -20125,14 +19192,6 @@
                     "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
                     "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="
                 },
-                "locate-path": {
-                    "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
-                    "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
-                    "requires": {
-                        "p-locate": "^4.1.0"
-                    }
-                },
                 "npm-run-path": {
                     "version": "4.0.1",
                     "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
@@ -20141,32 +19200,11 @@
                         "path-key": "^3.0.0"
                     }
                 },
-                "p-locate": {
-                    "version": "4.1.0",
-                    "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
-                    "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
-                    "requires": {
-                        "p-limit": "^2.2.0"
-                    }
-                },
-                "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=="
-                },
                 "path-key": {
                     "version": "3.1.1",
                     "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
                     "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
                 },
-                "pkg-dir": {
-                    "version": "4.2.0",
-                    "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
-                    "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
-                    "requires": {
-                        "find-up": "^4.0.0"
-                    }
-                },
                 "rechoir": {
                     "version": "0.7.1",
                     "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
@@ -20175,19 +19213,6 @@
                         "resolve": "^1.9.0"
                     }
                 },
-                "resolve-cwd": {
-                    "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
-                    "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
-                    "requires": {
-                        "resolve-from": "^5.0.0"
-                    }
-                },
-                "resolve-from": {
-                    "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
-                    "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="
-                },
                 "shebang-command": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -20212,21 +19237,21 @@
             }
         },
         "webpack-dev-middleware": {
-            "version": "5.3.1",
-            "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz",
-            "integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==",
+            "version": "5.3.3",
+            "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz",
+            "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==",
             "requires": {
                 "colorette": "^2.0.10",
-                "memfs": "^3.4.1",
+                "memfs": "^3.4.3",
                 "mime-types": "^2.1.31",
                 "range-parser": "^1.2.1",
                 "schema-utils": "^4.0.0"
             },
             "dependencies": {
                 "ajv": {
-                    "version": "8.10.0",
-                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz",
-                    "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==",
+                    "version": "8.11.0",
+                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
+                    "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
                     "requires": {
                         "fast-deep-equal": "^3.1.1",
                         "json-schema-traverse": "^1.0.0",
@@ -20240,13 +19265,6 @@
                     "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
                     "requires": {
                         "fast-deep-equal": "^3.1.3"
-                    },
-                    "dependencies": {
-                        "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=="
-                        }
                     }
                 },
                 "json-schema-traverse": {
@@ -20254,19 +19272,6 @@
                     "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
                     "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
                 },
-                "mime-db": {
-                    "version": "1.51.0",
-                    "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
-                    "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
-                },
-                "mime-types": {
-                    "version": "2.1.34",
-                    "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
-                    "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
-                    "requires": {
-                        "mime-db": "1.51.0"
-                    }
-                },
                 "schema-utils": {
                     "version": "4.0.0",
                     "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz",
@@ -20324,22 +19329,32 @@
                 "ansi-regex": {
                     "version": "2.1.1",
                     "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+                    "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
                     "dev": true
                 },
                 "debug": {
-                    "version": "4.3.3",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
-                    "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+                    "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"
                     }
                 },
+                "import-local": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
+                    "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
+                    "dev": true,
+                    "requires": {
+                        "pkg-dir": "^3.0.0",
+                        "resolve-cwd": "^2.0.0"
+                    }
+                },
                 "memory-fs": {
                     "version": "0.4.1",
                     "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
-                    "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+                    "integrity": "sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ==",
                     "dev": true,
                     "requires": {
                         "errno": "^0.1.3",
@@ -20358,6 +19373,15 @@
                     "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
                     "dev": true
                 },
+                "pkg-dir": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+                    "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+                    "dev": true,
+                    "requires": {
+                        "find-up": "^3.0.0"
+                    }
+                },
                 "readable-stream": {
                     "version": "2.3.7",
                     "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -20373,6 +19397,21 @@
                         "util-deprecate": "~1.0.1"
                     }
                 },
+                "resolve-cwd": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
+                    "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+                    "dev": true,
+                    "requires": {
+                        "resolve-from": "^3.0.0"
+                    }
+                },
+                "resolve-from": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+                    "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+                    "dev": true
+                },
                 "semver": {
                     "version": "6.3.0",
                     "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -20450,9 +19489,9 @@
                     "dev": true
                 },
                 "html-entities": {
-                    "version": "2.3.2",
-                    "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz",
-                    "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==",
+                    "version": "2.3.3",
+                    "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz",
+                    "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==",
                     "dev": true
                 },
                 "strip-ansi": {
@@ -20526,12 +19565,23 @@
             "dev": true,
             "requires": {
                 "iconv-lite": "0.4.24"
+            },
+            "dependencies": {
+                "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"
+                    }
+                }
             }
         },
         "whatwg-fetch": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz",
-            "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q=="
+            "version": "3.6.2",
+            "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz",
+            "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA=="
         },
         "whatwg-mimetype": {
             "version": "2.3.0",
@@ -20540,14 +19590,12 @@
             "dev": true
         },
         "whatwg-url": {
-            "version": "7.1.0",
-            "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
-            "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
-            "dev": true,
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+            "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
             "requires": {
-                "lodash.sortby": "^4.7.0",
-                "tr46": "^1.0.1",
-                "webidl-conversions": "^4.0.2"
+                "tr46": "~0.0.3",
+                "webidl-conversions": "^3.0.0"
             }
         },
         "when": {
@@ -20581,103 +19629,21 @@
             "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
         },
         "which-pm-runs": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
-            "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs="
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz",
+            "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA=="
         },
         "which-typed-array": {
-            "version": "1.1.7",
-            "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz",
-            "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==",
+            "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.18.5",
-                "foreach": "^2.0.5",
+                "es-abstract": "^1.20.0",
+                "for-each": "^0.3.3",
                 "has-tostringtag": "^1.0.0",
-                "is-typed-array": "^1.1.7"
-            },
-            "dependencies": {
-                "es-abstract": {
-                    "version": "1.19.1",
-                    "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz",
-                    "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==",
-                    "requires": {
-                        "call-bind": "^1.0.2",
-                        "es-to-primitive": "^1.2.1",
-                        "function-bind": "^1.1.1",
-                        "get-intrinsic": "^1.1.1",
-                        "get-symbol-description": "^1.0.0",
-                        "has": "^1.0.3",
-                        "has-symbols": "^1.0.2",
-                        "internal-slot": "^1.0.3",
-                        "is-callable": "^1.2.4",
-                        "is-negative-zero": "^2.0.1",
-                        "is-regex": "^1.1.4",
-                        "is-shared-array-buffer": "^1.0.1",
-                        "is-string": "^1.0.7",
-                        "is-weakref": "^1.0.1",
-                        "object-inspect": "^1.11.0",
-                        "object-keys": "^1.1.1",
-                        "object.assign": "^4.1.2",
-                        "string.prototype.trimend": "^1.0.4",
-                        "string.prototype.trimstart": "^1.0.4",
-                        "unbox-primitive": "^1.0.1"
-                    }
-                },
-                "has-symbols": {
-                    "version": "1.0.3",
-                    "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
-                    "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
-                },
-                "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-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"
-                    }
-                },
-                "object-inspect": {
-                    "version": "1.12.0",
-                    "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
-                    "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g=="
-                },
-                "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"
-                    }
-                },
-                "string.prototype.trimend": {
-                    "version": "1.0.4",
-                    "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
-                    "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
-                    "requires": {
-                        "call-bind": "^1.0.2",
-                        "define-properties": "^1.1.3"
-                    }
-                },
-                "string.prototype.trimstart": {
-                    "version": "1.0.4",
-                    "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
-                    "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
-                    "requires": {
-                        "call-bind": "^1.0.2",
-                        "define-properties": "^1.1.3"
-                    }
-                }
+                "is-typed-array": "^1.1.9"
             }
         },
         "wide-align": {
@@ -20723,6 +19689,13 @@
             "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=="
+                }
             }
         },
         "word-wrap": {
@@ -20775,9 +19748,9 @@
             },
             "dependencies": {
                 "ansi-regex": {
-                    "version": "4.1.0",
-                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-                    "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+                    "version": "4.1.1",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+                    "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="
                 },
                 "string-width": {
                     "version": "3.1.0",
@@ -20815,9 +19788,9 @@
             }
         },
         "ws": {
-            "version": "7.2.5",
-            "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz",
-            "integrity": "sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA=="
+            "version": "7.5.8",
+            "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.8.tgz",
+            "integrity": "sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw=="
         },
         "xdg-basedir": {
             "version": "3.0.0",
@@ -20841,7 +19814,7 @@
                 "lodash": {
                     "version": "3.10.1",
                     "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
-                    "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
+                    "integrity": "sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ=="
                 }
             }
         },
@@ -20881,14 +19854,14 @@
             "dev": true
         },
         "y18n": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
-            "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
+            "version": "4.0.3",
+            "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+            "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
         },
         "yallist": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
-            "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+            "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
         },
         "yaml": {
             "version": "1.10.2",
@@ -20913,9 +19886,9 @@
             },
             "dependencies": {
                 "ansi-regex": {
-                    "version": "4.1.0",
-                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-                    "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+                    "version": "4.1.1",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+                    "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="
                 },
                 "string-width": {
                     "version": "3.1.0",
@@ -20987,9 +19960,9 @@
             }
         },
         "zustand": {
-            "version": "3.7.1",
-            "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.1.tgz",
-            "integrity": "sha512-wHBCZlKj+bg03/hP+Tzv24YhnqqP8MCeN9ECPDXoF01062SIbnfl3j9O0znkDw1lNTY0a8WN3F///a0UhhaEqg=="
+            "version": "3.7.2",
+            "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz",
+            "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA=="
         }
     }
 }
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 166e68c94..ba6467da2 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -65,18 +65,18 @@ import { RecordingBox } from "../views/nodes/RecordingBox/RecordingBox";
 
 const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", ""));
 class EmptyBox {
-    public static LayoutString() {
-        return "";
-    }
+      public static LayoutString() {
+            return "";
+      }
 }
 abstract class FInfo {
-    description: string = "";
-    type?: string;
-    values?: Field[];
-    layoutField?: boolean; // is this field a layout (or datadoc) field
-    // format?: string; // format to display values (e.g, decimal places, $, etc)
-    // parse?: ScriptField; // parse a value from a string
-    constructor(d: string, l: boolean = false) { this.description = d; this.layoutField = l; }
+      description: string = "";
+      type?: string;
+      values?: Field[];
+      layoutField?: boolean; // is this field a layout (or datadoc) field
+      // format?: string; // format to display values (e.g, decimal places, $, etc)
+      // parse?: ScriptField; // parse a value from a string
+      constructor(d: string, l: boolean = false) { this.description = d; this.layoutField = l; }
 }
 class BoolInfo extends FInfo { type?= "boolean"; values?: boolean[] = [true, false]; }
 class NumInfo extends FInfo { type?= "number"; values?: number[] = []; }
@@ -93,1423 +93,1426 @@ type DIMt = DimInfo | typeof DimUnit.Pixel | typeof DimUnit.Ratio;
 type PEVt = PEInfo | "none" | "all";
 type DROPt = DAInfo | dropActionType;
 export class DocumentOptions {
-    system?: BOOLt = new BoolInfo("is this a system created/owned doc");
-    _dropAction?: DROPt = new DAInfo("what should happen to this document when it's dropped somewhere else");
-    allowOverlayDrop?: BOOLt = new BoolInfo("can documents be dropped onto this document without using dragging title bar or holding down embed key (ctrl)?");
-    childDropAction?: DROPt = new DAInfo("what should happen to the source document when it's dropped onto a child of a collection ");
-    targetDropAction?: DROPt = new DAInfo("what should happen to the source document when ??? ");
-    color?: string; // foreground color data doc
-    backgroundColor?: STRt = new StrInfo("background color for data doc");
-    _backgroundColor?: STRt = new StrInfo("background color for each template layout doc (overrides backgroundColor)", true);
-    _autoHeight?: BOOLt = new BoolInfo("whether document automatically resizes vertically to display contents", true);
-    _headerHeight?: NUMt = new NumInfo("height of document header used for displaying title", true);
-    _headerFontSize?: NUMt = new NumInfo("font size of header of custom notes", true);
-    _headerPointerEvents?: PEVt = new PEInfo("types of events the header of a custom text document can consume", true);
-    _panX?: NUMt = new NumInfo("horizontal pan location of a freeform view", true);
-    _panY?: NUMt = new NumInfo("vertical pan location of a freeform view", true);
-    _width?: NUMt = new NumInfo("displayed width of a document", true);
-    _height?: NUMt = new NumInfo("displayed height of document", true);
-    _nativeWidth?: NUMt = new NumInfo("native width of document contents (e.g., the pixel width of an image)", true);
-    _nativeHeight?: NUMt = new NumInfo("native height of document contents (e.g., the pixel height of an image)", true);
-    _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height", true);
-    _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units", true);
-    _fitWidth?: BOOLt = new BoolInfo("whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)", true);
-    _fitToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents
-    _lockedPosition?: boolean; // lock the x,y coordinates of the document so that it can't be dragged
-    _lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed
-    _isPushpin?: boolean; // whether document, when clicked, toggles display of its link target
-    _showTitle?: string; // field name to display in header (:hover is an optional suffix)
-    _showCaption?: string; // which field to display in the caption area.  leave empty to have no caption
-    _scrollTop?: number; // scroll location for pdfs
-    _noAutoscroll?: boolean;// whether collections autoscroll when this item is dragged
-    _chromeHidden?: boolean; // whether the editing chrome for a document is hidden
-    _searchDoc?: boolean; // is this a search document (used to change UI for search results in schema view)
-    _forceActive?: boolean; // flag to handle pointer events when not selected (or otherwise active)
-    _stayInCollection?: boolean;// whether the document should remain in its collection when someone tries to drag and drop it elsewhere
-    _raiseWhenDragged?: boolean; // whether a document is brought to front when dragged.
-    _hideContextMenu?: boolean; // whether the context menu can be shown
-    _viewType?: string; // sub type of a collection
-    _gridGap?: number; // gap between items in masonry view
-    _viewScale?: number; // how much a freeform view has been scaled (zoomed)
-    _overflow?: string; // set overflow behavior
-    _xMargin?: number; // gap between left edge of document and start of masonry/stacking layouts
-    _yMargin?: number; // gap between top edge of dcoument and start of masonry/stacking layouts
-    _xPadding?: number;
-    _yPadding?: number;
-    _itemIndex?: number; // which item index the carousel viewer is showing
-    _showSidebar?: boolean;  //whether an annotationsidebar should be displayed for text docuemnts
-    _singleLine?: boolean; // whether text document is restricted to a single line (carriage returns make new document)
-    _minFontSize?: number; // minimum font size for labelBoxes
-    _maxFontSize?: number; // maximum font size for labelBoxes
-    _columnWidth?: number;
-    _columnsHideIfEmpty?: boolean; // whether stacking view column headings should be hidden
-    _fontSize?: string;
-    _fontFamily?: string;
-    _fontWeight?: string;
-    _pivotField?: string; // field key used to determine headings for sections in stacking, masonry, pivot views
-    _curPage?: number; // current page of a PDF or other? paginated document
-    _currentTimecode?: number; // the current timecode of a time-based document (e.g., current time of a video)  value is in seconds
-    _currentFrame?: number; // the current frame of a frame-based collection (e.g., progressive slide)
-    _timecodeToShow?: number; // the time that a document should be displayed (e.g., when an annotation shows up as a video plays)
-    _timecodeToHide?: number; // the time that a document should be hidden
-    _timelineLabel?: boolean; // whether the document exists on a timeline
-    "_carousel-caption-xMargin"?: number;
-    "_carousel-caption-yMargin"?: number;
-    "icon-nativeWidth"?: number;
-    "icon-nativeHeight"?: number;
-    "dragFactory-count"?: number; // number of items created from a drag button (used for setting title with incrementing index)
-    x?: number;
-    y?: number;
-    z?: number; // whether document is in overlay (1) or not (0 or undefined)
-    lat?: number;
-    lng?: number;
-    infoWindowOpen?: boolean;
-    author?: string;
-    _layoutKey?: string;
-    unrendered?: boolean; // denotes an annotation that is not rendered with a DocumentView (e.g, rtf/pdf text selections and links to scroll locations in web/pdf)
-    type?: string;
-    title?: string;
-    "acl-Public"?: string; // public permissions
-    "_acl-Public"?: string; // public permissions
-    version?: string; // version identifier for a document
-    label?: string;
-    hidden?: boolean;
-    _hidden?: boolean;
-    pointerEvents?: string; // pointer events that the documentview should have
-    mediaState?: string; // status of media document: "pendingRecording", "recording", "paused", "playing"
-    autoPlayAnchors?: boolean; // whether to play audio/video when an anchor is clicked in a stackedTimeline.
-    dontPlayLinkOnSelect?: boolean;  // whether an audio/video should start playing when a link is followed to it.
-    toolTip?: string; // tooltip to display on hover
-    dontUndo?: boolean; // whether button clicks should be undoable (this is set to true for Undo/Redo/and sidebar buttons that open the siebar panel)
-    description?: string; // added for links
-    layout?: string | Doc; // default layout string for a document
-    contentPointerEvents?: string;  // pointer events allowed for content of a document view.  eg. set to "none" in menuSidebar for sharedDocs so that you can select a document, but not interact with its contents
-    childLimitHeight?: number; // whether to limit the height of collection children.  0 - means  height can be no bigger than width
-    childLayoutTemplate?: Doc; // template for collection to use to render its children (see PresBox layout in tree view)
-    childLayoutString?: string; // template string for collection to use to render its children
-    childDontRegisterViews?: boolean;
-    childHideLinkButton?: boolean; // hide link buttons on all children
-    hideLinkButton?: boolean; // whether the blue link counter button should be hidden
-    hideAllLinks?: boolean; // whether all individual blue anchor dots should be hidden
-    isTemplateForField?: string; // the field key for which the containing document is a rendering template
-    isTemplateDoc?: boolean;
-    watchedDocuments?: Doc; // list of documents an icon doc monitors in order to display a badge count
-    targetScriptKey?: string; // where to write a template script (used by collections with click templates which need to target onClick, onDoubleClick, etc)
-    templates?: List<string>;
-    hero?: ImageField; // primary image that best represents a compound document (e.g., for a buxton device document that has multiple images)
-    caption?: RichTextField;
-    opacity?: number;
-    defaultBackgroundColor?: string;
-    _isLinkButton?: boolean; // marks a document as a button that will follow its primary link when clicked
-    _linkAutoMove?: boolean; // whether link endpoint should move around the edges of a document to make shortest path to other link endpoint
-    isFolder?: boolean;
-    lastFrame?: number; // the last frame of a frame-based collection (e.g., progressive slide)
-    activeFrame?: number; // the active frame of a document in a frame base collection
-    appearFrame?: number; // the frame in which the document appears
-    presTransition?: number; //the time taken for the transition TO a document
-    presDuration?: number; //the duration of the slide in presentation view
-    presProgressivize?: boolean;
-    borderRounding?: string;
-    boxShadow?: string;
-    data?: any;
-    baseProto?: boolean; // is this a base prototoype
-    dontRegisterView?: boolean;
-    lookupField?: ScriptField; // script that returns the value of a field. This script is passed the rootDoc, layoutDoc, field, and container of the document.  see PresBox.
-    "onDoubleClick-rawScript"?: string; // onDoubleClick script in raw text form
-    "onChildDoubleClick-rawScript"?: string; // onChildDoubleClick script in raw text form
-    "onChildClick-rawScript"?: string; // on ChildClick script in raw text form
-    "onClick-rawScript"?: string; // onClick script in raw text form
-    "onCheckedClick-rawScript"?: string; // onChecked script in raw text form
-    "onCheckedClick-params"?: List<string>; // parameter list for onChecked treeview functions
-    columnHeaders?: List<SchemaHeaderField>; // headers for stacking views
-    schemaHeaders?: List<SchemaHeaderField>; // headers for schema view
-    clipWidth?: number; // percent transition from before to after in comparisonBox
-    dockingConfig?: string;
-    annotationOn?: Doc;
-    isPushpin?: boolean;
-    isGroup?: boolean; // whether a collection should use a grouping UI behavior
-    _removeDropProperties?: List<string>; // list of properties that should be removed from a document when it is dropped.  e.g., a creator button may be forceActive to allow it be dragged, but the forceActive property can be removed from the dropped document
-
-    // BACKGROUND GRID
-    _backgroundGridShow?: boolean;
-
-    //BUTTONS
-    buttonText?: string;
-    iconShape?: string; // shapes of the fonticon border
-    btnType?: string;
-    btnList?: List<string>;
-    docColorBtn?: string;
-    userColorBtn?: string;
-    canClick?: string;
-    script?: ScriptField;
-    numBtnType?: string;
-    numBtnMax?: number;
-    numBtnMin?: number;
-    switchToggle?: boolean;
-
-    //LINEAR VIEW
-    linearViewIsExpanded?: boolean; // is linear view expanded
-    linearViewExpandable?: boolean; // can linear view be expanded
-    linearViewToggleButton?: string; // button to open close linear view group
-    linearViewSubMenu?: boolean;
-    linearViewFloating?: boolean;
-    flexGap?: number; // Linear view flex gap
-    flexDirection?: "unset" | "row" | "column" | "row-reverse" | "column-reverse";
-
-    layout_linkView?: Doc; // view template for a link document
-    layout_keyValue?: string; // view tempalte for key value docs
-    linkRelationship?: string; // type of relatinoship a link represents
-    linkDisplay?: boolean; // whether a link line should be dipslayed between the two link anchors
-    anchor1?: Doc;
-    anchor2?: Doc;
-    "anchor1-useLinkSmallAnchor"?: boolean; // whether anchor1 of a link should use a miniature anchor dot (as when the anchor is a text selection)
-    "anchor2-useLinkSmallAnchor"?: boolean; // whether anchor1 of a link should use a miniature anchor dot (as when the anchor is a text selection)
-    ignoreClick?: boolean;
-    onClick?: ScriptField;
-    onDoubleClick?: ScriptField;
-    onChildClick?: ScriptField; // script given to children of a collection to execute when they are clicked
-    onChildDoubleClick?: ScriptField; // script given to children of a collection to execute when they are double clicked
-    onPointerDown?: ScriptField;
-    onPointerUp?: ScriptField;
-    dropConverter?: ScriptField; // script to run when documents are dropped on this Document.
-    dragFactory?: Doc; // document to create when dragging with a suitable onDragStart script
-    clickFactory?: Doc; // document to create when clicking on a button with a suitable onClick script
-    onDragStart?: ScriptField; //script to execute at start of drag operation --  e.g., when a "creator" button is dragged this script generates a different document to drop
-    cloneFieldFilter?: List<string>; // fields not to copy when the document is clonedclipboard?: Doc;
-    useCors?: boolean;
-    icon?: string;
-    target?: Doc; // available for use in scripts as the primary target document
-    sourcePanel?: Doc; // panel to display in 'targetContainer' as the result of a button onClick script
-    targetContainer?: Doc; // document whose proto will be set to 'panel' as the result of a onClick click script
-    searchFileTypes?: List<string>; // file types allowed in a search query
-    strokeWidth?: number;
-    freezeChildren?: string; // whether children are now allowed to be added and or removed from a collection
-    treeViewHideTitle?: boolean; // whether to hide the top document title of a tree view
-    treeViewHideHeaderIfTemplate?: boolean; // whether to hide the header for a document in a tree view only if a childLayoutTemplate is provided (presBox)
-    treeViewHideHeader?: boolean; // whether to hide the header for a document in a tree view
-    treeViewHideHeaderFields?: boolean; // whether to hide the drop down options for tree view items.
-    treeViewGrowsHorizontally?: boolean; // whether an embedded tree view of the document can grow horizontally without growing vertically
-
-    // Action Button
-    buttonMenu?: boolean; // whether a action button should be displayed 
-    buttonMenuDoc?: Doc;
-    explainer?: string;
-
-    treeViewOpenIsTransient?: boolean; // ignores the treeViewOpen Doc flag, allowing a treeViewItem's expand/collapse state to be independent of other views of the same document in the same or any other tree view
-    _treeViewOpen?: boolean; // whether this document is expanded in a tree view  (note: need _ and regular versions since this can be specified for both proto and layout docs)
-    treeViewOpen?: boolean; // whether this document is expanded in a tree view
-    treeViewExpandedView?: string; // which field/thing is displayed when this item is opened in tree view
-    treeViewExpandedViewLock?: boolean; // whether the expanded view can be changed
-    treeViewChecked?: ScriptField; // script to call when a tree view checkbox is checked
-    treeViewTruncateTitleWidth?: number;
-    treeViewHasOverlay?: boolean; // whether the treeview has an overlay for freeform annotations
-    treeViewType?: string; // whether treeview is a Slide, file system, or (default) collection hierarchy
-    sidebarColor?: string;  // background color of text sidebar
-    sidebarViewType?: string; // collection type of text sidebar
-    docMaxAutoHeight?: number; // maximum height for newly created (eg, from pasting) text documents
-    text?: string;
-    textTransform?: string; // is linear view expanded
-    letterSpacing?: string; // is linear view expanded
-    selectedIndex?: number; // which item in a linear view has been selected using the "thumb doc" ui
-    clipboard?: Doc;
-    searchQuery?: string; // for quersyBox
-    useLinkSmallAnchor?: boolean;  // whether links to this document should use a miniature linkAnchorBox
-    border?: string; //for searchbox
-    hoverBackgroundColor?: string; // background color of a label when hovered
-    linkRelationshipList?: List<string>; // for storing different link relationships (when set by user in the link editor)
-    linkRelationshipSizes?: List<number>; //stores number of links contained in each relationship 
-    linkColorList?: List<string>; // colors of links corresponding to specific link relationships
+      system?: BOOLt = new BoolInfo("is this a system created/owned doc");
+      _dropAction?: DROPt = new DAInfo("what should happen to this document when it's dropped somewhere else");
+      allowOverlayDrop?: BOOLt = new BoolInfo("can documents be dropped onto this document without using dragging title bar or holding down embed key (ctrl)?");
+      childDropAction?: DROPt = new DAInfo("what should happen to the source document when it's dropped onto a child of a collection ");
+      targetDropAction?: DROPt = new DAInfo("what should happen to the source document when ??? ");
+      color?: string; // foreground color data doc
+      backgroundColor?: STRt = new StrInfo("background color for data doc");
+      _backgroundColor?: STRt = new StrInfo("background color for each template layout doc (overrides backgroundColor)", true);
+      _autoHeight?: BOOLt = new BoolInfo("whether document automatically resizes vertically to display contents", true);
+      _headerHeight?: NUMt = new NumInfo("height of document header used for displaying title", true);
+      _headerFontSize?: NUMt = new NumInfo("font size of header of custom notes", true);
+      _headerPointerEvents?: PEVt = new PEInfo("types of events the header of a custom text document can consume", true);
+      _panX?: NUMt = new NumInfo("horizontal pan location of a freeform view", true);
+      _panY?: NUMt = new NumInfo("vertical pan location of a freeform view", true);
+      _width?: NUMt = new NumInfo("displayed width of a document", true);
+      _height?: NUMt = new NumInfo("displayed height of document", true);
+      _nativeWidth?: NUMt = new NumInfo("native width of document contents (e.g., the pixel width of an image)", true);
+      _nativeHeight?: NUMt = new NumInfo("native height of document contents (e.g., the pixel height of an image)", true);
+      _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height", true);
+      _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units", true);
+      _fitWidth?: BOOLt = new BoolInfo("whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)", true);
+      _fitToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents
+      _lockedPosition?: boolean; // lock the x,y coordinates of the document so that it can't be dragged
+      _lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed
+      _isPushpin?: boolean; // whether document, when clicked, toggles display of its link target
+      _showTitle?: string; // field name to display in header (:hover is an optional suffix)
+      _showCaption?: string; // which field to display in the caption area.  leave empty to have no caption
+      _scrollTop?: number; // scroll location for pdfs
+      _noAutoscroll?: boolean;// whether collections autoscroll when this item is dragged
+      _chromeHidden?: boolean; // whether the editing chrome for a document is hidden
+      _searchDoc?: boolean; // is this a search document (used to change UI for search results in schema view)
+      _forceActive?: boolean; // flag to handle pointer events when not selected (or otherwise active)
+      _stayInCollection?: boolean;// whether the document should remain in its collection when someone tries to drag and drop it elsewhere
+      _raiseWhenDragged?: boolean; // whether a document is brought to front when dragged.
+      _hideContextMenu?: boolean; // whether the context menu can be shown
+      _viewType?: string; // sub type of a collection
+      _gridGap?: number; // gap between items in masonry view
+      _viewScale?: number; // how much a freeform view has been scaled (zoomed)
+      _overflow?: string; // set overflow behavior
+      _xMargin?: number; // gap between left edge of document and start of masonry/stacking layouts
+      _yMargin?: number; // gap between top edge of dcoument and start of masonry/stacking layouts
+      _xPadding?: number;
+      _yPadding?: number;
+      _itemIndex?: number; // which item index the carousel viewer is showing
+      _showSidebar?: boolean;  //whether an annotationsidebar should be displayed for text docuemnts
+      _singleLine?: boolean; // whether text document is restricted to a single line (carriage returns make new document)
+      _minFontSize?: number; // minimum font size for labelBoxes
+      _maxFontSize?: number; // maximum font size for labelBoxes
+      _columnWidth?: number;
+      _columnsHideIfEmpty?: boolean; // whether stacking view column headings should be hidden
+      _fontSize?: string;
+      _fontFamily?: string;
+      _fontWeight?: string;
+      _pivotField?: string; // field key used to determine headings for sections in stacking, masonry, pivot views
+      _curPage?: number; // current page of a PDF or other? paginated document
+      _currentTimecode?: number; // the current timecode of a time-based document (e.g., current time of a video)  value is in seconds
+      _currentFrame?: number; // the current frame of a frame-based collection (e.g., progressive slide)
+      _timecodeToShow?: number; // the time that a document should be displayed (e.g., when an annotation shows up as a video plays)
+      _timecodeToHide?: number; // the time that a document should be hidden
+      _timelineLabel?: boolean; // whether the document exists on a timeline
+      "_carousel-caption-xMargin"?: number;
+      "_carousel-caption-yMargin"?: number;
+      "icon-nativeWidth"?: number;
+      "icon-nativeHeight"?: number;
+      "dragFactory-count"?: number; // number of items created from a drag button (used for setting title with incrementing index)
+      x?: number;
+      y?: number;
+      z?: number; // whether document is in overlay (1) or not (0 or undefined)
+      lat?: number;
+      lng?: number;
+      infoWindowOpen?: boolean;
+      author?: string;
+      _layoutKey?: string;
+      unrendered?: boolean; // denotes an annotation that is not rendered with a DocumentView (e.g, rtf/pdf text selections and links to scroll locations in web/pdf)
+      type?: string;
+      title?: string;
+      "acl-Public"?: string; // public permissions
+      "_acl-Public"?: string; // public permissions
+      version?: string; // version identifier for a document
+      label?: string;
+      hidden?: boolean;
+      _hidden?: boolean;
+      pointerEvents?: string; // pointer events that the documentview should have
+      mediaState?: string; // status of media document: "pendingRecording", "recording", "paused", "playing"
+      autoPlayAnchors?: boolean; // whether to play audio/video when an anchor is clicked in a stackedTimeline.
+      dontPlayLinkOnSelect?: boolean;  // whether an audio/video should start playing when a link is followed to it.
+      toolTip?: string; // tooltip to display on hover
+      dontUndo?: boolean; // whether button clicks should be undoable (this is set to true for Undo/Redo/and sidebar buttons that open the siebar panel)
+      description?: string; // added for links
+      layout?: string | Doc; // default layout string for a document
+      contentPointerEvents?: string;  // pointer events allowed for content of a document view.  eg. set to "none" in menuSidebar for sharedDocs so that you can select a document, but not interact with its contents
+      childLimitHeight?: number; // whether to limit the height of collection children.  0 - means  height can be no bigger than width
+      childLayoutTemplate?: Doc; // template for collection to use to render its children (see PresBox layout in tree view)
+      childLayoutString?: string; // template string for collection to use to render its children
+      childDontRegisterViews?: boolean;
+      childHideLinkButton?: boolean; // hide link buttons on all children
+      hideLinkButton?: boolean; // whether the blue link counter button should be hidden
+      hideDecorationTitle?: boolean;
+      hideResizeHandles?: boolean;
+      hideDocumentButtonBar?: boolean;
+      hideAllLinks?: boolean; // whether all individual blue anchor dots should be hidden
+      isTemplateForField?: string; // the field key for which the containing document is a rendering template
+      isTemplateDoc?: boolean;
+      watchedDocuments?: Doc; // list of documents an icon doc monitors in order to display a badge count
+      targetScriptKey?: string; // where to write a template script (used by collections with click templates which need to target onClick, onDoubleClick, etc)
+      templates?: List<string>;
+      hero?: ImageField; // primary image that best represents a compound document (e.g., for a buxton device document that has multiple images)
+      caption?: RichTextField;
+      opacity?: number;
+      defaultBackgroundColor?: string;
+      _isLinkButton?: boolean; // marks a document as a button that will follow its primary link when clicked
+      _linkAutoMove?: boolean; // whether link endpoint should move around the edges of a document to make shortest path to other link endpoint
+      isFolder?: boolean;
+      lastFrame?: number; // the last frame of a frame-based collection (e.g., progressive slide)
+      activeFrame?: number; // the active frame of a document in a frame base collection
+      appearFrame?: number; // the frame in which the document appears
+      presTransition?: number; //the time taken for the transition TO a document
+      presDuration?: number; //the duration of the slide in presentation view
+      presProgressivize?: boolean;
+      borderRounding?: string;
+      boxShadow?: string;
+      data?: any;
+      baseProto?: boolean; // is this a base prototoype
+      dontRegisterView?: boolean;
+      lookupField?: ScriptField; // script that returns the value of a field. This script is passed the rootDoc, layoutDoc, field, and container of the document.  see PresBox.
+      "onDoubleClick-rawScript"?: string; // onDoubleClick script in raw text form
+      "onChildDoubleClick-rawScript"?: string; // onChildDoubleClick script in raw text form
+      "onChildClick-rawScript"?: string; // on ChildClick script in raw text form
+      "onClick-rawScript"?: string; // onClick script in raw text form
+      "onCheckedClick-rawScript"?: string; // onChecked script in raw text form
+      "onCheckedClick-params"?: List<string>; // parameter list for onChecked treeview functions
+      columnHeaders?: List<SchemaHeaderField>; // headers for stacking views
+      schemaHeaders?: List<SchemaHeaderField>; // headers for schema view
+      clipWidth?: number; // percent transition from before to after in comparisonBox
+      dockingConfig?: string;
+      annotationOn?: Doc;
+      isPushpin?: boolean;
+      isGroup?: boolean; // whether a collection should use a grouping UI behavior
+      _removeDropProperties?: List<string>; // list of properties that should be removed from a document when it is dropped.  e.g., a creator button may be forceActive to allow it be dragged, but the forceActive property can be removed from the dropped document
+
+      // BACKGROUND GRID
+      _backgroundGridShow?: boolean;
+
+      //BUTTONS
+      buttonText?: string;
+      iconShape?: string; // shapes of the fonticon border
+      btnType?: string;
+      btnList?: List<string>;
+      docColorBtn?: string;
+      userColorBtn?: string;
+      canClick?: string;
+      script?: ScriptField;
+      numBtnType?: string;
+      numBtnMax?: number;
+      numBtnMin?: number;
+      switchToggle?: boolean;
+
+      //LINEAR VIEW
+      linearViewIsExpanded?: boolean; // is linear view expanded
+      linearViewExpandable?: boolean; // can linear view be expanded
+      linearViewToggleButton?: string; // button to open close linear view group
+      linearViewSubMenu?: boolean;
+      linearViewFloating?: boolean;
+      flexGap?: number; // Linear view flex gap
+      flexDirection?: "unset" | "row" | "column" | "row-reverse" | "column-reverse";
+
+      layout_linkView?: Doc; // view template for a link document
+      layout_keyValue?: string; // view tempalte for key value docs
+      linkRelationship?: string; // type of relatinoship a link represents
+      linkDisplay?: boolean; // whether a link line should be dipslayed between the two link anchors
+      anchor1?: Doc;
+      anchor2?: Doc;
+      "anchor1-useLinkSmallAnchor"?: boolean; // whether anchor1 of a link should use a miniature anchor dot (as when the anchor is a text selection)
+      "anchor2-useLinkSmallAnchor"?: boolean; // whether anchor1 of a link should use a miniature anchor dot (as when the anchor is a text selection)
+      ignoreClick?: boolean;
+      onClick?: ScriptField;
+      onDoubleClick?: ScriptField;
+      onChildClick?: ScriptField; // script given to children of a collection to execute when they are clicked
+      onChildDoubleClick?: ScriptField; // script given to children of a collection to execute when they are double clicked
+      onPointerDown?: ScriptField;
+      onPointerUp?: ScriptField;
+      dropConverter?: ScriptField; // script to run when documents are dropped on this Document.
+      dragFactory?: Doc; // document to create when dragging with a suitable onDragStart script
+      clickFactory?: Doc; // document to create when clicking on a button with a suitable onClick script
+      onDragStart?: ScriptField; //script to execute at start of drag operation --  e.g., when a "creator" button is dragged this script generates a different document to drop
+      cloneFieldFilter?: List<string>; // fields not to copy when the document is clonedclipboard?: Doc;
+      useCors?: boolean;
+      icon?: string;
+      target?: Doc; // available for use in scripts as the primary target document
+      sourcePanel?: Doc; // panel to display in 'targetContainer' as the result of a button onClick script
+      targetContainer?: Doc; // document whose proto will be set to 'panel' as the result of a onClick click script
+      searchFileTypes?: List<string>; // file types allowed in a search query
+      strokeWidth?: number;
+      freezeChildren?: string; // whether children are now allowed to be added and or removed from a collection
+      treeViewHideTitle?: boolean; // whether to hide the top document title of a tree view
+      treeViewHideHeaderIfTemplate?: boolean; // whether to hide the header for a document in a tree view only if a childLayoutTemplate is provided (presBox)
+      treeViewHideHeader?: boolean; // whether to hide the header for a document in a tree view
+      treeViewHideHeaderFields?: boolean; // whether to hide the drop down options for tree view items.
+      treeViewGrowsHorizontally?: boolean; // whether an embedded tree view of the document can grow horizontally without growing vertically
+
+      // Action Button
+      buttonMenu?: boolean; // whether a action button should be displayed 
+      buttonMenuDoc?: Doc;
+      explainer?: string;
+
+      treeViewOpenIsTransient?: boolean; // ignores the treeViewOpen Doc flag, allowing a treeViewItem's expand/collapse state to be independent of other views of the same document in the same or any other tree view
+      _treeViewOpen?: boolean; // whether this document is expanded in a tree view  (note: need _ and regular versions since this can be specified for both proto and layout docs)
+      treeViewOpen?: boolean; // whether this document is expanded in a tree view
+      treeViewExpandedView?: string; // which field/thing is displayed when this item is opened in tree view
+      treeViewExpandedViewLock?: boolean; // whether the expanded view can be changed
+      treeViewChecked?: ScriptField; // script to call when a tree view checkbox is checked
+      treeViewTruncateTitleWidth?: number;
+      treeViewHasOverlay?: boolean; // whether the treeview has an overlay for freeform annotations
+      treeViewType?: string; // whether treeview is a Slide, file system, or (default) collection hierarchy
+      sidebarColor?: string;  // background color of text sidebar
+      sidebarViewType?: string; // collection type of text sidebar
+      docMaxAutoHeight?: number; // maximum height for newly created (eg, from pasting) text documents
+      text?: string;
+      textTransform?: string; // is linear view expanded
+      letterSpacing?: string; // is linear view expanded
+      selectedIndex?: number; // which item in a linear view has been selected using the "thumb doc" ui
+      clipboard?: Doc;
+      searchQuery?: string; // for quersyBox
+      useLinkSmallAnchor?: boolean;  // whether links to this document should use a miniature linkAnchorBox
+      border?: string; //for searchbox
+      hoverBackgroundColor?: string; // background color of a label when hovered
+      linkRelationshipList?: List<string>; // for storing different link relationships (when set by user in the link editor)
+      linkRelationshipSizes?: List<number>; //stores number of links contained in each relationship 
+      linkColorList?: List<string>; // colors of links corresponding to specific link relationships
 }
 export namespace Docs {
 
-    const _docOptions = new DocumentOptions();
-
-    export async function setupFieldInfos() {
-        return await DocServer.GetRefField("FieldInfos8") as Doc ??
-            runInAction(() => {
-                const infos = new Doc("FieldInfos8", true);
-                const keys = Object.keys(new DocumentOptions());
-                for (const key of keys) {
-                    const options = (_docOptions as any)[key] as FInfo;
-                    const finfo = new Doc();
-                    finfo.name = key;
-                    switch (options.type) {
-                        case "boolean": finfo.options = new List<boolean>(options.values as any as boolean[]); break;
-                        case "number": finfo.options = new List<number>(options.values as any as number[]); break;
-                        case "Doc": finfo.options = new List<Doc>(options.values as any as Doc[]); break;
-                        default: // string, pointerEvents, dimUnit, dropActionType
-                            finfo.options = new List<string>(options.values as any as string[]); break;
-                    }
-                    finfo.layoutField = options.layoutField;
-                    finfo.description = options.description;
-                    finfo.type = options.type;
-                    infos[key] = finfo;
-                }
-                return infos;
-            });
-    }
-
-    export let newAccount: boolean = false;
-
-    export namespace Prototypes {
-
-        type LayoutSource = { LayoutString: (key: string) => string };
-        type PrototypeTemplate = {
-            layout: {
-                view: LayoutSource,
-                dataField: string
-            },
-            data?: any,
-            options?: Partial<DocumentOptions>
-        };
-        type TemplateMap = Map<DocumentType, PrototypeTemplate>;
-        type PrototypeMap = Map<DocumentType, Doc>;
-        const defaultDataKey = "data";
-
-        const TemplateMap: TemplateMap = new Map([
-            [DocumentType.RTF, {
-                layout: { view: FormattedTextBox, dataField: "text" },
-                options: {
-                    _height: 35, _xMargin: 10, _yMargin: 10, nativeDimModifiable: true, nativeHeightUnfrozen: true, treeViewGrowsHorizontally: true,
-                    links: "@links(self)"
-                }
-            }],
-            [DocumentType.SEARCH, {
-                layout: { view: SearchBox, dataField: defaultDataKey },
-                options: { _width: 400, links: "@links(self)" }
-            }],
-            [DocumentType.FILTER, {
-                layout: { view: FilterBox, dataField: defaultDataKey },
-                options: { _width: 400, links: "@links(self)" }
-            }],
-            [DocumentType.COLOR, {
-                layout: { view: ColorBox, dataField: defaultDataKey },
-                options: { _nativeWidth: 220, _nativeHeight: 300, links: "@links(self)" }
-            }],
-            [DocumentType.IMG, {
-                layout: { view: ImageBox, dataField: defaultDataKey },
-                options: { links: "@links(self)" }
-            }],
-            [DocumentType.WEB, {
-                layout: { view: WebBox, dataField: defaultDataKey },
-                options: { _height: 300, _fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true, links: "@links(self)" }
-            }],
-            [DocumentType.COL, {
-                layout: { view: CollectionView, dataField: defaultDataKey },
-                options: { _fitWidth: true, _panX: 0, _panY: 0, _viewScale: 1, links: "@links(self)" }
-            }],
-            [DocumentType.KVP, {
-                layout: { view: KeyValueBox, dataField: defaultDataKey },
-                options: { _fitWidth: true, _height: 150 }
-            }],
-            [DocumentType.VID, {
-                layout: { view: VideoBox, dataField: defaultDataKey },
-                options: { _currentTimecode: 0, links: "@links(self)" },
-            }],
-            [DocumentType.AUDIO, {
-                layout: { view: AudioBox, dataField: defaultDataKey },
-                options: { _height: 100, backgroundColor: "lightGray", links: "@links(self)" }
-            }],
-            [DocumentType.REC, {
-                layout: { view: VideoBox, dataField: defaultDataKey },
-                options: { _height: 100, backgroundColor: "pink", links: "@links(self)" }
-            }],
-            [DocumentType.PDF, {
-                layout: { view: PDFBox, dataField: defaultDataKey },
-                options: { _curPage: 1, _fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true, links: "@links(self)" }
-            }],
-            [DocumentType.MAP, {
-                layout: { view: MapBox, dataField: defaultDataKey },
-                options: { _height: 600, _width: 800, links: "@links(self)" }
-            }],
-            [DocumentType.IMPORT, {
-                layout: { view: DirectoryImportBox, dataField: defaultDataKey },
-                options: { _height: 150 }
-            }],
-            [DocumentType.LINK, {
-                layout: { view: LinkBox, dataField: defaultDataKey },
-                options: {
-                    childDontRegisterViews: true, _isLinkButton: true, _height: 150, description: "", showCaption: "description",
-                    backgroundColor: "lightblue", // lightblue is default color for linking dot and link documents text comment area
-                    links: "@links(self)",
-                    _removeDropProperties: new List(["isLinkButton"]),
-                }
-            }],
-            [DocumentType.LINKDB, {
-                data: new List<Doc>(),
-                layout: { view: EmptyBox, dataField: defaultDataKey },
-                options: { childDropAction: "alias", title: "Global Link Database" }
-            }],
-            [DocumentType.SCRIPTDB, {
-                data: new List<Doc>(),
-                layout: { view: EmptyBox, dataField: defaultDataKey },
-                options: { childDropAction: "alias", title: "Global Script Database" }
-            }],
-            [DocumentType.SCRIPTING, {
-                layout: { view: ScriptingBox, dataField: defaultDataKey },
-                options: { links: "@links(self)" }
-            }],
-            [DocumentType.YOUTUBE, {
-                layout: { view: YoutubeBox, dataField: defaultDataKey }
-            }],
-            [DocumentType.LABEL, {
-                layout: { view: LabelBox, dataField: defaultDataKey },
-                options: { links: "@links(self)", _singleLine: true }
-            }],
-            [DocumentType.EQUATION, {
-                layout: { view: EquationBox, dataField: defaultDataKey },
-                options: { links: "@links(self)", hideResizeHandles: true, hideDecorationTitle: true }
-            }],
-            [DocumentType.FUNCPLOT, {
-                layout: { view: FunctionPlotBox, dataField: defaultDataKey },
-                options: { links: "@links(self)" }
-            }],
-            [DocumentType.BUTTON, {
-                layout: { view: LabelBox, dataField: "onClick" },
-                options: { links: "@links(self)" }
-            }],
-            [DocumentType.SLIDER, {
-                layout: { view: SliderBox, dataField: defaultDataKey, },
-                options: { links: "@links(self)", treeViewGrowsHorizontally: true }
-            }],
-            [DocumentType.PRES, {
-                layout: { view: PresBox, dataField: defaultDataKey },
-                options: { links: "@links(self)" }
-            }],
-            [DocumentType.FONTICON, {
-                layout: { view: FontIconBox, dataField: defaultDataKey },
-                options: { hideLinkButton: true, _width: 40, _height: 40, borderRounding: "100%", links: "@links(self)" },
-            }],
-            [DocumentType.WEBCAM, {
-                layout: { view: RecordingBox, dataField: defaultDataKey },
-                options: { links: "@links(self)" }
-            }],
-            [DocumentType.PRESELEMENT, {
-                layout: { view: PresElementBox, dataField: defaultDataKey }
-            }],
-            [DocumentType.MARKER, {
-                layout: { view: CollectionView, dataField: defaultDataKey },
-                options: { links: "@links(self)", hideLinkButton: true, pointerEvents: "none" }
-            }],
-            [DocumentType.INK, { // NOTE: this is unused!! ink fields are filled in directly within the InkDocument() method
-                layout: { view: InkingStroke, dataField: defaultDataKey },
-                options: { links: "@links(self)" }
-            }],
-            [DocumentType.SCREENSHOT, {
-                layout: { view: ScreenshotBox, dataField: defaultDataKey },
-                options: { links: "@links(self)" }
-            }],
-            [DocumentType.COMPARISON, {
-                layout: { view: ComparisonBox, dataField: defaultDataKey },
-                options: { clipWidth: 50, backgroundColor: "gray", targetDropAction: "alias", links: "@links(self)" }
-            }],
-            [DocumentType.GROUPDB, {
-                data: new List<Doc>(),
-                layout: { view: EmptyBox, dataField: defaultDataKey },
-                options: { childDropAction: "alias", title: "Global Group Database" }
-            }],
-            [DocumentType.GROUP, {
-                layout: { view: EmptyBox, dataField: defaultDataKey },
-                options: { links: "@links(self)" }
-            }],
-        ]);
-
-        const suffix = "Proto";
-
-        /**
-         * This function loads or initializes the prototype for each docment type.
-         * 
-         * This is an asynchronous function because it has to attempt
-         * to fetch the prototype documents from the server.
-         * 
-         * Once we have this object that maps the prototype ids to a potentially
-         * undefined document, we either initialize our private prototype
-         * variables with the document returned from the server or, if prototypes
-         * haven't been initialized, the newly initialized prototype document.
-         */
-        export async function initialize(): Promise<void> {
-            ProxyField.initPlugin();
-            ComputedField.initPlugin();
-            // non-guid string ids for each document prototype
-            const prototypeIds = Object.values(DocumentType).filter(type => type !== DocumentType.NONE).map(type => type + suffix);
-            // fetch the actual prototype documents from the server
-            const actualProtos = Docs.newAccount ? {} : await DocServer.GetRefFields(prototypeIds);
-            if (!Docs.newAccount) {
-                Cast(actualProtos[DocumentType.WEB + suffix], Doc, null).nativeHeightUnfrozen = true; // to avoid having to recreate the DB
-                Cast(actualProtos[DocumentType.PDF + suffix], Doc, null).nativeHeightUnfrozen = true;
-                Cast(actualProtos[DocumentType.RTF + suffix], Doc, null).nativeHeightUnfrozen = true;
-                Cast(actualProtos[DocumentType.WEB + suffix], Doc, null).nativeDimModifiable = true; // to avoid having to recreate the DB
-                Cast(actualProtos[DocumentType.PDF + suffix], Doc, null).nativeDimModifiable = true;
-                Cast(actualProtos[DocumentType.RTF + suffix], Doc, null).nativeDimModifiable = true;
-            }
-
-            // update this object to include any default values: DocumentOptions for all prototypes
-            prototypeIds.map(id => {
-                const existing = actualProtos[id] as Doc;
-                const type = id.replace(suffix, "") as DocumentType;
-                // get or create prototype of the specified type...
-                const target = existing || buildPrototype(type, id);
-                // ...and set it if not undefined (can be undefined only if TemplateMap does not contain
-                // an entry dedicated to the given DocumentType)
-                target && PrototypeMap.set(type, target);
-            });
-        }
-
-        /**
-         * Retrieves the prototype for the given document type, or
-         * undefined if that type's proto doesn't have a configuration
-         * in the template map.
-         * @param type 
-         */
-        const PrototypeMap: PrototypeMap = new Map();
-        export function get(type: DocumentType): Doc { return PrototypeMap.get(type)!; }
-
-        /**
-         * A collection of all links in the database.  Ideally, this would be a search, but for now all links are cached here.
-         */
-        export function MainLinkDocument() { return Prototypes.get(DocumentType.LINKDB); }
-
-        /**
-         * A collection of all scripts in the database
-         */
-        export function MainScriptDocument() { return Prototypes.get(DocumentType.SCRIPTDB); }
-
-        /**
-         * A collection of all user acl groups in the database
-         */
-        export function MainGroupDocument() { return Prototypes.get(DocumentType.GROUPDB); }
-
-        /**
-         * This is a convenience method that is used to initialize
-         * prototype documents for the first time.
-         * 
-         * @param protoId the id of the prototype, indicating the specific prototype
-         * to initialize (see the *protoId list at the top of the namespace)
-         * @param title the prototype document's title, follows *-PROTO
-         * @param layout the layout key for this prototype and thus the
-         * layout key that all delegates will inherit
-         * @param options any value specified in the DocumentOptions object likewise
-         * becomes the default value for that key for all delegates
-         */
-        function buildPrototype(type: DocumentType, prototypeId: string): Opt<Doc> {
-            // load template from type
-            const template = TemplateMap.get(type);
-            if (!template) {
-                return undefined;
-            }
-            const layout = template.layout;
-            // create title
-            const upper = suffix.toUpperCase();
-            const title = prototypeId.toUpperCase().replace(upper, `_${upper}`);
-            // synthesize the default options, the type and title from computed values and
-            // whatever options pertain to this specific prototype
-            const options: DocumentOptions = {
-                system: true, _layoutKey: "layout", title, type, baseProto: true, x: 0, y: 0, _width: 300, ...(template.options || {}),
-                layout: layout.view?.LayoutString(layout.dataField), data: template.data, layout_keyValue: KeyValueBox.LayoutString("")
+      const _docOptions = new DocumentOptions();
+
+      export async function setupFieldInfos() {
+            return await DocServer.GetRefField("FieldInfos8") as Doc ??
+                  runInAction(() => {
+                        const infos = new Doc("FieldInfos8", true);
+                        const keys = Object.keys(new DocumentOptions());
+                        for (const key of keys) {
+                              const options = (_docOptions as any)[key] as FInfo;
+                              const finfo = new Doc();
+                              finfo.name = key;
+                              switch (options.type) {
+                                    case "boolean": finfo.options = new List<boolean>(options.values as any as boolean[]); break;
+                                    case "number": finfo.options = new List<number>(options.values as any as number[]); break;
+                                    case "Doc": finfo.options = new List<Doc>(options.values as any as Doc[]); break;
+                                    default: // string, pointerEvents, dimUnit, dropActionType
+                                          finfo.options = new List<string>(options.values as any as string[]); break;
+                              }
+                              finfo.layoutField = options.layoutField;
+                              finfo.description = options.description;
+                              finfo.type = options.type;
+                              infos[key] = finfo;
+                        }
+                        return infos;
+                  });
+      }
+
+      export let newAccount: boolean = false;
+
+      export namespace Prototypes {
+
+            type LayoutSource = { LayoutString: (key: string) => string };
+            type PrototypeTemplate = {
+                  layout: {
+                        view: LayoutSource,
+                        dataField: string
+                  },
+                  data?: any,
+                  options?: Partial<DocumentOptions>
             };
-            Object.entries(options).map(pair => {
-                if (typeof pair[1] === "string" && pair[1].startsWith("@")) {
-                    (options as any)[pair[0]] = ComputedField.MakeFunction(pair[1].substring(1));
-                }
-            });
-            return Doc.assign(new Doc(prototypeId, true), options as any, undefined, true);
-        }
-    }
-
-    /**
-     * Encapsulates the factory used to create new document instances
-     * delegated from top-level prototypes
-     */
-    export namespace Create {
-
-        /**
-         * This function receives the relevant document prototype and uses
-         * it to create a new of that base-level prototype, or the
-         * underlying data document, which it then delegates again 
-         * to create the view document.
-         * 
-         * It also takes the opportunity to register the user
-         * that created the document and the time of creation.
-         * 
-         * @param proto the specific document prototype off of which to model
-         * this new instance (textProto, imageProto, etc.)
-         * @param data the Field to store at this new instance's data key
-         * @param options any initial values to provide for this new instance
-         * @param delegId if applicable, an existing document id. If undefined, Doc's
-         * constructor just generates a new GUID. This is currently used
-         * only when creating a DockDocument from the current user's already existing
-         * main document.
-         */
-        function InstanceFromProto(proto: Doc, data: Field | undefined, options: DocumentOptions, delegId?: string, fieldKey: string = "data", protoId?: string) {
-            const viewKeys = ["x", "y", "system"]; // keys that should be addded to the view document even though they don't begin with an "_"
-            const { omit: dataProps, extract: viewProps } = OmitKeys(options, viewKeys, "^_");
-
-            dataProps["acl-Override"] = "None";
-            dataProps["acl-Public"] = options["acl-Public"] ? options["acl-Public"] : Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment;
-
-            dataProps.system = viewProps.system;
-            dataProps.isPrototype = true;
-            dataProps.author = Doc.CurrentUserEmail;
-            dataProps.creationDate = new DateField;
-            dataProps[`${fieldKey}-lastModified`] = new DateField;
-
-            dataProps[fieldKey] = data;
-
-            // so that the list of annotations is already initialised, prevents issues in addonly.
-            // without this, if a doc has no annotations but the user has AddOnly privileges, they won't be able to add an annotation because they would have needed to create the field's list which they don't have permissions to do.
-            dataProps[fieldKey + "-annotations"] = new List<Doc>();
-            const dataDoc = Doc.assign(Doc.MakeDelegate(proto, protoId), dataProps, undefined, true);
-
-            const viewFirstProps: { [id: string]: any } = {};
-            viewFirstProps["acl-Public"] = options["_acl-Public"] ? options["_acl-Public"] : Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment;
-            viewFirstProps["acl-Override"] = "None";
-            viewFirstProps.author = Doc.CurrentUserEmail;
-            const viewDoc = Doc.assign(Doc.MakeDelegate(dataDoc, delegId), viewFirstProps, true, true);
-            Doc.assign(viewDoc, viewProps, true, true);
-            ![DocumentType.LINK, DocumentType.MARKER, DocumentType.LABEL].includes(viewDoc.type as any) && DocUtils.MakeLinkToActiveAudio(() => viewDoc);
-
-            !Doc.IsSystem(dataDoc) && ![DocumentType.MARKER, DocumentType.KVP, DocumentType.LINK, DocumentType.LINKANCHOR].includes(proto.type as any) &&
-                !dataDoc.isFolder && !dataProps.annotationOn && Doc.AddDocToList(Cast(Doc.UserDoc().myFileOrphans, Doc, null), "data", dataDoc);
-
-            updateCachedAcls(dataDoc);
-            updateCachedAcls(viewDoc);
-            return viewDoc;
-        }
-
-        export function ImageDocument(url: string, options: DocumentOptions = {}) {
-            const imgField = new ImageField(url);
-            return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: basename(url), ...options });
-        }
-
-        export function PresDocument(options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.PRES), new List<Doc>(), options);
-        }
-
-        export function ScriptingDocument(script: Opt<ScriptField>, options: DocumentOptions = {}, fieldKey?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.SCRIPTING), script,
-                { ...options, layout: fieldKey ? ScriptingBox.LayoutString(fieldKey) : undefined });
-        }
-
-        export function VideoDocument(url: string, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.VID), new VideoField(url), options);
-        }
-
-        export function YoutubeDocument(url: string, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.YOUTUBE), new YoutubeField(url), options);
-        }
-
-        export function WebCamDocument(url: string, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.WEBCAM), "", options);
-        }
-
-        export function ScreenshotDocument(options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.SCREENSHOT), "", options);
-        }
-
-        export function ComparisonDocument(options: DocumentOptions = { title: "Comparison Box" }) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COMPARISON), "", options);
-        }
-
-        export function AudioDocument(url: string, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.AUDIO), new AudioField(url),
-                { ...options, backgroundColor: ComputedField.MakeFunction("this._mediaState === 'playing' ? 'green':'gray'") as any });
-        }
-
-        export function RecordingDocument(url: string, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.REC), "", options);
-        }
-
-        export function SearchDocument(options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.SEARCH), new List<Doc>([]), options);
-        }
-
-        export function ColorDocument(options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COLOR), "", options);
-        }
-
-        export function RTFDocument(field: RichTextField, options: DocumentOptions = {}, fieldKey: string = "text") {
-            return InstanceFromProto(Prototypes.get(DocumentType.RTF), field, options, undefined, fieldKey);
-        }
-        export function TextDocument(text: string, options: DocumentOptions = {}, fieldKey: string = "text") {
-            const rtf = {
-                doc: {
-                    type: "doc", content: [{
-                        type: "paragraph",
-                        content: [{
-                            type: "text",
-                            text
-                        }]
-                    }]
-                },
-                selection: { type: "text", anchor: 1, head: 1 },
-                storedMarks: []
+            type TemplateMap = Map<DocumentType, PrototypeTemplate>;
+            type PrototypeMap = Map<DocumentType, Doc>;
+            const defaultDataKey = "data";
+
+            const TemplateMap: TemplateMap = new Map([
+                  [DocumentType.RTF, {
+                        layout: { view: FormattedTextBox, dataField: "text" },
+                        options: {
+                              _height: 35, _xMargin: 10, _yMargin: 10, nativeDimModifiable: true, nativeHeightUnfrozen: true, treeViewGrowsHorizontally: true,
+                              links: "@links(self)"
+                        }
+                  }],
+                  [DocumentType.SEARCH, {
+                        layout: { view: SearchBox, dataField: defaultDataKey },
+                        options: { _width: 400, links: "@links(self)" }
+                  }],
+                  [DocumentType.FILTER, {
+                        layout: { view: FilterBox, dataField: defaultDataKey },
+                        options: { _width: 400, links: "@links(self)" }
+                  }],
+                  [DocumentType.COLOR, {
+                        layout: { view: ColorBox, dataField: defaultDataKey },
+                        options: { _nativeWidth: 220, _nativeHeight: 300, links: "@links(self)" }
+                  }],
+                  [DocumentType.IMG, {
+                        layout: { view: ImageBox, dataField: defaultDataKey },
+                        options: { links: "@links(self)" }
+                  }],
+                  [DocumentType.WEB, {
+                        layout: { view: WebBox, dataField: defaultDataKey },
+                        options: { _height: 300, _fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true, links: "@links(self)" }
+                  }],
+                  [DocumentType.COL, {
+                        layout: { view: CollectionView, dataField: defaultDataKey },
+                        options: { _fitWidth: true, _panX: 0, _panY: 0, _viewScale: 1, links: "@links(self)" }
+                  }],
+                  [DocumentType.KVP, {
+                        layout: { view: KeyValueBox, dataField: defaultDataKey },
+                        options: { _fitWidth: true, _height: 150 }
+                  }],
+                  [DocumentType.VID, {
+                        layout: { view: VideoBox, dataField: defaultDataKey },
+                        options: { _currentTimecode: 0, links: "@links(self)" },
+                  }],
+                  [DocumentType.AUDIO, {
+                        layout: { view: AudioBox, dataField: defaultDataKey },
+                        options: { _height: 100, backgroundColor: "lightGray", links: "@links(self)" }
+                  }],
+                  [DocumentType.REC, {
+                        layout: { view: VideoBox, dataField: defaultDataKey },
+                        options: { _height: 100, backgroundColor: "pink", links: "@links(self)" }
+                  }],
+                  [DocumentType.PDF, {
+                        layout: { view: PDFBox, dataField: defaultDataKey },
+                        options: { _curPage: 1, _fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true, links: "@links(self)" }
+                  }],
+                  [DocumentType.MAP, {
+                        layout: { view: MapBox, dataField: defaultDataKey },
+                        options: { _height: 600, _width: 800, links: "@links(self)" }
+                  }],
+                  [DocumentType.IMPORT, {
+                        layout: { view: DirectoryImportBox, dataField: defaultDataKey },
+                        options: { _height: 150 }
+                  }],
+                  [DocumentType.LINK, {
+                        layout: { view: LinkBox, dataField: defaultDataKey },
+                        options: {
+                              childDontRegisterViews: true, _isLinkButton: true, _height: 150, description: "", showCaption: "description",
+                              backgroundColor: "lightblue", // lightblue is default color for linking dot and link documents text comment area
+                              links: "@links(self)",
+                              _removeDropProperties: new List(["isLinkButton"]),
+                        }
+                  }],
+                  [DocumentType.LINKDB, {
+                        data: new List<Doc>(),
+                        layout: { view: EmptyBox, dataField: defaultDataKey },
+                        options: { childDropAction: "alias", title: "Global Link Database" }
+                  }],
+                  [DocumentType.SCRIPTDB, {
+                        data: new List<Doc>(),
+                        layout: { view: EmptyBox, dataField: defaultDataKey },
+                        options: { childDropAction: "alias", title: "Global Script Database" }
+                  }],
+                  [DocumentType.SCRIPTING, {
+                        layout: { view: ScriptingBox, dataField: defaultDataKey },
+                        options: { links: "@links(self)" }
+                  }],
+                  [DocumentType.YOUTUBE, {
+                        layout: { view: YoutubeBox, dataField: defaultDataKey }
+                  }],
+                  [DocumentType.LABEL, {
+                        layout: { view: LabelBox, dataField: defaultDataKey },
+                        options: { links: "@links(self)", _singleLine: true }
+                  }],
+                  [DocumentType.EQUATION, {
+                        layout: { view: EquationBox, dataField: defaultDataKey },
+                        options: { links: "@links(self)", hideResizeHandles: true, hideDecorationTitle: true }
+                  }],
+                  [DocumentType.FUNCPLOT, {
+                        layout: { view: FunctionPlotBox, dataField: defaultDataKey },
+                        options: { links: "@links(self)" }
+                  }],
+                  [DocumentType.BUTTON, {
+                        layout: { view: LabelBox, dataField: "onClick" },
+                        options: { links: "@links(self)" }
+                  }],
+                  [DocumentType.SLIDER, {
+                        layout: { view: SliderBox, dataField: defaultDataKey, },
+                        options: { links: "@links(self)", treeViewGrowsHorizontally: true }
+                  }],
+                  [DocumentType.PRES, {
+                        layout: { view: PresBox, dataField: defaultDataKey },
+                        options: { links: "@links(self)" }
+                  }],
+                  [DocumentType.FONTICON, {
+                        layout: { view: FontIconBox, dataField: defaultDataKey },
+                        options: { hideLinkButton: true, _width: 40, _height: 40, borderRounding: "100%", links: "@links(self)", hideDocumentButtonBar: true },
+                  }],
+                  [DocumentType.WEBCAM, {
+                        layout: { view: RecordingBox, dataField: defaultDataKey },
+                        options: { links: "@links(self)" }
+                  }],
+                  [DocumentType.PRESELEMENT, {
+                        layout: { view: PresElementBox, dataField: defaultDataKey }
+                  }],
+                  [DocumentType.MARKER, {
+                        layout: { view: CollectionView, dataField: defaultDataKey },
+                        options: { links: "@links(self)", hideLinkButton: true, pointerEvents: "none" }
+                  }],
+                  [DocumentType.INK, { // NOTE: this is unused!! ink fields are filled in directly within the InkDocument() method
+                        layout: { view: InkingStroke, dataField: defaultDataKey },
+                        options: { links: "@links(self)" }
+                  }],
+                  [DocumentType.SCREENSHOT, {
+                        layout: { view: ScreenshotBox, dataField: defaultDataKey },
+                        options: { links: "@links(self)" }
+                  }],
+                  [DocumentType.COMPARISON, {
+                        layout: { view: ComparisonBox, dataField: defaultDataKey },
+                        options: { clipWidth: 50, backgroundColor: "gray", targetDropAction: "alias", links: "@links(self)" }
+                  }],
+                  [DocumentType.GROUPDB, {
+                        data: new List<Doc>(),
+                        layout: { view: EmptyBox, dataField: defaultDataKey },
+                        options: { childDropAction: "alias", title: "Global Group Database" }
+                  }],
+                  [DocumentType.GROUP, {
+                        layout: { view: EmptyBox, dataField: defaultDataKey },
+                        options: { links: "@links(self)" }
+                  }],
+            ]);
+
+            const suffix = "Proto";
+
+            /**
+             * This function loads or initializes the prototype for each docment type.
+             * 
+             * This is an asynchronous function because it has to attempt
+             * to fetch the prototype documents from the server.
+             * 
+             * Once we have this object that maps the prototype ids to a potentially
+             * undefined document, we either initialize our private prototype
+             * variables with the document returned from the server or, if prototypes
+             * haven't been initialized, the newly initialized prototype document.
+             */
+            export async function initialize(): Promise<void> {
+                  ProxyField.initPlugin();
+                  ComputedField.initPlugin();
+                  // non-guid string ids for each document prototype
+                  const prototypeIds = Object.values(DocumentType).filter(type => type !== DocumentType.NONE).map(type => type + suffix);
+                  // fetch the actual prototype documents from the server
+                  const actualProtos = Docs.newAccount ? {} : await DocServer.GetRefFields(prototypeIds);
+                  if (!Docs.newAccount) {
+                        Cast(actualProtos[DocumentType.WEB + suffix], Doc, null).nativeHeightUnfrozen = true; // to avoid having to recreate the DB
+                        Cast(actualProtos[DocumentType.PDF + suffix], Doc, null).nativeHeightUnfrozen = true;
+                        Cast(actualProtos[DocumentType.RTF + suffix], Doc, null).nativeHeightUnfrozen = true;
+                        Cast(actualProtos[DocumentType.WEB + suffix], Doc, null).nativeDimModifiable = true; // to avoid having to recreate the DB
+                        Cast(actualProtos[DocumentType.PDF + suffix], Doc, null).nativeDimModifiable = true;
+                        Cast(actualProtos[DocumentType.RTF + suffix], Doc, null).nativeDimModifiable = true;
+                  }
+
+                  // update this object to include any default values: DocumentOptions for all prototypes
+                  prototypeIds.map(id => {
+                        const existing = actualProtos[id] as Doc;
+                        const type = id.replace(suffix, "") as DocumentType;
+                        // get or create prototype of the specified type...
+                        const target = existing || buildPrototype(type, id);
+                        // ...and set it if not undefined (can be undefined only if TemplateMap does not contain
+                        // an entry dedicated to the given DocumentType)
+                        target && PrototypeMap.set(type, target);
+                  });
+            }
+
+            /**
+             * Retrieves the prototype for the given document type, or
+             * undefined if that type's proto doesn't have a configuration
+             * in the template map.
+             * @param type 
+             */
+            const PrototypeMap: PrototypeMap = new Map();
+            export function get(type: DocumentType): Doc { return PrototypeMap.get(type)!; }
+
+            /**
+             * A collection of all links in the database.  Ideally, this would be a search, but for now all links are cached here.
+             */
+            export function MainLinkDocument() { return Prototypes.get(DocumentType.LINKDB); }
+
+            /**
+             * A collection of all scripts in the database
+             */
+            export function MainScriptDocument() { return Prototypes.get(DocumentType.SCRIPTDB); }
+
+            /**
+             * A collection of all user acl groups in the database
+             */
+            export function MainGroupDocument() { return Prototypes.get(DocumentType.GROUPDB); }
+
+            /**
+             * This is a convenience method that is used to initialize
+             * prototype documents for the first time.
+             * 
+             * @param protoId the id of the prototype, indicating the specific prototype
+             * to initialize (see the *protoId list at the top of the namespace)
+             * @param title the prototype document's title, follows *-PROTO
+             * @param layout the layout key for this prototype and thus the
+             * layout key that all delegates will inherit
+             * @param options any value specified in the DocumentOptions object likewise
+             * becomes the default value for that key for all delegates
+             */
+            function buildPrototype(type: DocumentType, prototypeId: string): Opt<Doc> {
+                  // load template from type
+                  const template = TemplateMap.get(type);
+                  if (!template) {
+                        return undefined;
+                  }
+                  const layout = template.layout;
+                  // create title
+                  const upper = suffix.toUpperCase();
+                  const title = prototypeId.toUpperCase().replace(upper, `_${upper}`);
+                  // synthesize the default options, the type and title from computed values and
+                  // whatever options pertain to this specific prototype
+                  const options: DocumentOptions = {
+                        system: true, _layoutKey: "layout", title, type, baseProto: true, x: 0, y: 0, _width: 300, ...(template.options || {}),
+                        layout: layout.view?.LayoutString(layout.dataField), data: template.data, layout_keyValue: KeyValueBox.LayoutString("")
+                  };
+                  Object.entries(options).map(pair => {
+                        if (typeof pair[1] === "string" && pair[1].startsWith("@")) {
+                              (options as any)[pair[0]] = ComputedField.MakeFunction(pair[1].substring(1));
+                        }
+                  });
+                  return Doc.assign(new Doc(prototypeId, true), options as any, undefined, true);
+            }
+      }
+
+      /**
+       * Encapsulates the factory used to create new document instances
+       * delegated from top-level prototypes
+       */
+      export namespace Create {
+
+            /**
+             * This function receives the relevant document prototype and uses
+             * it to create a new of that base-level prototype, or the
+             * underlying data document, which it then delegates again 
+             * to create the view document.
+             * 
+             * It also takes the opportunity to register the user
+             * that created the document and the time of creation.
+             * 
+             * @param proto the specific document prototype off of which to model
+             * this new instance (textProto, imageProto, etc.)
+             * @param data the Field to store at this new instance's data key
+             * @param options any initial values to provide for this new instance
+             * @param delegId if applicable, an existing document id. If undefined, Doc's
+             * constructor just generates a new GUID. This is currently used
+             * only when creating a DockDocument from the current user's already existing
+             * main document.
+             */
+            function InstanceFromProto(proto: Doc, data: Field | undefined, options: DocumentOptions, delegId?: string, fieldKey: string = "data", protoId?: string) {
+                  const viewKeys = ["x", "y", "system"]; // keys that should be addded to the view document even though they don't begin with an "_"
+                  const { omit: dataProps, extract: viewProps } = OmitKeys(options, viewKeys, "^_");
+
+                  dataProps["acl-Override"] = "None";
+                  dataProps["acl-Public"] = options["acl-Public"] ? options["acl-Public"] : Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment;
+
+                  dataProps.system = viewProps.system;
+                  dataProps.isPrototype = true;
+                  dataProps.author = Doc.CurrentUserEmail;
+                  dataProps.creationDate = new DateField;
+                  dataProps[`${fieldKey}-lastModified`] = new DateField;
+
+                  dataProps[fieldKey] = data;
+
+                  // so that the list of annotations is already initialised, prevents issues in addonly.
+                  // without this, if a doc has no annotations but the user has AddOnly privileges, they won't be able to add an annotation because they would have needed to create the field's list which they don't have permissions to do.
+                  dataProps[fieldKey + "-annotations"] = new List<Doc>();
+                  const dataDoc = Doc.assign(Doc.MakeDelegate(proto, protoId), dataProps, undefined, true);
+
+                  const viewFirstProps: { [id: string]: any } = {};
+                  viewFirstProps["acl-Public"] = options["_acl-Public"] ? options["_acl-Public"] : Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment;
+                  viewFirstProps["acl-Override"] = "None";
+                  viewFirstProps.author = Doc.CurrentUserEmail;
+                  const viewDoc = Doc.assign(Doc.MakeDelegate(dataDoc, delegId), viewFirstProps, true, true);
+                  Doc.assign(viewDoc, viewProps, true, true);
+                  ![DocumentType.LINK, DocumentType.MARKER, DocumentType.LABEL].includes(viewDoc.type as any) && DocUtils.MakeLinkToActiveAudio(() => viewDoc);
+
+                  !Doc.IsSystem(dataDoc) && ![DocumentType.MARKER, DocumentType.KVP, DocumentType.LINK, DocumentType.LINKANCHOR].includes(proto.type as any) &&
+                        !dataDoc.isFolder && !dataProps.annotationOn && Doc.AddDocToList(Cast(Doc.UserDoc().myFileOrphans, Doc, null), "data", dataDoc);
+
+                  updateCachedAcls(dataDoc);
+                  updateCachedAcls(viewDoc);
+                  return viewDoc;
+            }
+
+            export function ImageDocument(url: string, options: DocumentOptions = {}) {
+                  const imgField = new ImageField(url);
+                  return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: basename(url), ...options });
+            }
+
+            export function PresDocument(options: DocumentOptions = {}) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.PRES), new List<Doc>(), options);
+            }
+
+            export function ScriptingDocument(script: Opt<ScriptField>, options: DocumentOptions = {}, fieldKey?: string) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.SCRIPTING), script,
+                        { ...options, layout: fieldKey ? ScriptingBox.LayoutString(fieldKey) : undefined });
+            }
+
+            export function VideoDocument(url: string, options: DocumentOptions = {}) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.VID), new VideoField(url), options);
+            }
+
+            export function YoutubeDocument(url: string, options: DocumentOptions = {}) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.YOUTUBE), new YoutubeField(url), options);
+            }
+
+            export function WebCamDocument(url: string, options: DocumentOptions = {}) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.WEBCAM), "", options);
+            }
+
+            export function ScreenshotDocument(options: DocumentOptions = {}) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.SCREENSHOT), "", options);
+            }
+
+            export function ComparisonDocument(options: DocumentOptions = { title: "Comparison Box" }) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.COMPARISON), "", options);
+            }
+
+            export function AudioDocument(url: string, options: DocumentOptions = {}) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.AUDIO), new AudioField(url),
+                        { ...options, backgroundColor: ComputedField.MakeFunction("this._mediaState === 'playing' ? 'green':'gray'") as any });
+            }
+
+            export function RecordingDocument(url: string, options: DocumentOptions = {}) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.REC), "", options);
+            }
+
+            export function SearchDocument(options: DocumentOptions = {}) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.SEARCH), new List<Doc>([]), options);
+            }
+
+            export function ColorDocument(options: DocumentOptions = {}) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.COLOR), "", options);
+            }
+
+            export function RTFDocument(field: RichTextField, options: DocumentOptions = {}, fieldKey: string = "text") {
+                  return InstanceFromProto(Prototypes.get(DocumentType.RTF), field, options, undefined, fieldKey);
+            }
+            export function TextDocument(text: string, options: DocumentOptions = {}, fieldKey: string = "text") {
+                  const rtf = {
+                        doc: {
+                              type: "doc", content: [{
+                                    type: "paragraph",
+                                    content: [{
+                                          type: "text",
+                                          text
+                                    }]
+                              }]
+                        },
+                        selection: { type: "text", anchor: 1, head: 1 },
+                        storedMarks: []
+                  };
+                  const field = text ? new RichTextField(JSON.stringify(rtf), text) : undefined;
+                  return InstanceFromProto(Prototypes.get(DocumentType.RTF), field, options, undefined, fieldKey);
+            }
+
+            export function LinkDocument(source: { doc: Doc, ctx?: Doc }, target: { doc: Doc, ctx?: Doc }, options: DocumentOptions = {}, id?: string) {
+                  const linkDoc = InstanceFromProto(Prototypes.get(DocumentType.LINK), undefined, {
+                        anchor1: source.doc, anchor2: target.doc, ...options
+                  }, id);
+
+                  LinkManager.Instance.addLink(linkDoc);
+
+                  return linkDoc;
+            }
+
+            export function InkDocument(color: string, tool: string, strokeWidth: number, strokeBezier: string, fillColor: string, arrowStart: string, arrowEnd: string, dash: string, points: PointData[], options: DocumentOptions = {}) {
+                  const I = new Doc();
+                  I[Initializing] = true;
+                  I.type = DocumentType.INK;
+                  I.layout = InkingStroke.LayoutString("data");
+                  I.color = color;
+                  I.hideDecorationTitle = true;  // don't show title when selected
+                  // I.hideOpenButton = true; // don't show open full screen button when selected
+                  I.fillColor = fillColor;
+                  I.strokeWidth = strokeWidth;
+                  I.strokeBezier = strokeBezier;
+                  I.strokeStartMarker = arrowStart;
+                  I.strokeEndMarker = arrowEnd;
+                  I.strokeDash = dash;
+                  I.tool = tool;
+                  I["text-align"] = "center";
+                  I.title = "ink";
+                  I.x = options.x;
+                  I.y = options.y;
+                  I._width = options._width as number;
+                  I._height = options._height as number;
+                  I._fontFamily = "cursive";
+                  I.author = Doc.CurrentUserEmail;
+                  I.rotation = 0;
+                  I.data = new InkField(points);
+                  I.creationDate = new DateField;
+                  I["acl-Public"] = Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment;
+                  I["acl-Override"] = "None";
+                  I.links = ComputedField.MakeFunction("links(self)");
+                  I[Initializing] = false;
+                  return I;
+            }
+
+            export function PdfDocument(url: string, options: DocumentOptions = {}) {
+                  const width = options._width || undefined;
+                  const height = options._height || undefined;
+                  const nwid = options._nativeWidth || undefined;
+                  const nhght = options._nativeHeight || undefined;
+                  if (!nhght && width && height && nwid) options._nativeHeight = Number(nwid) * Number(height) / Number(width);
+                  return InstanceFromProto(Prototypes.get(DocumentType.PDF), new PdfField(url), options);
+            }
+
+            export function WebDocument(url: string, options: DocumentOptions = {}) {
+                  const width = options._width || undefined;
+                  const height = options._height || undefined;
+                  const nwid = options._nativeWidth || undefined;
+                  const nhght = options._nativeHeight || undefined;
+                  if (!nhght && width && height && nwid) options._nativeHeight = Number(nwid) * Number(height) / Number(width);
+                  return InstanceFromProto(Prototypes.get(DocumentType.WEB), url ? new WebField(url) : undefined, options);
+            }
+
+            export function HtmlDocument(html: string, options: DocumentOptions = {}) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.WEB), new HtmlField(html), options);
+            }
+
+            export function MapDocument(documents: Array<Doc>, options: DocumentOptions = {}) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.MAP), new List(documents), options);
+            }
+
+            export function MapMarkerDocument(lat: number, lng: number, infoWindowOpen: boolean, documents: Array<Doc>, options: DocumentOptions, id?: string) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.MARKER), new List(documents), { lat, lng, infoWindowOpen, ...options }, id);
+            }
+
+            export function KVPDocument(document: Doc, options: DocumentOptions = {}) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.KVP), document, { title: document.title + ".kvp", ...options });
+            }
+
+            export function FreeformDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
+                  const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _xPadding: 20, _yPadding: 20, ...options, _viewType: CollectionViewType.Freeform }, id);
+                  documents.map(d => d.context = inst);
+                  return inst;
+            }
+
+            export function WebanchorDocument(url?: string, options: DocumentOptions = {}, id?: string) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.MARKER), url, options, id);
+            }
+
+            export function TextanchorDocument(options: DocumentOptions = {}, id?: string) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.MARKER), options?.data, options, id);
+            }
+
+            export function HTMLAnchorDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.MARKER), new List(documents), options, id);
+            }
+
+            export function PileDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _overflow: "visible", _forceActive: true, _noAutoscroll: true, ...options, _viewType: CollectionViewType.Pile }, id);
+            }
+
+            export function LinearDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Linear }, id);
+            }
+
+            export function MapCollectionDocument(documents: Array<Doc>, options: DocumentOptions = {}) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Map });
+            }
+
+            export function CarouselDocument(documents: Array<Doc>, options: DocumentOptions) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Carousel });
+            }
+
+            export function Carousel3DDocument(documents: Array<Doc>, options: DocumentOptions) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Carousel3D });
+            }
+
+            export function SchemaDocument(schemaHeaders: SchemaHeaderField[], documents: Array<Doc>, options: DocumentOptions) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaHeaders: new List(schemaHeaders), ...options, _viewType: CollectionViewType.Schema });
+            }
+
+            export function TreeDocument(documents: Array<Doc>, options: DocumentOptions, id?: string, protoId?: string) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _xMargin: 5, _yMargin: 5, ...options, _viewType: CollectionViewType.Tree }, id, undefined, protoId);
+            }
+
+            export function StackingDocument(documents: Array<Doc>, options: DocumentOptions, id?: string, protoId?: string) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Stacking }, id, undefined, protoId);
+            }
+
+            export function MulticolumnDocument(documents: Array<Doc>, options: DocumentOptions) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Multicolumn });
+            }
+            export function MultirowDocument(documents: Array<Doc>, options: DocumentOptions) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Multirow });
+            }
+
+            export function MasonryDocument(documents: Array<Doc>, options: DocumentOptions) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Masonry });
+            }
+
+            export function LabelDocument(options?: DocumentOptions) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.LABEL), undefined, { ...(options || {}) });
+            }
+
+            export function EquationDocument(options?: DocumentOptions) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.EQUATION), undefined, { ...(options || {}) });
+            }
+
+            export function FunctionPlotDocument(documents: Array<Doc>, options?: DocumentOptions) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.FUNCPLOT), new List(documents), { ...(options || {}) });
+            }
+
+            export function ButtonDocument(options?: DocumentOptions) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.BUTTON), undefined, { ...(options || {}), "onClick-rawScript": "-script-" });
+            }
+
+            export function SliderDocument(options?: DocumentOptions) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.SLIDER), undefined, { ...(options || {}) });
+            }
+
+            export function FontIconDocument(options?: DocumentOptions) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.FONTICON), undefined, { ...(options || {}) });
+            }
+            export function FilterDocument(options?: DocumentOptions) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.FILTER), undefined, { ...(options || {}) });
+            }
+
+            export function PresElementBoxDocument(options?: DocumentOptions) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.PRESELEMENT), undefined, { ...(options || {}) });
+            }
+
+            export function DockDocument(documents: Array<Doc>, config: string, options: DocumentOptions, id?: string) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { freezeChildren: "remove|add", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id);
+            }
+
+            export function DirectoryImportDocument(options: DocumentOptions = {}) {
+                  return InstanceFromProto(Prototypes.get(DocumentType.IMPORT), new List<Doc>(), options);
+            }
+
+            export type DocConfig = {
+                  doc: Doc,
+                  initialWidth?: number,
+                  path?: Doc[]
             };
-            const field = text ? new RichTextField(JSON.stringify(rtf), text) : undefined;
-            return InstanceFromProto(Prototypes.get(DocumentType.RTF), field, options, undefined, fieldKey);
-        }
-
-        export function LinkDocument(source: { doc: Doc, ctx?: Doc }, target: { doc: Doc, ctx?: Doc }, options: DocumentOptions = {}, id?: string) {
-            const linkDoc = InstanceFromProto(Prototypes.get(DocumentType.LINK), undefined, {
-                anchor1: source.doc, anchor2: target.doc, ...options
-            }, id);
-
-            LinkManager.Instance.addLink(linkDoc);
-
-            return linkDoc;
-        }
-
-        export function InkDocument(color: string, tool: string, strokeWidth: number, strokeBezier: string, fillColor: string, arrowStart: string, arrowEnd: string, dash: string, points: PointData[], options: DocumentOptions = {}) {
-            const I = new Doc();
-            I[Initializing] = true;
-            I.type = DocumentType.INK;
-            I.layout = InkingStroke.LayoutString("data");
-            I.color = color;
-            I.hideDecorationTitle = true;  // don't show title when selected
-            // I.hideOpenButton = true; // don't show open full screen button when selected
-            I.fillColor = fillColor;
-            I.strokeWidth = strokeWidth;
-            I.strokeBezier = strokeBezier;
-            I.strokeStartMarker = arrowStart;
-            I.strokeEndMarker = arrowEnd;
-            I.strokeDash = dash;
-            I.tool = tool;
-            I["text-align"] = "center";
-            I.title = "ink";
-            I.x = options.x;
-            I.y = options.y;
-            I._width = options._width as number;
-            I._height = options._height as number;
-            I._fontFamily = "cursive";
-            I.author = Doc.CurrentUserEmail;
-            I.rotation = 0;
-            I.data = new InkField(points);
-            I.creationDate = new DateField;
-            I["acl-Public"] = Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment;
-            I["acl-Override"] = "None";
-            I.links = ComputedField.MakeFunction("links(self)");
-            I[Initializing] = false;
-            return I;
-        }
-
-        export function PdfDocument(url: string, options: DocumentOptions = {}) {
-            const width = options._width || undefined;
-            const height = options._height || undefined;
-            const nwid = options._nativeWidth || undefined;
-            const nhght = options._nativeHeight || undefined;
-            if (!nhght && width && height && nwid) options._nativeHeight = Number(nwid) * Number(height) / Number(width);
-            return InstanceFromProto(Prototypes.get(DocumentType.PDF), new PdfField(url), options);
-        }
-
-        export function WebDocument(url: string, options: DocumentOptions = {}) {
-            const width = options._width || undefined;
-            const height = options._height || undefined;
-            const nwid = options._nativeWidth || undefined;
-            const nhght = options._nativeHeight || undefined;
-            if (!nhght && width && height && nwid) options._nativeHeight = Number(nwid) * Number(height) / Number(width);
-            return InstanceFromProto(Prototypes.get(DocumentType.WEB), url ? new WebField(url) : undefined, options);
-        }
-
-        export function HtmlDocument(html: string, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.WEB), new HtmlField(html), options);
-        }
-
-        export function MapDocument(documents: Array<Doc>, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.MAP), new List(documents), options);
-        }
-
-        export function MapMarkerDocument(lat: number, lng: number, infoWindowOpen: boolean, documents: Array<Doc>, options: DocumentOptions, id?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.MARKER), new List(documents), { lat, lng, infoWindowOpen, ...options }, id);
-        }
-
-        export function KVPDocument(document: Doc, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.KVP), document, { title: document.title + ".kvp", ...options });
-        }
-
-        export function FreeformDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
-            const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _xPadding: 20, _yPadding: 20, ...options, _viewType: CollectionViewType.Freeform }, id);
-            documents.map(d => d.context = inst);
-            return inst;
-        }
-
-        export function WebanchorDocument(url?: string, options: DocumentOptions = {}, id?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.MARKER), url, options, id);
-        }
-
-        export function TextanchorDocument(options: DocumentOptions = {}, id?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.MARKER), options?.data, options, id);
-        }
-
-        export function HTMLAnchorDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.MARKER), new List(documents), options, id);
-        }
-
-        export function PileDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _overflow: "visible", _forceActive: true, _noAutoscroll: true, ...options, _viewType: CollectionViewType.Pile }, id);
-        }
-
-        export function LinearDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Linear }, id);
-        }
-
-        export function MapCollectionDocument(documents: Array<Doc>, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Map });
-        }
-
-        export function CarouselDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Carousel });
-        }
-
-        export function Carousel3DDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Carousel3D });
-        }
-
-        export function SchemaDocument(schemaHeaders: SchemaHeaderField[], documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaHeaders: new List(schemaHeaders), ...options, _viewType: CollectionViewType.Schema });
-        }
-
-        export function TreeDocument(documents: Array<Doc>, options: DocumentOptions, id?: string, protoId?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _xMargin: 5, _yMargin: 5, ...options, _viewType: CollectionViewType.Tree }, id, undefined, protoId);
-        }
-
-        export function StackingDocument(documents: Array<Doc>, options: DocumentOptions, id?: string, protoId?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Stacking }, id, undefined, protoId);
-        }
-
-        export function MulticolumnDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Multicolumn });
-        }
-        export function MultirowDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Multirow });
-        }
-
-        export function MasonryDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Masonry });
-        }
-
-        export function LabelDocument(options?: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.LABEL), undefined, { ...(options || {}) });
-        }
-
-        export function EquationDocument(options?: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.EQUATION), undefined, { ...(options || {}) });
-        }
-
-        export function FunctionPlotDocument(documents: Array<Doc>, options?: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.FUNCPLOT), new List(documents), { ...(options || {}) });
-        }
-
-        export function ButtonDocument(options?: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.BUTTON), undefined, { ...(options || {}), "onClick-rawScript": "-script-" });
-        }
-
-        export function SliderDocument(options?: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.SLIDER), undefined, { ...(options || {}) });
-        }
-
-        export function FontIconDocument(options?: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.FONTICON), undefined, { ...(options || {}) });
-        }
-        export function FilterDocument(options?: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.FILTER), undefined, { ...(options || {}) });
-        }
-
-        export function PresElementBoxDocument(options?: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.PRESELEMENT), undefined, { ...(options || {}) });
-        }
-
-        export function DockDocument(documents: Array<Doc>, config: string, options: DocumentOptions, id?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { freezeChildren: "remove|add", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id);
-        }
-
-        export function DirectoryImportDocument(options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.IMPORT), new List<Doc>(), options);
-        }
-
-        export type DocConfig = {
-            doc: Doc,
-            initialWidth?: number,
-            path?: Doc[]
-        };
-
-        export function StandardCollectionDockingDocument(configs: Array<DocConfig>, options: DocumentOptions, id?: string, type: string = "row") {
-            const layoutConfig = {
-                content: [
-                    {
-                        type: type,
+
+            export function StandardCollectionDockingDocument(configs: Array<DocConfig>, options: DocumentOptions, id?: string, type: string = "row") {
+                  const layoutConfig = {
                         content: [
-                            ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, undefined, config.initialWidth))
+                              {
+                                    type: type,
+                                    content: [
+                                          ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, undefined, config.initialWidth))
+                                    ]
+                              }
                         ]
-                    }
-                ]
-            };
-            return DockDocument(configs.map(c => c.doc), JSON.stringify(layoutConfig), options, id);
-        }
+                  };
+                  return DockDocument(configs.map(c => c.doc), JSON.stringify(layoutConfig), options, id);
+            }
 
-        export function DelegateDocument(proto: Doc, options: DocumentOptions = {}) {
-            return InstanceFromProto(proto, undefined, options);
-        }
-    }
+            export function DelegateDocument(proto: Doc, options: DocumentOptions = {}) {
+                  return InstanceFromProto(proto, undefined, options);
+            }
+      }
 }
 
 export namespace DocUtils {
-    export function Excluded(d: Doc, docFilters: string[]) {
-        const filterFacets: { [key: string]: { [value: string]: string } } = {};  // maps each filter key to an object with value=>modifier fields
-        docFilters.forEach(filter => {
-            const fields = filter.split(":");
-            const key = fields[0];
-            const value = fields[1];
-            const modifiers = fields[2];
-            if (!filterFacets[key]) {
-                filterFacets[key] = {};
-            }
-            filterFacets[key][value] = modifiers;
-        });
-
-        if (d.z) return false;
-        for (const facetKey of Object.keys(filterFacets)) {
-            const facet = filterFacets[facetKey];
-            const xs = Object.keys(facet).filter(value => facet[value] === "x");
-            const failsNotEqualFacets = xs?.some(value => Doc.matchFieldValue(d, facetKey, value));
-            if (failsNotEqualFacets) {
-                return true;
-            }
-        }
-        return false;
-    }
-    /**
-     * @param docs 
-     * @param docFilters 
-     * @param docRangeFilters 
-     * @param viewSpecScript 
-     * Given a list of docs and docFilters, @returns the list of Docs that match those filters 
-     */
-    export function FilterDocs(docs: Doc[], docFilters: string[], docRangeFilters: string[], viewSpecScript?: ScriptField, parentCollection?: Doc) {
-        const childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs;
-        if (!docFilters?.length && !docRangeFilters?.length) {
-            return childDocs.filter(d => !d.cookies);  // remove documents that need a cookie if there are no filters to provide one
-        }
-
-        const filterFacets: { [key: string]: { [value: string]: string } } = {};  // maps each filter key to an object with value=>modifier fields
-        docFilters.forEach(filter => {
-            const fields = filter.split(":");
-            const key = fields[0];
-            const value = fields[1];
-            const modifiers = fields[2];
-            if (!filterFacets[key]) {
-                filterFacets[key] = {};
-            }
-            filterFacets[key][value] = modifiers;
-        });
-
-        const filteredDocs = docFilters.length ? childDocs.filter(d => {
-            if (d.z) return true;
-            // if the document needs a cookie but no filter provides the cookie, then the document does not pass the filter
-            if (d.cookies && (!filterFacets.cookies || !Object.keys(filterFacets.cookies).some(key => d.cookies === key))) {
-                return false;
-            }
-
-            for (const facetKey of Object.keys(filterFacets).filter(fkey => fkey !== "cookies")) {
-                const facet = filterFacets[facetKey];
-
-                // facets that match some value in the field of the document (e.g. some text field)
-                const matches = Object.keys(facet).filter(value => value !== "cookies" && facet[value] === "match");
-
-                // facets that have a check next to them
-                const checks = Object.keys(facet).filter(value => facet[value] === "check");
-
-                // metadata facets that exist
-                const exists = Object.keys(facet).filter(value => facet[value] === "exists");
-
-                // metadata facets that exist
-                const unsets = Object.keys(facet).filter(value => facet[value] === "unset");
-
-                // facets that have an x next to them
-                const xs = Object.keys(facet).filter(value => facet[value] === "x");
-
-                if (!unsets.length && !exists.length && !xs.length && !checks.length && !matches.length) return true;
-                const failsNotEqualFacets = !xs.length ? false : xs.some(value => Doc.matchFieldValue(d, facetKey, value));
-                const satisfiesCheckFacets = !checks.length ? true : checks.some(value => Doc.matchFieldValue(d, facetKey, value));
-                const satisfiesExistsFacets = !exists.length ? true : exists.some(value => d[facetKey] !== undefined);
-                const satisfiesUnsetsFacets = !unsets.length ? true : unsets.some(value => d[facetKey] === undefined);
-                const satisfiesMatchFacets = !matches.length ? true : matches.some(value => {
-                    if (facetKey.startsWith("*")) { //  fields starting with a '*' are used to match families of related fields.  ie, *lastModified will match text-lastModified, data-lastModified, etc
-                        const allKeys = Array.from(Object.keys(d));
-                        allKeys.push(...Object.keys(Doc.GetProto(d)));
-                        const keys = allKeys.filter(key => key.includes(facetKey.substring(1)));
-                        return keys.some(key => Field.toString(d[key] as Field).includes(value));
-                    }
-                    return Field.toString(d[facetKey] as Field).includes(value);
-                });
-                // if we're ORing them together, the default return is false, and we return true for a doc if it satisfies any one set of criteria
-                if ((parentCollection?.currentFilter as Doc)?.filterBoolean === "OR") {
-                    if (satisfiesUnsetsFacets && satisfiesExistsFacets && satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true;
-                }
-                // if we're ANDing them together, the default return is true, and we return false for a doc if it doesn't satisfy any set of criteria
-                else {
-                    if (!satisfiesUnsetsFacets || !satisfiesExistsFacets || !satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false;
-                }
-
-            }
-            return (parentCollection?.currentFilter as Doc)?.filterBoolean === "OR" ? false : true;
-        }) : childDocs;
-        const rangeFilteredDocs = filteredDocs.filter(d => {
-            for (let i = 0; i < docRangeFilters.length; i += 3) {
-                const key = docRangeFilters[i];
-                const min = Number(docRangeFilters[i + 1]);
-                const max = Number(docRangeFilters[i + 2]);
-                const val = Cast(d[key], "number", null);
-                if (val < min || val > max) return false;
-                if (val === undefined) {
-                    //console.log("Should 'undefined' pass range filter or not?")
-                }
-            }
-            return true;
-        });
-        return rangeFilteredDocs;
-    }
-
-    export function Publish(promoteDoc: Doc, targetID: string, addDoc: any, remDoc: any) {
-        targetID = targetID.replace(/^-/, "").replace(/\([0-9]*\)$/, "");
-        DocServer.GetRefField(targetID).then(doc => {
-            if (promoteDoc !== doc) {
-                let copy = doc as Doc;
-                if (copy) {
-                    Doc.Overwrite(promoteDoc, copy, true);
-                } else {
-                    copy = Doc.MakeCopy(promoteDoc, true, targetID);
-                }
-                !doc && (copy.title = undefined) && (Doc.GetProto(copy).title = targetID);
-                addDoc && addDoc(copy);
-                remDoc && remDoc(promoteDoc);
-                if (!doc) {
-                    DocListCastAsync(promoteDoc.links).then(links => {
-                        links && links.map(async link => {
-                            if (link) {
-                                const a1 = await Cast(link.anchor1, Doc);
-                                if (a1 && Doc.AreProtosEqual(a1, promoteDoc)) link.anchor1 = copy;
-                                const a2 = await Cast(link.anchor2, Doc);
-                                if (a2 && Doc.AreProtosEqual(a2, promoteDoc)) link.anchor2 = copy;
-                                LinkManager.Instance.deleteLink(link);
-                                LinkManager.Instance.addLink(link);
-                            }
+      export function Excluded(d: Doc, docFilters: string[]) {
+            const filterFacets: { [key: string]: { [value: string]: string } } = {};  // maps each filter key to an object with value=>modifier fields
+            docFilters.forEach(filter => {
+                  const fields = filter.split(":");
+                  const key = fields[0];
+                  const value = fields[1];
+                  const modifiers = fields[2];
+                  if (!filterFacets[key]) {
+                        filterFacets[key] = {};
+                  }
+                  filterFacets[key][value] = modifiers;
+            });
+
+            if (d.z) return false;
+            for (const facetKey of Object.keys(filterFacets)) {
+                  const facet = filterFacets[facetKey];
+                  const xs = Object.keys(facet).filter(value => facet[value] === "x");
+                  const failsNotEqualFacets = xs?.some(value => Doc.matchFieldValue(d, facetKey, value));
+                  if (failsNotEqualFacets) {
+                        return true;
+                  }
+            }
+            return false;
+      }
+      /**
+       * @param docs 
+       * @param docFilters 
+       * @param docRangeFilters 
+       * @param viewSpecScript 
+       * Given a list of docs and docFilters, @returns the list of Docs that match those filters 
+       */
+      export function FilterDocs(docs: Doc[], docFilters: string[], docRangeFilters: string[], viewSpecScript?: ScriptField, parentCollection?: Doc) {
+            const childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs;
+            if (!docFilters?.length && !docRangeFilters?.length) {
+                  return childDocs.filter(d => !d.cookies);  // remove documents that need a cookie if there are no filters to provide one
+            }
+
+            const filterFacets: { [key: string]: { [value: string]: string } } = {};  // maps each filter key to an object with value=>modifier fields
+            docFilters.forEach(filter => {
+                  const fields = filter.split(":");
+                  const key = fields[0];
+                  const value = fields[1];
+                  const modifiers = fields[2];
+                  if (!filterFacets[key]) {
+                        filterFacets[key] = {};
+                  }
+                  filterFacets[key][value] = modifiers;
+            });
+
+            const filteredDocs = docFilters.length ? childDocs.filter(d => {
+                  if (d.z) return true;
+                  // if the document needs a cookie but no filter provides the cookie, then the document does not pass the filter
+                  if (d.cookies && (!filterFacets.cookies || !Object.keys(filterFacets.cookies).some(key => d.cookies === key))) {
+                        return false;
+                  }
+
+                  for (const facetKey of Object.keys(filterFacets).filter(fkey => fkey !== "cookies")) {
+                        const facet = filterFacets[facetKey];
+
+                        // facets that match some value in the field of the document (e.g. some text field)
+                        const matches = Object.keys(facet).filter(value => value !== "cookies" && facet[value] === "match");
+
+                        // facets that have a check next to them
+                        const checks = Object.keys(facet).filter(value => facet[value] === "check");
+
+                        // metadata facets that exist
+                        const exists = Object.keys(facet).filter(value => facet[value] === "exists");
+
+                        // metadata facets that exist
+                        const unsets = Object.keys(facet).filter(value => facet[value] === "unset");
+
+                        // facets that have an x next to them
+                        const xs = Object.keys(facet).filter(value => facet[value] === "x");
+
+                        if (!unsets.length && !exists.length && !xs.length && !checks.length && !matches.length) return true;
+                        const failsNotEqualFacets = !xs.length ? false : xs.some(value => Doc.matchFieldValue(d, facetKey, value));
+                        const satisfiesCheckFacets = !checks.length ? true : checks.some(value => Doc.matchFieldValue(d, facetKey, value));
+                        const satisfiesExistsFacets = !exists.length ? true : exists.some(value => d[facetKey] !== undefined);
+                        const satisfiesUnsetsFacets = !unsets.length ? true : unsets.some(value => d[facetKey] === undefined);
+                        const satisfiesMatchFacets = !matches.length ? true : matches.some(value => {
+                              if (facetKey.startsWith("*")) { //  fields starting with a '*' are used to match families of related fields.  ie, *lastModified will match text-lastModified, data-lastModified, etc
+                                    const allKeys = Array.from(Object.keys(d));
+                                    allKeys.push(...Object.keys(Doc.GetProto(d)));
+                                    const keys = allKeys.filter(key => key.includes(facetKey.substring(1)));
+                                    return keys.some(key => Field.toString(d[key] as Field).includes(value));
+                              }
+                              return Field.toString(d[facetKey] as Field).includes(value);
+                        });
+                        // if we're ORing them together, the default return is false, and we return true for a doc if it satisfies any one set of criteria
+                        if ((parentCollection?.currentFilter as Doc)?.filterBoolean === "OR") {
+                              if (satisfiesUnsetsFacets && satisfiesExistsFacets && satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true;
+                        }
+                        // if we're ANDing them together, the default return is true, and we return false for a doc if it doesn't satisfy any set of criteria
+                        else {
+                              if (!satisfiesUnsetsFacets || !satisfiesExistsFacets || !satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false;
+                        }
+
+                  }
+                  return (parentCollection?.currentFilter as Doc)?.filterBoolean === "OR" ? false : true;
+            }) : childDocs;
+            const rangeFilteredDocs = filteredDocs.filter(d => {
+                  for (let i = 0; i < docRangeFilters.length; i += 3) {
+                        const key = docRangeFilters[i];
+                        const min = Number(docRangeFilters[i + 1]);
+                        const max = Number(docRangeFilters[i + 2]);
+                        const val = Cast(d[key], "number", null);
+                        if (val < min || val > max) return false;
+                        if (val === undefined) {
+                              //console.log("Should 'undefined' pass range filter or not?")
+                        }
+                  }
+                  return true;
+            });
+            return rangeFilteredDocs;
+      }
+
+      export function Publish(promoteDoc: Doc, targetID: string, addDoc: any, remDoc: any) {
+            targetID = targetID.replace(/^-/, "").replace(/\([0-9]*\)$/, "");
+            DocServer.GetRefField(targetID).then(doc => {
+                  if (promoteDoc !== doc) {
+                        let copy = doc as Doc;
+                        if (copy) {
+                              Doc.Overwrite(promoteDoc, copy, true);
+                        } else {
+                              copy = Doc.MakeCopy(promoteDoc, true, targetID);
+                        }
+                        !doc && (copy.title = undefined) && (Doc.GetProto(copy).title = targetID);
+                        addDoc && addDoc(copy);
+                        remDoc && remDoc(promoteDoc);
+                        if (!doc) {
+                              DocListCastAsync(promoteDoc.links).then(links => {
+                                    links && links.map(async link => {
+                                          if (link) {
+                                                const a1 = await Cast(link.anchor1, Doc);
+                                                if (a1 && Doc.AreProtosEqual(a1, promoteDoc)) link.anchor1 = copy;
+                                                const a2 = await Cast(link.anchor2, Doc);
+                                                if (a2 && Doc.AreProtosEqual(a2, promoteDoc)) link.anchor2 = copy;
+                                                LinkManager.Instance.deleteLink(link);
+                                                LinkManager.Instance.addLink(link);
+                                          }
+                                    });
+                              });
+                        }
+                  }
+            });
+      }
+
+      export function DefaultFocus(doc: Doc, options?: DocFocusOptions) {
+            options?.afterFocus?.(false);
+      }
+
+      export let ActiveRecordings: { props: FieldViewProps, getAnchor: () => Doc }[] = [];
+
+      export function MakeLinkToActiveAudio(getSourceDoc: () => Doc, broadcastEvent = true) {
+            broadcastEvent && runInAction(() => DocumentManager.Instance.RecordingEvent = DocumentManager.Instance.RecordingEvent + 1);
+            return DocUtils.ActiveRecordings.map(audio =>
+                  DocUtils.MakeLink({ doc: getSourceDoc() }, { doc: audio.getAnchor() || audio.props.Document }, "recording annotation:linked recording", "recording timeline"));
+      }
+
+      export function MakeLink(source: { doc: Doc }, target: { doc: Doc }, linkRelationship: string = "", description: string = "", id?: string, allowParCollectionLink?: boolean, showPopup?: number[]) {
+            if (!linkRelationship) linkRelationship = target.doc.type === DocumentType.RTF ? "Commentary:Comments On" : "link";
+            const sv = DocumentManager.Instance.getDocumentView(source.doc);
+            if (!allowParCollectionLink && sv?.props.ContainingCollectionDoc === target.doc) return;
+            if (target.doc === Doc.UserDoc()) return undefined;
+
+            const makeLink = action((linkDoc: Doc, showPopup?: number[]) => {
+                  if (showPopup) {
+                        LinkManager.currentLink = linkDoc;
+
+                        TaskCompletionBox.textDisplayed = "Link Created";
+                        TaskCompletionBox.popupX = showPopup[0];
+                        TaskCompletionBox.popupY = showPopup[1] - 33;
+                        TaskCompletionBox.taskCompleted = true;
+
+                        LinkDescriptionPopup.popupX = showPopup[0];
+                        LinkDescriptionPopup.popupY = showPopup[1];
+                        LinkDescriptionPopup.descriptionPopup = true;
+
+                        const rect = document.body.getBoundingClientRect();
+                        if (LinkDescriptionPopup.popupX + 200 > rect.width) {
+                              LinkDescriptionPopup.popupX -= 190;
+                              TaskCompletionBox.popupX -= 40;
+                        }
+                        if (LinkDescriptionPopup.popupY + 100 > rect.height) {
+                              LinkDescriptionPopup.popupY -= 40;
+                              TaskCompletionBox.popupY -= 40;
+                        }
+
+                        setTimeout(action(() => TaskCompletionBox.taskCompleted = false), 2500);
+                  }
+                  return linkDoc;
+            });
+
+            return makeLink(Docs.Create.LinkDocument(source, target, {
+                  title: ComputedField.MakeFunction("generateLinkTitle(self)") as any,
+                  "anchor1-useLinkSmallAnchor": source.doc.useLinkSmallAnchor ? true : undefined,
+                  "anchor2-useLinkSmallAnchor": target.doc.useLinkSmallAnchor ? true : undefined,
+                  "acl-Public": SharingPermissions.Augment,
+                  "_acl-Public": SharingPermissions.Augment,
+                  linkDisplay: true,
+                  _hidden: true,
+                  _linkAutoMove: true,
+                  linkRelationship,
+                  _showCaption: "description",
+                  _showTitle: "linkRelationship",
+                  description
+            }, id), showPopup);
+      }
+
+      export function DocumentFromField(target: Doc, fieldKey: string, proto?: Doc, options?: DocumentOptions): Doc | undefined {
+            let created: Doc | undefined;
+            let layout: ((fieldKey: string) => string) | undefined;
+            const field = target[fieldKey];
+            const resolved = options || {};
+            if (field instanceof ImageField) {
+                  created = Docs.Create.ImageDocument((field).url.href, resolved);
+                  layout = ImageBox.LayoutString;
+            } else if (field instanceof Doc) {
+                  created = field;
+            } else if (field instanceof VideoField) {
+                  created = Docs.Create.VideoDocument((field).url.href, resolved);
+                  layout = VideoBox.LayoutString;
+            } else if (field instanceof PdfField) {
+                  created = Docs.Create.PdfDocument((field).url.href, resolved);
+                  layout = PDFBox.LayoutString;
+            } else if (field instanceof AudioField) {
+                  created = Docs.Create.AudioDocument((field).url.href, resolved);
+                  layout = AudioBox.LayoutString;
+            } else if (field instanceof RecordingField) {
+                  created = Docs.Create.RecordingDocument((field).url.href, resolved);
+                  layout = RecordingBox.LayoutString;
+            } else if (field instanceof InkField) {
+                  created = Docs.Create.InkDocument(ActiveInkColor(), CurrentUserUtils.SelectedTool, ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), (field).inkData, resolved);
+                  layout = InkingStroke.LayoutString;
+            } else if (field instanceof List && field[0] instanceof Doc) {
+                  created = Docs.Create.StackingDocument(DocListCast(field), resolved);
+                  layout = CollectionView.LayoutString;
+            } else if (field instanceof MapField) {
+                  created = Docs.Create.MapDocument(DocListCast(field), resolved);
+                  layout = MapBox.LayoutString;
+            }
+            else {
+                  created = Docs.Create.TextDocument("", { ...{ _width: 200, _height: 25, _autoHeight: true }, ...resolved });
+                  layout = FormattedTextBox.LayoutString;
+            }
+            if (created) {
+                  created.layout = layout?.(fieldKey);
+                  created.title = fieldKey;
+                  proto && created.proto && (created.proto = Doc.GetProto(proto));
+            }
+            return created;
+      }
+
+      export async function DocumentFromType(type: string, path: string, options: DocumentOptions): Promise<Opt<Doc>> {
+            let ctor: ((path: string, options: DocumentOptions) => (Doc | Promise<Doc | undefined>)) | undefined = undefined;
+            if (type.indexOf("image") !== -1) {
+                  ctor = Docs.Create.ImageDocument;
+                  if (!options._width) options._width = 300;
+            }
+            if (type.indexOf("video") !== -1) {
+                  ctor = Docs.Create.VideoDocument;
+                  if (!options._width) options._width = 600;
+                  if (!options._height) options._height = (options._width as number) * 2 / 3;
+            }
+            if (type.indexOf("audio") !== -1) {
+                  ctor = Docs.Create.AudioDocument;
+            }
+            if (type.indexOf("pdf") !== -1) {
+                  ctor = Docs.Create.PdfDocument;
+                  if (!options._width) options._width = 400;
+                  if (!options._height) options._height = (options._width as number) * 1200 / 927;
+            }
+            //TODO:al+glr
+            // if (type.indexOf("map") !== -1) {
+            //     ctor = Docs.Create.MapDocument;
+            //     if (!options._width) options._width = 800;
+            //     if (!options._height) options._height = (options._width as number) * 3 / 4;
+            // }
+            if (type.indexOf("html") !== -1) {
+                  if (path.includes(window.location.hostname)) {
+                        const s = path.split('/');
+                        const id = s[s.length - 1];
+                        return DocServer.GetRefField(id).then(field => {
+                              if (field instanceof Doc) {
+                                    const alias = Doc.MakeAlias(field);
+                                    alias.x = options.x || 0;
+                                    alias.y = options.y || 0;
+                                    alias._width = (options._width as number) || 300;
+                                    alias._height = (options._height as number) || (options._width as number) || 300;
+                                    return alias;
+                              }
+                              return undefined;
                         });
-                    });
-                }
-            }
-        });
-    }
-
-    export function DefaultFocus(doc: Doc, options?: DocFocusOptions) {
-        options?.afterFocus?.(false);
-    }
-
-    export let ActiveRecordings: { props: FieldViewProps, getAnchor: () => Doc }[] = [];
-
-    export function MakeLinkToActiveAudio(getSourceDoc: () => Doc, broadcastEvent = true) {
-        broadcastEvent && runInAction(() => DocumentManager.Instance.RecordingEvent = DocumentManager.Instance.RecordingEvent + 1);
-        return DocUtils.ActiveRecordings.map(audio =>
-            DocUtils.MakeLink({ doc: getSourceDoc() }, { doc: audio.getAnchor() || audio.props.Document }, "recording annotation:linked recording", "recording timeline"));
-    }
-
-    export function MakeLink(source: { doc: Doc }, target: { doc: Doc }, linkRelationship: string = "", description: string = "", id?: string, allowParCollectionLink?: boolean, showPopup?: number[]) {
-        if (!linkRelationship) linkRelationship = target.doc.type === DocumentType.RTF ? "Commentary:Comments On" : "link";
-        const sv = DocumentManager.Instance.getDocumentView(source.doc);
-        if (!allowParCollectionLink && sv?.props.ContainingCollectionDoc === target.doc) return;
-        if (target.doc === Doc.UserDoc()) return undefined;
-
-        const makeLink = action((linkDoc: Doc, showPopup?: number[]) => {
-            if (showPopup) {
-                LinkManager.currentLink = linkDoc;
-
-                TaskCompletionBox.textDisplayed = "Link Created";
-                TaskCompletionBox.popupX = showPopup[0];
-                TaskCompletionBox.popupY = showPopup[1] - 33;
-                TaskCompletionBox.taskCompleted = true;
-
-                LinkDescriptionPopup.popupX = showPopup[0];
-                LinkDescriptionPopup.popupY = showPopup[1];
-                LinkDescriptionPopup.descriptionPopup = true;
-
-                const rect = document.body.getBoundingClientRect();
-                if (LinkDescriptionPopup.popupX + 200 > rect.width) {
-                    LinkDescriptionPopup.popupX -= 190;
-                    TaskCompletionBox.popupX -= 40;
-                }
-                if (LinkDescriptionPopup.popupY + 100 > rect.height) {
-                    LinkDescriptionPopup.popupY -= 40;
-                    TaskCompletionBox.popupY -= 40;
-                }
-
-                setTimeout(action(() => TaskCompletionBox.taskCompleted = false), 2500);
-            }
-            return linkDoc;
-        });
-
-        return makeLink(Docs.Create.LinkDocument(source, target, {
-            title: ComputedField.MakeFunction("generateLinkTitle(self)") as any,
-            "anchor1-useLinkSmallAnchor": source.doc.useLinkSmallAnchor ? true : undefined,
-            "anchor2-useLinkSmallAnchor": target.doc.useLinkSmallAnchor ? true : undefined,
-            "acl-Public": SharingPermissions.Augment,
-            "_acl-Public": SharingPermissions.Augment,
-            linkDisplay: true,
-            _hidden: true,
-            _linkAutoMove: true,
-            linkRelationship,
-            _showCaption: "description",
-            _showTitle: "linkRelationship",
-            description
-        }, id), showPopup);
-    }
-
-    export function DocumentFromField(target: Doc, fieldKey: string, proto?: Doc, options?: DocumentOptions): Doc | undefined {
-        let created: Doc | undefined;
-        let layout: ((fieldKey: string) => string) | undefined;
-        const field = target[fieldKey];
-        const resolved = options || {};
-        if (field instanceof ImageField) {
-            created = Docs.Create.ImageDocument((field).url.href, resolved);
-            layout = ImageBox.LayoutString;
-        } else if (field instanceof Doc) {
-            created = field;
-        } else if (field instanceof VideoField) {
-            created = Docs.Create.VideoDocument((field).url.href, resolved);
-            layout = VideoBox.LayoutString;
-        } else if (field instanceof PdfField) {
-            created = Docs.Create.PdfDocument((field).url.href, resolved);
-            layout = PDFBox.LayoutString;
-        } else if (field instanceof AudioField) {
-            created = Docs.Create.AudioDocument((field).url.href, resolved);
-            layout = AudioBox.LayoutString;
-        } else if (field instanceof RecordingField) {
-            created = Docs.Create.RecordingDocument((field).url.href, resolved);
-            layout = RecordingBox.LayoutString;
-        } else if (field instanceof InkField) {
-            created = Docs.Create.InkDocument(ActiveInkColor(), CurrentUserUtils.SelectedTool, ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), (field).inkData, resolved);
-            layout = InkingStroke.LayoutString;
-        } else if (field instanceof List && field[0] instanceof Doc) {
-            created = Docs.Create.StackingDocument(DocListCast(field), resolved);
-            layout = CollectionView.LayoutString;
-        } else if (field instanceof MapField) {
-            created = Docs.Create.MapDocument(DocListCast(field), resolved);
-            layout = MapBox.LayoutString;
-        }
-        else {
-            created = Docs.Create.TextDocument("", { ...{ _width: 200, _height: 25, _autoHeight: true }, ...resolved });
-            layout = FormattedTextBox.LayoutString;
-        }
-        if (created) {
-            created.layout = layout?.(fieldKey);
-            created.title = fieldKey;
-            proto && created.proto && (created.proto = Doc.GetProto(proto));
-        }
-        return created;
-    }
-
-    export async function DocumentFromType(type: string, path: string, options: DocumentOptions): Promise<Opt<Doc>> {
-        let ctor: ((path: string, options: DocumentOptions) => (Doc | Promise<Doc | undefined>)) | undefined = undefined;
-        if (type.indexOf("image") !== -1) {
-            ctor = Docs.Create.ImageDocument;
-            if (!options._width) options._width = 300;
-        }
-        if (type.indexOf("video") !== -1) {
-            ctor = Docs.Create.VideoDocument;
-            if (!options._width) options._width = 600;
-            if (!options._height) options._height = (options._width as number) * 2 / 3;
-        }
-        if (type.indexOf("audio") !== -1) {
-            ctor = Docs.Create.AudioDocument;
-        }
-        if (type.indexOf("pdf") !== -1) {
-            ctor = Docs.Create.PdfDocument;
-            if (!options._width) options._width = 400;
-            if (!options._height) options._height = (options._width as number) * 1200 / 927;
-        }
-        //TODO:al+glr
-        // if (type.indexOf("map") !== -1) {
-        //     ctor = Docs.Create.MapDocument;
-        //     if (!options._width) options._width = 800;
-        //     if (!options._height) options._height = (options._width as number) * 3 / 4;
-        // }
-        if (type.indexOf("html") !== -1) {
-            if (path.includes(window.location.hostname)) {
-                const s = path.split('/');
-                const id = s[s.length - 1];
-                return DocServer.GetRefField(id).then(field => {
-                    if (field instanceof Doc) {
-                        const alias = Doc.MakeAlias(field);
-                        alias.x = options.x || 0;
-                        alias.y = options.y || 0;
-                        alias._width = (options._width as number) || 300;
-                        alias._height = (options._height as number) || (options._width as number) || 300;
-                        return alias;
-                    }
-                    return undefined;
-                });
-            }
-            ctor = Docs.Create.WebDocument;
-            options = { ...options, _width: 400, _height: 512, title: path, };
-        }
-        return ctor ? ctor(path, options) : undefined;
-    }
-
-    export function addDocumentCreatorMenuItems(docTextAdder: (d: Doc) => void, docAdder: (d: Doc) => void, x: number, y: number, simpleMenu: boolean = false): void {
-        !simpleMenu && ContextMenu.Instance.addItem({
-            description: "Quick Notes",
-            subitems: DocListCast((Doc.UserDoc()["template-notes"] as Doc).data).map((note, i) => ({
-                description: ":" + StrCast(note.title),
-                event: undoBatch((args: { x: number, y: number }) => {
-                    const textDoc = Docs.Create.TextDocument("", {
-                        _width: 200, x, y, _autoHeight: note._autoHeight !== false,
-                        title: StrCast(note.title) + "#" + (note.aliasCount = NumCast(note.aliasCount) + 1)
-                    });
-                    textDoc.layoutKey = "layout_" + note.title;
-                    textDoc[textDoc.layoutKey] = note;
-                    docTextAdder(textDoc);
-                }),
-                icon: StrCast(note.icon) as IconProp
-            })) as ContextMenuProps[],
-            icon: "sticky-note"
-        });
-        const math: ContextMenuProps = ({
-            description: ":Math", event: () => {
-                const created = Docs.Create.EquationDocument();
-                if (created) {
-                    created.author = Doc.CurrentUserEmail;
-                    created.x = x;
-                    created.y = y;
-                    created.width = 300;
-                    created.height = 35;
-                    EquationBox.SelectOnLoad = created[Id];
-                    docAdder?.(created);
-                }
-            }, icon: "calculator"
-        });
-        const documentList: ContextMenuProps[] = DocListCast(Cast(Doc.UserDoc().myItemCreators, Doc, null)?.data).filter(btnDoc => !btnDoc.hidden).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc && doc !== Doc.UserDoc().emptyPresentation).map((dragDoc, i) => ({
-            description: ":" + StrCast(dragDoc.title),
-            event: undoBatch((args: { x: number, y: number }) => {
-                const newDoc = Doc.copyDragFactory(dragDoc);
-                if (newDoc) {
-                    newDoc.author = Doc.CurrentUserEmail;
-                    newDoc.x = x;
-                    newDoc.y = y;
-                    if (newDoc.type === DocumentType.RTF) FormattedTextBox.SelectOnLoad = newDoc[Id];
-                    docAdder?.(newDoc);
-                }
-            }),
-            icon: Doc.toIcon(dragDoc),
-        })) as ContextMenuProps[];
-        documentList.push(math);
-        ContextMenu.Instance.addItem({
-            description: "Create document",
-            subitems: documentList,
-            icon: "file"
-        });
-    }// applies a custom template to a document.  the template is identified by it's short name (e.g, slideView not layout_slideView)
-    export function makeCustomViewClicked(doc: Doc, creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = "custom", docLayoutTemplate?: Doc) {
-        const batch = UndoManager.StartBatch("makeCustomViewClicked");
-        runInAction(() => {
-            doc.layoutKey = "layout_" + templateSignature;
-            if (doc[doc.layoutKey] === undefined) {
-                createCustomView(doc, creator, templateSignature, docLayoutTemplate);
-            }
-        });
-        batch.end();
-        return doc;
-    }
-    export function findTemplate(templateName: string, type: string, signature: string) {
-        let docLayoutTemplate: Opt<Doc>;
-        const iconViews = DocListCast(Cast(Doc.UserDoc()["template-icons"], Doc, null)?.data);
-        const templBtns = DocListCast(Cast(Doc.UserDoc()["template-buttons"], Doc, null)?.data);
-        const noteTypes = DocListCast(Cast(Doc.UserDoc()["template-notes"], Doc, null)?.data);
-        const clickFuncs = DocListCast(Cast(Doc.UserDoc().clickFuncs, Doc, null)?.data);
-        const allTemplates = iconViews.concat(templBtns).concat(noteTypes).concat(clickFuncs).map(btnDoc => (btnDoc.dragFactory as Doc) || btnDoc).filter(doc => doc.isTemplateDoc);
-        // bcz: this is hacky -- want to have different templates be applied depending on the "type" of a document.  but type is not reliable and there could be other types of template searches so this should be generalized
-        // first try to find a template that matches the specific document type (<typeName>_<templateName>).  otherwise, fallback to a general match on <templateName>
-        !docLayoutTemplate && allTemplates.forEach(tempDoc => StrCast(tempDoc.title) === templateName + "_" + type && (docLayoutTemplate = tempDoc));
-        !docLayoutTemplate && allTemplates.forEach(tempDoc => StrCast(tempDoc.title) === templateName && (docLayoutTemplate = tempDoc));
-        return docLayoutTemplate;
-    }
-    export function createCustomView(doc: Doc, creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = "custom", docLayoutTemplate?: Doc) {
-        const templateName = templateSignature.replace(/\(.*\)/, "");
-        docLayoutTemplate = docLayoutTemplate || findTemplate(templateName, StrCast(doc.type), templateSignature);
-
-        const customName = "layout_" + templateSignature;
-        const _width = NumCast(doc._width);
-        const _height = NumCast(doc._height);
-        const options = { title: "data", backgroundColor: StrCast(doc.backgroundColor), _autoHeight: true, _width, x: -_width / 2, y: - _height / 2, _showSidebar: false };
-
-        if (docLayoutTemplate) {
-            Doc.ApplyTemplateTo(docLayoutTemplate, doc, customName, undefined);
-        } else {
-            let fieldTemplate: Opt<Doc>;
-            if (doc.data instanceof RichTextField || typeof (doc.data) === "string") {
-                fieldTemplate = Docs.Create.TextDocument("", options);
-            } else if (doc.data instanceof PdfField) {
-                fieldTemplate = Docs.Create.PdfDocument("http://www.msn.com", options);
-            } else if (doc.data instanceof VideoField) {
-                fieldTemplate = Docs.Create.VideoDocument("http://www.cs.brown.edu", options);
-            } else if (doc.data instanceof AudioField) {
-                fieldTemplate = Docs.Create.AudioDocument("http://www.cs.brown.edu", options);
-            } else if (doc.data instanceof ImageField) {
-                fieldTemplate = Docs.Create.ImageDocument("http://www.cs.brown.edu", options);
-            }
-            const docTemplate = creator?.(fieldTemplate ? [fieldTemplate] : [], { title: customName + "(" + doc.title + ")", isTemplateDoc: true, _width: _width + 20, _height: Math.max(100, _height + 45) });
-            fieldTemplate && Doc.MakeMetadataFieldTemplate(fieldTemplate, docTemplate ? Doc.GetProto(docTemplate) : docTemplate);
-            docTemplate && Doc.ApplyTemplateTo(docTemplate, doc, customName, undefined);
-        }
-    }
-    export function makeCustomView(doc: Doc, custom: boolean, layout: string) {
-        Doc.setNativeView(doc);
-        if (custom) {
-            makeCustomViewClicked(doc, Docs.Create.StackingDocument, layout, undefined);
-        }
-    }
-    export function iconify(doc: Doc) {
-        const layoutKey = Cast(doc.layoutKey, "string", null);
-        DocUtils.makeCustomViewClicked(doc, Docs.Create.StackingDocument, "icon", undefined);
-        if (layoutKey && layoutKey !== "layout" && layoutKey !== "layout_icon") doc.deiconifyLayout = layoutKey.replace("layout_", "");
-    }
-
-    export function pileup(docList: Doc[], x?: number, y?: number, size: number = 55, create: boolean = true) {
-        let w = 0, h = 0;
-        runInAction(() => {
-            docList.forEach(d => {
-                DocUtils.iconify(d);
-                w = Math.max(NumCast(d._width), w);
-                h = Math.max(NumCast(d._height), h);
+                  }
+                  ctor = Docs.Create.WebDocument;
+                  options = { ...options, _width: 400, _height: 512, title: path, };
+            }
+            return ctor ? ctor(path, options) : undefined;
+      }
+
+      export function addDocumentCreatorMenuItems(docTextAdder: (d: Doc) => void, docAdder: (d: Doc) => void, x: number, y: number, simpleMenu: boolean = false): void {
+            !simpleMenu && ContextMenu.Instance.addItem({
+                  description: "Quick Notes",
+                  subitems: DocListCast((Doc.UserDoc()["template-notes"] as Doc).data).map((note, i) => ({
+                        description: ":" + StrCast(note.title),
+                        event: undoBatch((args: { x: number, y: number }) => {
+                              const textDoc = Docs.Create.TextDocument("", {
+                                    _width: 200, x, y, _autoHeight: note._autoHeight !== false,
+                                    title: StrCast(note.title) + "#" + (note.aliasCount = NumCast(note.aliasCount) + 1)
+                              });
+                              textDoc.layoutKey = "layout_" + note.title;
+                              textDoc[textDoc.layoutKey] = note;
+                              docTextAdder(textDoc);
+                        }),
+                        icon: StrCast(note.icon) as IconProp
+                  })) as ContextMenuProps[],
+                  icon: "sticky-note"
             });
-            docList.forEach((d, i) => {
-                d.x = Math.cos(Math.PI * 2 * i / docList.length) * size;
-                d.y = Math.sin(Math.PI * 2 * i / docList.length) * size;
-                d._timecodeToShow = undefined;  // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
+            const math: ContextMenuProps = ({
+                  description: ":Math", event: () => {
+                        const created = Docs.Create.EquationDocument();
+                        if (created) {
+                              created.author = Doc.CurrentUserEmail;
+                              created.x = x;
+                              created.y = y;
+                              created.width = 300;
+                              created.height = 35;
+                              EquationBox.SelectOnLoad = created[Id];
+                              docAdder?.(created);
+                        }
+                  }, icon: "calculator"
             });
-            const aggBounds = aggregateBounds(docList.map(d => ({ x: NumCast(d.x), y: NumCast(d.y), width: NumCast(d._width), height: NumCast(d._height) })), 0, 0);
-            docList.forEach((d, i) => {
-                d.x = NumCast(d.x) - ((aggBounds.r + aggBounds.x) / 2);
-                d.y = NumCast(d.y) - ((aggBounds.b + aggBounds.y) / 2);
-                d._timecodeToShow = undefined;  // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
+            const documentList: ContextMenuProps[] = DocListCast(Cast(Doc.UserDoc().myItemCreators, Doc, null)?.data).filter(btnDoc => !btnDoc.hidden).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc && doc !== Doc.UserDoc().emptyPresentation).map((dragDoc, i) => ({
+                  description: ":" + StrCast(dragDoc.title),
+                  event: undoBatch((args: { x: number, y: number }) => {
+                        const newDoc = Doc.copyDragFactory(dragDoc);
+                        if (newDoc) {
+                              newDoc.author = Doc.CurrentUserEmail;
+                              newDoc.x = x;
+                              newDoc.y = y;
+                              if (newDoc.type === DocumentType.RTF) FormattedTextBox.SelectOnLoad = newDoc[Id];
+                              docAdder?.(newDoc);
+                        }
+                  }),
+                  icon: Doc.toIcon(dragDoc),
+            })) as ContextMenuProps[];
+            documentList.push(math);
+            ContextMenu.Instance.addItem({
+                  description: "Create document",
+                  subitems: documentList,
+                  icon: "file"
             });
-        });
-        if (create) {
-            const newCollection = Docs.Create.PileDocument(docList, { title: "pileup", x: (x || 0) - size, y: (y || 0) - size, _width: size * 2, _height: size * 2, });
-            newCollection.x = NumCast(newCollection.x) + NumCast(newCollection._width) / 2 - size;
-            newCollection.y = NumCast(newCollection.y) + NumCast(newCollection._height) / 2 - size;
-            newCollection._width = newCollection._height = size * 2;
-            newCollection._jitterRotation = 10;
-            return newCollection;
-        }
-    }
-
-    export function LeavePushpin(doc: Doc, annotationField: string) {
-        if (doc.isPushpin) return undefined;
-        const context = Cast(doc.context, Doc, null) ?? Cast(doc.annotationOn, Doc, null);
-        const hasContextAnchor = DocListCast(doc.links).
-            some(l =>
-                (l.anchor2 === doc && Cast(l.anchor1, Doc, null)?.annotationOn === context) ||
-                (l.anchor1 === doc && Cast(l.anchor2, Doc, null)?.annotationOn === context));
-        if (context && !hasContextAnchor && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) {
-            const pushpin = Docs.Create.FontIconDocument({
-                title: "pushpin", label: "", annotationOn: Cast(doc.annotationOn, Doc, null), isPushpin: true,
-                icon: "map-pin", x: Cast(doc.x, "number", null), y: Cast(doc.y, "number", null), backgroundColor: "#ACCEF7",
-                _width: 15, _height: 15, _xPadding: 0, _isLinkButton: true, _timecodeToShow: Cast(doc._timecodeToShow, "number", null)
+      }// applies a custom template to a document.  the template is identified by it's short name (e.g, slideView not layout_slideView)
+      export function makeCustomViewClicked(doc: Doc, creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = "custom", docLayoutTemplate?: Doc) {
+            const batch = UndoManager.StartBatch("makeCustomViewClicked");
+            runInAction(() => {
+                  doc.layoutKey = "layout_" + templateSignature;
+                  if (doc[doc.layoutKey] === undefined) {
+                        createCustomView(doc, creator, templateSignature, docLayoutTemplate);
+                  }
             });
-            Doc.AddDocToList(context, annotationField, pushpin);
-            const pushpinLink = DocUtils.MakeLink({ doc: pushpin }, { doc: doc }, "pushpin", "");
-            doc._timecodeToShow = undefined;
-            return pushpin;
-        }
-        return undefined;
-    }
-
-    // /**
-    //  * 
-    //  * @param dms Degree Minute Second format exif gps data
-    //  * @param ref ref that determines negativity of decimal coordinates
-    //  * @returns a decimal format of gps latitude / longitude
-    //  */
-    // function getDecimalfromDMS(dms?: number[], ref?: string) {
-    //     if (dms && ref) {
-    //         let degrees = dms[0] / dms[1];
-    //         let minutes = dms[2] / dms[3] / 60.0;
-    //         let seconds = dms[4] / dms[5] / 3600.0;
-
-    //         if (['S', 'W'].includes(ref)) {
-    //             degrees = -degrees; minutes = -minutes; seconds = -seconds
-    //         }
-    //         return (degrees + minutes + seconds).toFixed(5);
-    //     }
-    // }
-
-    function ConvertDMSToDD(degrees: number, minutes: number, seconds: number, direction: string) {
-        var dd = degrees + minutes / 60 + seconds / (60 * 60);
-        if (direction === "S" || direction === "W") {
-            dd = dd * -1;
-        } // Don't do anything for N or E
-        return dd;
-    }
-
-    async function processFileupload(generatedDocuments: Doc[], name: string, type: string, result: Error | Upload.FileInformation, options: DocumentOptions) {
-        if (result instanceof Error) {
-            alert(`Upload failed: ${result.message}`);
-            return;
-        }
-        const full = { ...options, _width: 400, title: name };
-        const pathname = Utils.prepend(result.accessPaths.agnostic.client);
-        const doc = await DocUtils.DocumentFromType(type, pathname, full);
-        if (doc) {
-            const proto = Doc.GetProto(doc);
-            proto.text = result.rawText;
-            proto.fileUpload = pathname.replace(/.*\//, "").replace("upload_", "").replace(/\.[a-z0-9]*$/, "");
-            if (Upload.isImageInformation(result)) {
-                const maxNativeDim = Math.min(Math.max(result.nativeHeight, result.nativeWidth), defaultNativeImageDim);
-                proto["data-nativeOrientation"] = result.exifData?.data?.image?.Orientation ?? ((StrCast((result.exifData?.data as any)?.Orientation).includes("Rotate 90")) ? 5 : undefined);
-                proto["data-nativeWidth"] = (result.nativeWidth < result.nativeHeight) ? maxNativeDim * result.nativeWidth / result.nativeHeight : maxNativeDim;
-                proto["data-nativeHeight"] = (result.nativeWidth < result.nativeHeight) ? maxNativeDim : maxNativeDim / (result.nativeWidth / result.nativeHeight);
-                if (NumCast(proto["data-nativeOrientation"]) >= 5) {
-                    proto["data-nativeHeight"] = (result.nativeWidth < result.nativeHeight) ? maxNativeDim * result.nativeWidth / result.nativeHeight : maxNativeDim;
-                    proto["data-nativeWidth"] = (result.nativeWidth < result.nativeHeight) ? maxNativeDim : maxNativeDim / (result.nativeWidth / result.nativeHeight);
-                }
-                proto.contentSize = result.contentSize;
-                // exif gps data coordinates are stored in DMS (Degrees Minutes Seconds), the following operation converts that to decimal coordinates
-                const latitude = result.exifData?.data?.GPSLatitude;
-                const latitudeDirection = result.exifData?.data?.GPSLatitudeRef;
-                const longitude = result.exifData?.data?.GPSLongitude;
-                const longitudeDirection = result.exifData?.data?.GPSLongitudeRef;
-                if (latitude !== undefined && longitude !== undefined && latitudeDirection !== undefined && longitudeDirection !== undefined) {
-                    proto.lat = ConvertDMSToDD(latitude[0], latitude[1], latitude[2], latitudeDirection);
-                    proto.lng = ConvertDMSToDD(longitude[0], longitude[1], longitude[2], longitudeDirection);
-                }
-
-            }
-            generatedDocuments.push(doc);
-        }
-    }
-
-    export async function uploadYoutubeVideo(videoId: string, options: DocumentOptions) {
-        const generatedDocuments: Doc[] = [];
-        for (const { source: { name, type }, result } of await Networking.UploadYoutubeToServer(videoId)) {
-            name && type && processFileupload(generatedDocuments, name, type, result, options);
-        }
-        return generatedDocuments;
-    }
-    export async function uploadFilesToDocs(files: File[], options: DocumentOptions) {
-        const generatedDocuments: Doc[] = [];
-        const upfiles = await Networking.UploadFilesToServer(files);
-        for (const { source: { name, type }, result } of upfiles) {
-            name && type && processFileupload(generatedDocuments, name, type, result, options);
-        }
-        return generatedDocuments;
-    }
+            batch.end();
+            return doc;
+      }
+      export function findTemplate(templateName: string, type: string, signature: string) {
+            let docLayoutTemplate: Opt<Doc>;
+            const iconViews = DocListCast(Cast(Doc.UserDoc()["template-icons"], Doc, null)?.data);
+            const templBtns = DocListCast(Cast(Doc.UserDoc()["template-buttons"], Doc, null)?.data);
+            const noteTypes = DocListCast(Cast(Doc.UserDoc()["template-notes"], Doc, null)?.data);
+            const clickFuncs = DocListCast(Cast(Doc.UserDoc().clickFuncs, Doc, null)?.data);
+            const allTemplates = iconViews.concat(templBtns).concat(noteTypes).concat(clickFuncs).map(btnDoc => (btnDoc.dragFactory as Doc) || btnDoc).filter(doc => doc.isTemplateDoc);
+            // bcz: this is hacky -- want to have different templates be applied depending on the "type" of a document.  but type is not reliable and there could be other types of template searches so this should be generalized
+            // first try to find a template that matches the specific document type (<typeName>_<templateName>).  otherwise, fallback to a general match on <templateName>
+            !docLayoutTemplate && allTemplates.forEach(tempDoc => StrCast(tempDoc.title) === templateName + "_" + type && (docLayoutTemplate = tempDoc));
+            !docLayoutTemplate && allTemplates.forEach(tempDoc => StrCast(tempDoc.title) === templateName && (docLayoutTemplate = tempDoc));
+            return docLayoutTemplate;
+      }
+      export function createCustomView(doc: Doc, creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = "custom", docLayoutTemplate?: Doc) {
+            const templateName = templateSignature.replace(/\(.*\)/, "");
+            docLayoutTemplate = docLayoutTemplate || findTemplate(templateName, StrCast(doc.type), templateSignature);
+
+            const customName = "layout_" + templateSignature;
+            const _width = NumCast(doc._width);
+            const _height = NumCast(doc._height);
+            const options = { title: "data", backgroundColor: StrCast(doc.backgroundColor), _autoHeight: true, _width, x: -_width / 2, y: - _height / 2, _showSidebar: false };
+
+            if (docLayoutTemplate) {
+                  Doc.ApplyTemplateTo(docLayoutTemplate, doc, customName, undefined);
+            } else {
+                  let fieldTemplate: Opt<Doc>;
+                  if (doc.data instanceof RichTextField || typeof (doc.data) === "string") {
+                        fieldTemplate = Docs.Create.TextDocument("", options);
+                  } else if (doc.data instanceof PdfField) {
+                        fieldTemplate = Docs.Create.PdfDocument("http://www.msn.com", options);
+                  } else if (doc.data instanceof VideoField) {
+                        fieldTemplate = Docs.Create.VideoDocument("http://www.cs.brown.edu", options);
+                  } else if (doc.data instanceof AudioField) {
+                        fieldTemplate = Docs.Create.AudioDocument("http://www.cs.brown.edu", options);
+                  } else if (doc.data instanceof ImageField) {
+                        fieldTemplate = Docs.Create.ImageDocument("http://www.cs.brown.edu", options);
+                  }
+                  const docTemplate = creator?.(fieldTemplate ? [fieldTemplate] : [], { title: customName + "(" + doc.title + ")", isTemplateDoc: true, _width: _width + 20, _height: Math.max(100, _height + 45) });
+                  fieldTemplate && Doc.MakeMetadataFieldTemplate(fieldTemplate, docTemplate ? Doc.GetProto(docTemplate) : docTemplate);
+                  docTemplate && Doc.ApplyTemplateTo(docTemplate, doc, customName, undefined);
+            }
+      }
+      export function makeCustomView(doc: Doc, custom: boolean, layout: string) {
+            Doc.setNativeView(doc);
+            if (custom) {
+                  makeCustomViewClicked(doc, Docs.Create.StackingDocument, layout, undefined);
+            }
+      }
+      export function iconify(doc: Doc) {
+            const layoutKey = Cast(doc.layoutKey, "string", null);
+            DocUtils.makeCustomViewClicked(doc, Docs.Create.StackingDocument, "icon", undefined);
+            if (layoutKey && layoutKey !== "layout" && layoutKey !== "layout_icon") doc.deiconifyLayout = layoutKey.replace("layout_", "");
+      }
+
+      export function pileup(docList: Doc[], x?: number, y?: number, size: number = 55, create: boolean = true) {
+            let w = 0, h = 0;
+            runInAction(() => {
+                  docList.forEach(d => {
+                        DocUtils.iconify(d);
+                        w = Math.max(NumCast(d._width), w);
+                        h = Math.max(NumCast(d._height), h);
+                  });
+                  docList.forEach((d, i) => {
+                        d.x = Math.cos(Math.PI * 2 * i / docList.length) * size;
+                        d.y = Math.sin(Math.PI * 2 * i / docList.length) * size;
+                        d._timecodeToShow = undefined;  // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
+                  });
+                  const aggBounds = aggregateBounds(docList.map(d => ({ x: NumCast(d.x), y: NumCast(d.y), width: NumCast(d._width), height: NumCast(d._height) })), 0, 0);
+                  docList.forEach((d, i) => {
+                        d.x = NumCast(d.x) - ((aggBounds.r + aggBounds.x) / 2);
+                        d.y = NumCast(d.y) - ((aggBounds.b + aggBounds.y) / 2);
+                        d._timecodeToShow = undefined;  // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
+                  });
+            });
+            if (create) {
+                  const newCollection = Docs.Create.PileDocument(docList, { title: "pileup", x: (x || 0) - size, y: (y || 0) - size, _width: size * 2, _height: size * 2, });
+                  newCollection.x = NumCast(newCollection.x) + NumCast(newCollection._width) / 2 - size;
+                  newCollection.y = NumCast(newCollection.y) + NumCast(newCollection._height) / 2 - size;
+                  newCollection._width = newCollection._height = size * 2;
+                  newCollection._jitterRotation = 10;
+                  return newCollection;
+            }
+      }
+
+      export function LeavePushpin(doc: Doc, annotationField: string) {
+            if (doc.isPushpin) return undefined;
+            const context = Cast(doc.context, Doc, null) ?? Cast(doc.annotationOn, Doc, null);
+            const hasContextAnchor = DocListCast(doc.links).
+                  some(l =>
+                        (l.anchor2 === doc && Cast(l.anchor1, Doc, null)?.annotationOn === context) ||
+                        (l.anchor1 === doc && Cast(l.anchor2, Doc, null)?.annotationOn === context));
+            if (context && !hasContextAnchor && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) {
+                  const pushpin = Docs.Create.FontIconDocument({
+                        title: "pushpin", label: "", annotationOn: Cast(doc.annotationOn, Doc, null), isPushpin: true,
+                        icon: "map-pin", x: Cast(doc.x, "number", null), y: Cast(doc.y, "number", null), backgroundColor: "#ACCEF7",
+                        _width: 15, _height: 15, _xPadding: 0, _isLinkButton: true, _timecodeToShow: Cast(doc._timecodeToShow, "number", null)
+                  });
+                  Doc.AddDocToList(context, annotationField, pushpin);
+                  const pushpinLink = DocUtils.MakeLink({ doc: pushpin }, { doc: doc }, "pushpin", "");
+                  doc._timecodeToShow = undefined;
+                  return pushpin;
+            }
+            return undefined;
+      }
+
+      // /**
+      //  * 
+      //  * @param dms Degree Minute Second format exif gps data
+      //  * @param ref ref that determines negativity of decimal coordinates
+      //  * @returns a decimal format of gps latitude / longitude
+      //  */
+      // function getDecimalfromDMS(dms?: number[], ref?: string) {
+      //     if (dms && ref) {
+      //         let degrees = dms[0] / dms[1];
+      //         let minutes = dms[2] / dms[3] / 60.0;
+      //         let seconds = dms[4] / dms[5] / 3600.0;
+
+      //         if (['S', 'W'].includes(ref)) {
+      //             degrees = -degrees; minutes = -minutes; seconds = -seconds
+      //         }
+      //         return (degrees + minutes + seconds).toFixed(5);
+      //     }
+      // }
+
+      function ConvertDMSToDD(degrees: number, minutes: number, seconds: number, direction: string) {
+            var dd = degrees + minutes / 60 + seconds / (60 * 60);
+            if (direction === "S" || direction === "W") {
+                  dd = dd * -1;
+            } // Don't do anything for N or E
+            return dd;
+      }
+
+      async function processFileupload(generatedDocuments: Doc[], name: string, type: string, result: Error | Upload.FileInformation, options: DocumentOptions) {
+            if (result instanceof Error) {
+                  alert(`Upload failed: ${result.message}`);
+                  return;
+            }
+            const full = { ...options, _width: 400, title: name };
+            const pathname = Utils.prepend(result.accessPaths.agnostic.client);
+            const doc = await DocUtils.DocumentFromType(type, pathname, full);
+            if (doc) {
+                  const proto = Doc.GetProto(doc);
+                  proto.text = result.rawText;
+                  proto.fileUpload = pathname.replace(/.*\//, "").replace("upload_", "").replace(/\.[a-z0-9]*$/, "");
+                  if (Upload.isImageInformation(result)) {
+                        const maxNativeDim = Math.min(Math.max(result.nativeHeight, result.nativeWidth), defaultNativeImageDim);
+                        proto["data-nativeOrientation"] = result.exifData?.data?.image?.Orientation ?? ((StrCast((result.exifData?.data as any)?.Orientation).includes("Rotate 90")) ? 5 : undefined);
+                        proto["data-nativeWidth"] = (result.nativeWidth < result.nativeHeight) ? maxNativeDim * result.nativeWidth / result.nativeHeight : maxNativeDim;
+                        proto["data-nativeHeight"] = (result.nativeWidth < result.nativeHeight) ? maxNativeDim : maxNativeDim / (result.nativeWidth / result.nativeHeight);
+                        if (NumCast(proto["data-nativeOrientation"]) >= 5) {
+                              proto["data-nativeHeight"] = (result.nativeWidth < result.nativeHeight) ? maxNativeDim * result.nativeWidth / result.nativeHeight : maxNativeDim;
+                              proto["data-nativeWidth"] = (result.nativeWidth < result.nativeHeight) ? maxNativeDim : maxNativeDim / (result.nativeWidth / result.nativeHeight);
+                        }
+                        proto.contentSize = result.contentSize;
+                        // exif gps data coordinates are stored in DMS (Degrees Minutes Seconds), the following operation converts that to decimal coordinates
+                        const latitude = result.exifData?.data?.GPSLatitude;
+                        const latitudeDirection = result.exifData?.data?.GPSLatitudeRef;
+                        const longitude = result.exifData?.data?.GPSLongitude;
+                        const longitudeDirection = result.exifData?.data?.GPSLongitudeRef;
+                        if (latitude !== undefined && longitude !== undefined && latitudeDirection !== undefined && longitudeDirection !== undefined) {
+                              proto.lat = ConvertDMSToDD(latitude[0], latitude[1], latitude[2], latitudeDirection);
+                              proto.lng = ConvertDMSToDD(longitude[0], longitude[1], longitude[2], longitudeDirection);
+                        }
+
+                  }
+                  generatedDocuments.push(doc);
+            }
+      }
+
+      export async function uploadYoutubeVideo(videoId: string, options: DocumentOptions) {
+            const generatedDocuments: Doc[] = [];
+            for (const { source: { name, type }, result } of await Networking.UploadYoutubeToServer(videoId)) {
+                  name && type && processFileupload(generatedDocuments, name, type, result, options);
+            }
+            return generatedDocuments;
+      }
+      export async function uploadFilesToDocs(files: File[], options: DocumentOptions) {
+            const generatedDocuments: Doc[] = [];
+            const upfiles = await Networking.UploadFilesToServer(files);
+            for (const { source: { name, type }, result } of upfiles) {
+                  name && type && processFileupload(generatedDocuments, name, type, result, options);
+            }
+            return generatedDocuments;
+      }
 }
 
 ScriptingGlobals.add("Docs", Docs);
 ScriptingGlobals.add(function makeDelegate(proto: any) { const d = Docs.Create.DelegateDocument(proto, { title: "child of " + proto.title }); return d; });
 ScriptingGlobals.add(function generateLinkTitle(self: Doc) {
-    const anchor1title = self.anchor1 && self.anchor1 !== self ? Cast(self.anchor1, Doc, null).title : "<?>";
-    const anchor2title = self.anchor2 && self.anchor2 !== self ? Cast(self.anchor2, Doc, null).title : "<?>";
-    const relation = self.linkRelationship || "to";
-    return `${anchor1title} (${relation}) ${anchor2title}`;
+      const anchor1title = self.anchor1 && self.anchor1 !== self ? Cast(self.anchor1, Doc, null).title : "<?>";
+      const anchor2title = self.anchor2 && self.anchor2 !== self ? Cast(self.anchor2, Doc, null).title : "<?>";
+      const relation = self.linkRelationship || "to";
+      return `${anchor1title} (${relation}) ${anchor2title}`;
 });
 ScriptingGlobals.add(function openTabAlias(tab: Doc) {
-    CollectionDockingView.AddSplit(Doc.MakeAlias(tab), "right");
+      CollectionDockingView.AddSplit(Doc.MakeAlias(tab), "right");
 });
\ No newline at end of file
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 29e088143..bc4fec3f0 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -33,548 +33,552 @@ import React = require("react");
 
 @observer
 export class DocumentDecorations extends React.Component<{ PanelWidth: number, PanelHeight: number, boundsLeft: number, boundsTop: number }, { value: string }> {
-    static Instance: DocumentDecorations;
-    private _resizeHdlId = "";
-    private _keyinput = React.createRef<HTMLInputElement>();
-    private _resizeBorderWidth = 16;
-    private _linkBoxHeight = 20 + 3; // link button height + margin
-    private _titleHeight = 20;
-    private _resizeUndo?: UndoManager.Batch;
-    private _offX = 0; _offY = 0;  // offset from click pt to inner edge of resize border
-    private _snapX = 0; _snapY = 0; // last snapped location of resize border
-    private _dragHeights = new Map<Doc, { start: number, lowest: number }>();
-    private _inkDragDocs: { doc: Doc, x: number, y: number, width: number, height: number }[] = [];
-
-    @observable private _accumulatedTitle = "";
-    @observable private _titleControlString: string = "#title";
-    @observable private _edtingTitle = false;
-    @observable private _hidden = false;
-    @observable public AddToSelection = false; // if Shift is pressed, then this should be set so that clicking on the selection background is ignored so overlapped documents can be added to the selection set.
-    @observable public Interacting = false;
-    @observable public pushIcon: IconProp = "arrow-alt-circle-up";
-    @observable public pullIcon: IconProp = "arrow-alt-circle-down";
-    @observable public pullColor: string = "white";
-
-    constructor(props: any) {
-        super(props);
-        DocumentDecorations.Instance = this;
-        reaction(() => SelectionManager.Views().slice(), action(docs => this._edtingTitle = false));
-    }
-
-    @computed
-    get Bounds() {
-        const views = SelectionManager.Views();
-        return views.filter(dv => dv.props.renderDepth > 0).map(dv => dv.getBounds()).reduce((bounds, rect) =>
-            !rect ? bounds :
-                {
-                    x: Math.min(rect.left, bounds.x),
-                    y: Math.min(rect.top, bounds.y),
-                    r: Math.max(rect.right, bounds.r),
-                    b: Math.max(rect.bottom, bounds.b),
-                    c: views.length === 1 ? rect.center : undefined
-                },
-            { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE, c: undefined as ({ X: number, Y: number } | undefined) });
-    }
-
-    @action
-    titleBlur = () => {
-        this._edtingTitle = false;
-        if (this._accumulatedTitle.startsWith("#") || this._accumulatedTitle.startsWith("=")) {
-            this._titleControlString = this._accumulatedTitle;
-        } else if (this._titleControlString.startsWith("#")) {
-            const titleFieldKey = this._titleControlString.substring(1);
-            UndoManager.RunInBatch(() => titleFieldKey && SelectionManager.Views().forEach(d => {
-                if (titleFieldKey === "title") {
-                    d.dataDoc["title-custom"] = !this._accumulatedTitle.startsWith("-");
-                    if (StrCast(d.rootDoc.title).startsWith("@") && !this._accumulatedTitle.startsWith("@")) {
-                        Doc.RemoveDocFromList(Doc.UserDoc(), "myPublishedDocs", d.rootDoc);
-                    }
-                    if (!StrCast(d.rootDoc.title).startsWith("@") && this._accumulatedTitle.startsWith("@")) {
-                        Doc.AddDocToList(Doc.UserDoc(), "myPublishedDocs", d.rootDoc);
-                    }
-                }
-                //@ts-ignore
-                const titleField = (+this._accumulatedTitle === this._accumulatedTitle ? +this._accumulatedTitle : this._accumulatedTitle);
-                Doc.SetInPlace(d.rootDoc, titleFieldKey, titleField, true);
-
-                if (d.rootDoc.syncLayoutFieldWithTitle) {
-                    const title = titleField.toString();
-                    const curKey = Doc.LayoutFieldKey(d.rootDoc);
-                    if (curKey !== title && d.dataDoc[title] === undefined) {
-                        d.rootDoc.layout = FormattedTextBox.LayoutString(title);
-                        setTimeout(() => {
-                            const val = d.dataDoc[curKey];
-                            d.dataDoc[curKey] = undefined;
-                            d.dataDoc[title] = val;
-                        });
-                    }
-                }
-            }), "title blur");
-        }
-    }
-
-    titleEntered = (e: React.KeyboardEvent) => {
-        if (e.key === "Enter") {
-            e.stopPropagation();
-            (e.target as any).blur();
-        }
-    }
-
-    @action onTitleDown = (e: React.PointerEvent): void => {
-        setupMoveUpEvents(this, e, e => this.onBackgroundMove(true, e), (e) => { }, action((e) => {
-            !this._edtingTitle && (this._accumulatedTitle = this._titleControlString.startsWith("#") ? this.selectionTitle : this._titleControlString);
-            this._edtingTitle = true;
-            this._keyinput.current && setTimeout(this._keyinput.current.focus);
-        }));
-    }
-
-    onBackgroundDown = (e: React.PointerEvent) => setupMoveUpEvents(this, e, e => this.onBackgroundMove(false, e), emptyFunction, emptyFunction);
-
-    @action
-    onBackgroundMove = (dragTitle: boolean, e: PointerEvent): boolean => {
-        const dragDocView = SelectionManager.Views()[0];
-        const { left, top } = dragDocView.getBounds() || { left: 0, top: 0 };
-        const dragData = new DragManager.DocumentDragData(SelectionManager.Views().map(dv => dv.props.Document), dragDocView.props.dropAction);
-        dragData.offset = dragDocView.props.ScreenToLocalTransform().transformDirection(e.x - left, e.y - top);
-        dragData.moveDocument = dragDocView.props.moveDocument;
-        dragData.isDocDecorationMove = true;
-        dragData.canEmbed = dragTitle;
-        this._hidden = this.Interacting = true;
-        DragManager.StartDocumentDrag(SelectionManager.Views().map(dv => dv.ContentDiv!), dragData, e.x, e.y, {
-            dragComplete: action(e => {
-                dragData.canEmbed && SelectionManager.DeselectAll();
-                this._hidden = this.Interacting = false;
-            }),
-            hideSource: true
-        });
-        return true;
-    }
-
-    _deleteAfterIconify = false;
-    _iconifyBatch: UndoManager.Batch | undefined;
-    onCloseClick = (forceDeleteOrIconify: boolean | undefined) => {
-        if (this.canDelete) {
-            const views = SelectionManager.Views().slice().filter(v => v);
-            if (forceDeleteOrIconify === false && this._iconifyBatch) return;
-            this._deleteAfterIconify = forceDeleteOrIconify || this._iconifyBatch ? true : false;
-            if (!this._iconifyBatch) {
-                this._iconifyBatch = UndoManager.StartBatch("iconifying");
-            } else {
-                forceDeleteOrIconify = false; // can't force immediate close in the middle of iconifying -- have to wait until iconifying completes
+      static Instance: DocumentDecorations;
+      private _resizeHdlId = "";
+      private _keyinput = React.createRef<HTMLInputElement>();
+      private _resizeBorderWidth = 16;
+      private _linkBoxHeight = 20 + 3; // link button height + margin
+      private _titleHeight = 20;
+      private _resizeUndo?: UndoManager.Batch;
+      private _offX = 0; _offY = 0;  // offset from click pt to inner edge of resize border
+      private _snapX = 0; _snapY = 0; // last snapped location of resize border
+      private _dragHeights = new Map<Doc, { start: number, lowest: number }>();
+      private _inkDragDocs: { doc: Doc, x: number, y: number, width: number, height: number }[] = [];
+
+      @observable private _accumulatedTitle = "";
+      @observable private _titleControlString: string = "#title";
+      @observable private _edtingTitle = false;
+      @observable private _hidden = false;
+      @observable public AddToSelection = false; // if Shift is pressed, then this should be set so that clicking on the selection background is ignored so overlapped documents can be added to the selection set.
+      @observable public Interacting = false;
+      @observable public pushIcon: IconProp = "arrow-alt-circle-up";
+      @observable public pullIcon: IconProp = "arrow-alt-circle-down";
+      @observable public pullColor: string = "white";
+
+      constructor(props: any) {
+            super(props);
+            DocumentDecorations.Instance = this;
+            reaction(() => SelectionManager.Views().slice(), action(docs => this._edtingTitle = false));
+      }
+
+      @computed
+      get Bounds() {
+            const views = SelectionManager.Views();
+            return views.filter(dv => dv.props.renderDepth > 0).map(dv => dv.getBounds()).reduce((bounds, rect) =>
+                  !rect ? bounds :
+                        {
+                              x: Math.min(rect.left, bounds.x),
+                              y: Math.min(rect.top, bounds.y),
+                              r: Math.max(rect.right, bounds.r),
+                              b: Math.max(rect.bottom, bounds.b),
+                              c: views.length === 1 ? rect.center : undefined
+                        },
+                  { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE, c: undefined as ({ X: number, Y: number } | undefined) });
+      }
+
+      @action
+      titleBlur = () => {
+            this._edtingTitle = false;
+            if (this._accumulatedTitle.startsWith("#") || this._accumulatedTitle.startsWith("=")) {
+                  this._titleControlString = this._accumulatedTitle;
+            } else if (this._titleControlString.startsWith("#")) {
+                  const titleFieldKey = this._titleControlString.substring(1);
+                  UndoManager.RunInBatch(() => titleFieldKey && SelectionManager.Views().forEach(d => {
+                        if (titleFieldKey === "title") {
+                              d.dataDoc["title-custom"] = !this._accumulatedTitle.startsWith("-");
+                              if (StrCast(d.rootDoc.title).startsWith("@") && !this._accumulatedTitle.startsWith("@")) {
+                                    Doc.RemoveDocFromList(Doc.UserDoc(), "myPublishedDocs", d.rootDoc);
+                              }
+                              if (!StrCast(d.rootDoc.title).startsWith("@") && this._accumulatedTitle.startsWith("@")) {
+                                    Doc.AddDocToList(Doc.UserDoc(), "myPublishedDocs", d.rootDoc);
+                              }
+                        }
+                        //@ts-ignore
+                        const titleField = (+this._accumulatedTitle === this._accumulatedTitle ? +this._accumulatedTitle : this._accumulatedTitle);
+                        Doc.SetInPlace(d.rootDoc, titleFieldKey, titleField, true);
+
+                        if (d.rootDoc.syncLayoutFieldWithTitle) {
+                              const title = titleField.toString();
+                              const curKey = Doc.LayoutFieldKey(d.rootDoc);
+                              if (curKey !== title && d.dataDoc[title] === undefined) {
+                                    d.rootDoc.layout = FormattedTextBox.LayoutString(title);
+                                    setTimeout(() => {
+                                          const val = d.dataDoc[curKey];
+                                          d.dataDoc[curKey] = undefined;
+                                          d.dataDoc[title] = val;
+                                    });
+                              }
+                        }
+                  }), "title blur");
             }
-            var iconifyingCount = views.length;
-            const finished = action((force?: boolean) => {
-                if ((force || --iconifyingCount === 0) && this._iconifyBatch) {
-                    if (this._deleteAfterIconify) {
-                        views.forEach(iconView => iconView.props.removeDocument?.(iconView.props.Document));
-                        SelectionManager.DeselectAll();
-                    }
-                    this._iconifyBatch?.end();
-                    this._iconifyBatch = undefined;
-                }
+      }
+
+      titleEntered = (e: React.KeyboardEvent) => {
+            if (e.key === "Enter") {
+                  e.stopPropagation();
+                  (e.target as any).blur();
+            }
+      }
+
+      @action onTitleDown = (e: React.PointerEvent): void => {
+            setupMoveUpEvents(this, e, e => this.onBackgroundMove(true, e), (e) => { }, action((e) => {
+                  !this._edtingTitle && (this._accumulatedTitle = this._titleControlString.startsWith("#") ? this.selectionTitle : this._titleControlString);
+                  this._edtingTitle = true;
+                  this._keyinput.current && setTimeout(this._keyinput.current.focus);
+            }));
+      }
+
+      onBackgroundDown = (e: React.PointerEvent) => setupMoveUpEvents(this, e, e => this.onBackgroundMove(false, e), emptyFunction, emptyFunction);
+
+      @action
+      onBackgroundMove = (dragTitle: boolean, e: PointerEvent): boolean => {
+            const dragDocView = SelectionManager.Views()[0];
+            const { left, top } = dragDocView.getBounds() || { left: 0, top: 0 };
+            const dragData = new DragManager.DocumentDragData(SelectionManager.Views().map(dv => dv.props.Document), dragDocView.props.dropAction);
+            dragData.offset = dragDocView.props.ScreenToLocalTransform().transformDirection(e.x - left, e.y - top);
+            dragData.moveDocument = dragDocView.props.moveDocument;
+            dragData.isDocDecorationMove = true;
+            dragData.canEmbed = dragTitle;
+            this._hidden = this.Interacting = true;
+            DragManager.StartDocumentDrag(SelectionManager.Views().map(dv => dv.ContentDiv!), dragData, e.x, e.y, {
+                  dragComplete: action(e => {
+                        dragData.canEmbed && SelectionManager.DeselectAll();
+                        this._hidden = this.Interacting = false;
+                  }),
+                  hideSource: true
             });
-            if (forceDeleteOrIconify) finished(forceDeleteOrIconify);
-            else if (!this._deleteAfterIconify) views.forEach(dv => dv.iconify(finished));
-        }
-    }
-    onMaximizeDown = (e: React.PointerEvent) => {
-        setupMoveUpEvents(this, e, () => {
-            DragManager.StartWindowDrag?.(e, [SelectionManager.Views().slice(-1)[0].rootDoc]);
             return true;
-        }, emptyFunction, this.onMaximizeClick, false, false);
-    }
-
-    onMaximizeClick = (e: any): void => {
-        const selectedDocs = SelectionManager.Views();
-        if (selectedDocs.length) {
-            if (e.ctrlKey) {    // open an alias in a new tab with Ctrl Key
-                const bestAlias = DocListCast(selectedDocs[0].props.Document.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail);
-                CollectionDockingView.AddSplit(bestAlias ?? Doc.MakeAlias(selectedDocs[0].props.Document), "right");
-            } else if (e.shiftKey) {   // open centered in a new workspace with Shift Key
-                const alias = Doc.MakeAlias(selectedDocs[0].props.Document);
-                alias.context = undefined;
-                alias.x = -alias[WidthSym]() / 2;
-                alias.y = -alias[HeightSym]() / 2;
-                CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([alias], { title: "Tab for " + alias.title }), "right");
-            } else if (e.altKey) {    // open same document in new tab
-                CollectionDockingView.ToggleSplit(selectedDocs[0].props.Document, "right");
-            } else {
-                var openDoc = selectedDocs[0].props.Document;
-                if (openDoc.layoutKey === "layout_icon") {
-                    openDoc = DocListCast(openDoc.aliases).find(alias => !alias.context) ?? Doc.MakeAlias(openDoc);
-                    Doc.deiconifyView(openDoc);
-                }
-                LightboxView.SetLightboxDoc(openDoc, undefined, selectedDocs.slice(1).map(view => view.props.Document));
+      }
+
+      _deleteAfterIconify = false;
+      _iconifyBatch: UndoManager.Batch | undefined;
+      onCloseClick = (forceDeleteOrIconify: boolean | undefined) => {
+            if (this.canDelete) {
+                  const views = SelectionManager.Views().slice().filter(v => v);
+                  if (forceDeleteOrIconify === false && this._iconifyBatch) return;
+                  this._deleteAfterIconify = forceDeleteOrIconify || this._iconifyBatch ? true : false;
+                  if (!this._iconifyBatch) {
+                        this._iconifyBatch = UndoManager.StartBatch("iconifying");
+                  } else {
+                        forceDeleteOrIconify = false; // can't force immediate close in the middle of iconifying -- have to wait until iconifying completes
+                  }
+                  var iconifyingCount = views.length;
+                  const finished = action((force?: boolean) => {
+                        if ((force || --iconifyingCount === 0) && this._iconifyBatch) {
+                              if (this._deleteAfterIconify) {
+                                    views.forEach(iconView => iconView.props.removeDocument?.(iconView.props.Document));
+                                    SelectionManager.DeselectAll();
+                              }
+                              this._iconifyBatch?.end();
+                              this._iconifyBatch = undefined;
+                        }
+                  });
+                  if (forceDeleteOrIconify) finished(forceDeleteOrIconify);
+                  else if (!this._deleteAfterIconify) views.forEach(dv => dv.iconify(finished));
             }
-        }
-        SelectionManager.DeselectAll();
-    }
-
-    onIconifyClick = (): void => {
-        SelectionManager.Views().forEach(dv => dv?.iconify());
-        SelectionManager.DeselectAll();
-    }
-
-    onSelectorClick = () => SelectionManager.Views()?.[0]?.props.ContainingCollectionView?.props.select(false);
-
-    onRadiusDown = (e: React.PointerEvent): void => {
-        this._resizeUndo = UndoManager.StartBatch("DocDecs set radius");
-        setupMoveUpEvents(this, e, (e, down) => {
-            const dist = Math.sqrt((e.clientX - down[0]) * (e.clientX - down[0]) + (e.clientY - down[1]) * (e.clientY - down[1]));
-            SelectionManager.Views().map(dv => dv.props.Document).map(doc => doc.layout instanceof Doc ? doc.layout : doc.isTemplateForField ? doc : Doc.GetProto(doc)).
-                map(d => d.borderRounding = `${Math.max(0, dist < 3 ? 0 : dist)}px`);
-            return false;
-        }, (e) => this._resizeUndo?.end(), (e) => { });
-    }
-
-    @action
-    onRotateDown = (e: React.PointerEvent): void => {
-        const rotateUndo = UndoManager.StartBatch("rotatedown");
-        const selectedInk = SelectionManager.Views().filter(i => i.ComponentView instanceof InkingStroke);
-        const centerPoint = !selectedInk.length ? { X: this.Bounds.x, Y: this.Bounds.y } : { X: this.Bounds.c?.X ?? (this.Bounds.x + this.Bounds.r) / 2, Y: this.Bounds.c?.Y ?? (this.Bounds.y + this.Bounds.b) / 2 };
-        setupMoveUpEvents(this, e,
-            (e: PointerEvent, down: number[], delta: number[]) => {
-                const previousPoint = { X: e.clientX, Y: e.clientY };
-                const movedPoint = { X: e.clientX - delta[0], Y: e.clientY - delta[1] };
-                const angle = InkStrokeProperties.angleChange(previousPoint, movedPoint, centerPoint);
-                if (selectedInk.length) {
-                    angle && InkStrokeProperties.Instance.rotateInk(selectedInk, -angle, centerPoint);
-                } else {
-                    SelectionManager.Views().forEach(dv => dv.rootDoc._jitterRotation = NumCast(dv.rootDoc._jitterRotation) - angle * 180 / Math.PI);
-                }
-                return false;
-            },
-            () => {
-                rotateUndo?.end();
-                UndoManager.FilterBatches(["data", "x", "y", "width", "height"]);
-            },
-            emptyFunction);
-    }
-
-    @action
-    onPointerDown = (e: React.PointerEvent): void => {
-        DragManager.docsBeingDragged = SelectionManager.Views().map(dv => dv.rootDoc);
-        this._inkDragDocs = DragManager.docsBeingDragged
-            .filter(doc => doc.type === DocumentType.INK)
-            .map(doc => {
-                if (InkStrokeProperties.Instance._lock) {
-                    Doc.SetNativeHeight(doc, NumCast(doc._height));
-                    Doc.SetNativeWidth(doc, NumCast(doc._width));
-                }
-                return ({ doc, x: NumCast(doc.x), y: NumCast(doc.y), width: NumCast(doc._width), height: NumCast(doc._height) });
-            });
-
-        setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction);
-        this.Interacting = true; // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them
-        this._resizeHdlId = e.currentTarget.className;
-        const bounds = e.currentTarget.getBoundingClientRect();
-        this._offX = this._resizeHdlId.toLowerCase().includes("left") ? bounds.right - e.clientX : bounds.left - e.clientX;
-        this._offY = this._resizeHdlId.toLowerCase().includes("top") ? bounds.bottom - e.clientY : bounds.top - e.clientY;
-        this._resizeUndo = UndoManager.StartBatch("DocDecs resize");
-        this._snapX = e.pageX;
-        this._snapY = e.pageY;
-        const ffviewSet = new Set<CollectionFreeFormView>();
-        SelectionManager.Views().forEach(docView => {
-            const ffview = docView.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView;
-            ffview && ffviewSet.add(ffview);
-            this._dragHeights.set(docView.layoutDoc, { start: NumCast(docView.rootDoc._height), lowest: NumCast(docView.rootDoc._height) });
-        });
-        Array.from(ffviewSet).map(ffview => ffview.setupDragLines(false));
-    }
-
-    onPointerMove = (e: PointerEvent, down: number[], move: number[]): boolean => {
-        const first = SelectionManager.Views()[0];
-        let thisPt = { x: e.clientX - this._offX, y: e.clientY - this._offY };
-        var fixedAspect = Doc.NativeAspect(first.layoutDoc);
-        InkStrokeProperties.Instance._lock && SelectionManager.Views().filter(dv => dv.rootDoc.type === DocumentType.INK)
-            .forEach(dv => fixedAspect = Doc.NativeAspect(dv.rootDoc));
-
-        const resizeHdl = this._resizeHdlId.split(" ")[0];
-        if (fixedAspect && (resizeHdl === "documentDecorations-bottomRightResizer" || resizeHdl === "documentDecorations-topLeftResizer")) { // need to generalize for bl and tr drag handles
-            const project = (p: number[], a: number[], b: number[]) => {
-                const atob = [b[0] - a[0], b[1] - a[1]];
-                const atop = [p[0] - a[0], p[1] - a[1]];
-                const len = atob[0] * atob[0] + atob[1] * atob[1];
-                let dot = atop[0] * atob[0] + atop[1] * atob[1];
-                const t = dot / len;
-                dot = (b[0] - a[0]) * (p[1] - a[1]) - (b[1] - a[1]) * (p[0] - a[0]);
-                return [a[0] + atob[0] * t, a[1] + atob[1] * t];
-            };
-            const tl = first.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
-            const drag = project([e.clientX + this._offX, e.clientY + this._offY], tl, [tl[0] + fixedAspect, tl[1] + 1]);
-            thisPt = DragManager.snapDragAspect(drag, fixedAspect);
-        } else {
-            thisPt = DragManager.snapDrag(e, -this._offX, -this._offY, this._offX, this._offY);
-        }
-
-        move[0] = thisPt.x - this._snapX;
-        move[1] = thisPt.y - this._snapY;
-        this._snapX = thisPt.x;
-        this._snapY = thisPt.y;
-        let dragBottom = false, dragRight = false, dragBotRight = false;
-        let dX = 0, dY = 0, dW = 0, dH = 0;
-        switch (this._resizeHdlId.split(" ")[0]) {
-            case "": break;
-            case "documentDecorations-topLeftResizer":
-                dX = -1;
-                dY = -1;
-                dW = -move[0];
-                dH = -move[1];
-                break;
-            case "documentDecorations-topRightResizer":
-                dW = move[0];
-                dY = -1;
-                dH = -move[1];
-                break;
-            case "documentDecorations-topResizer":
-                dY = -1;
-                dH = -move[1];
-                dragBottom = true;
-                break;
-            case "documentDecorations-bottomLeftResizer":
-                dX = -1;
-                dW = -move[0];
-                dH = move[1];
-                break;
-            case "documentDecorations-bottomRightResizer":
-                dW = move[0];
-                dH = move[1];
-                dragBotRight = true;
-                break;
-            case "documentDecorations-bottomResizer":
-                dH = move[1];
-                dragBottom = true;
-                break;
-            case "documentDecorations-leftResizer":
-                dX = -1;
-                dW = -move[0];
-                break;
-            case "documentDecorations-rightResizer":
-                dW = move[0];
-                dragRight = true;
-                break;
-        }
-
-        SelectionManager.Views().forEach(action((docView: DocumentView) => {
-            if (e.ctrlKey && !Doc.NativeHeight(docView.props.Document)) docView.toggleNativeDimensions();
-            if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) {
-                const doc = Document(docView.rootDoc);
-                const nwidth = docView.nativeWidth;
-                const nheight = docView.nativeHeight;
-                const docheight = doc._height || 0;
-                const docwidth = doc._width || 0;
-                const width = docwidth;
-                let height = (docheight || (nheight / nwidth * width));
-                height = !height || isNaN(height) ? 20 : height;
-                const scale = docView.props.ScreenToLocalTransform().Scale;
-                const modifyNativeDim = (e.ctrlKey || doc.forceReflow) && doc.nativeDimModifiable;
-                if (nwidth && nheight) {
-                    if (nwidth / nheight !== width / height && !dragBottom) {
-                        height = nheight / nwidth * width;
-                    }
-                    if (modifyNativeDim && !dragBottom) { // ctrl key enables modification of the nativeWidth or nativeHeight durin the interaction
-                        if (Math.abs(dW) > Math.abs(dH)) dH = dW * nheight / nwidth;
-                        else dW = dH * nwidth / nheight;
-                    }
-                }
-                let actualdW = Math.max(width + (dW * scale), 20);
-                let actualdH = Math.max(height + (dH * scale), 20);
-                const fixedAspect = (nwidth && nheight && !doc._fitWidth);
-                if (fixedAspect) {
-                    if ((Math.abs(dW) > Math.abs(dH) && (!dragBottom || !modifyNativeDim)) || dragRight) {
-                        if (dragRight && modifyNativeDim) {
-                            doc._nativeWidth = actualdW / (doc._width || 1) * Doc.NativeWidth(doc);
-                        } else {
-                            if (!doc._fitWidth) {
-                                actualdH = nheight / nwidth * actualdW;
-                                doc._height = actualdH;
-                            }
-                            else if (!modifyNativeDim || dragBotRight) doc._height = actualdH;
+      }
+      onMaximizeDown = (e: React.PointerEvent) => {
+            setupMoveUpEvents(this, e, () => {
+                  DragManager.StartWindowDrag?.(e, [SelectionManager.Views().slice(-1)[0].rootDoc]);
+                  return true;
+            }, emptyFunction, this.onMaximizeClick, false, false);
+      }
+
+      onMaximizeClick = (e: any): void => {
+            const selectedDocs = SelectionManager.Views();
+            if (selectedDocs.length) {
+                  if (e.ctrlKey) {    // open an alias in a new tab with Ctrl Key
+                        const bestAlias = DocListCast(selectedDocs[0].props.Document.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail);
+                        CollectionDockingView.AddSplit(bestAlias ?? Doc.MakeAlias(selectedDocs[0].props.Document), "right");
+                  } else if (e.shiftKey) {   // open centered in a new workspace with Shift Key
+                        const alias = Doc.MakeAlias(selectedDocs[0].props.Document);
+                        alias.context = undefined;
+                        alias.x = -alias[WidthSym]() / 2;
+                        alias.y = -alias[HeightSym]() / 2;
+                        CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([alias], { title: "Tab for " + alias.title }), "right");
+                  } else if (e.altKey) {    // open same document in new tab
+                        CollectionDockingView.ToggleSplit(selectedDocs[0].props.Document, "right");
+                  } else {
+                        var openDoc = selectedDocs[0].props.Document;
+                        if (openDoc.layoutKey === "layout_icon") {
+                              openDoc = DocListCast(openDoc.aliases).find(alias => !alias.context) ?? Doc.MakeAlias(openDoc);
+                              Doc.deiconifyView(openDoc);
                         }
-                        doc._width = actualdW;
-                    }
-                    else {
-                        if (dragBottom && (modifyNativeDim ||
-                            (docView.layoutDoc.nativeHeightUnfrozen && docView.layoutDoc._fitWidth))) { // frozen web pages, PDFs, and some RTFS have frozen nativewidth/height.  But they are marked to allow their nativeHeight to be explicitly modified with fitWidth and vertical resizing. (ie, with fitWidth they can't grow horizontally to match a vertical resize so it makes more sense to change their nativeheight even if the ctrl key isn't used)
-                            doc._nativeHeight = actualdH / (doc._height || 1) * Doc.NativeHeight(doc);
-                            doc._autoHeight = false;
+                        LightboxView.SetLightboxDoc(openDoc, undefined, selectedDocs.slice(1).map(view => view.props.Document));
+                  }
+            }
+            SelectionManager.DeselectAll();
+      }
+
+      onIconifyClick = (): void => {
+            SelectionManager.Views().forEach(dv => dv?.iconify());
+            SelectionManager.DeselectAll();
+      }
+
+      onSelectorClick = () => SelectionManager.Views()?.[0]?.props.ContainingCollectionView?.props.select(false);
+
+      onRadiusDown = (e: React.PointerEvent): void => {
+            this._resizeUndo = UndoManager.StartBatch("DocDecs set radius");
+            setupMoveUpEvents(this, e, (e, down) => {
+                  const dist = Math.sqrt((e.clientX - down[0]) * (e.clientX - down[0]) + (e.clientY - down[1]) * (e.clientY - down[1]));
+                  SelectionManager.Views().map(dv => dv.props.Document).map(doc => doc.layout instanceof Doc ? doc.layout : doc.isTemplateForField ? doc : Doc.GetProto(doc)).
+                        map(d => d.borderRounding = `${Math.max(0, dist < 3 ? 0 : dist)}px`);
+                  return false;
+            }, (e) => this._resizeUndo?.end(), (e) => { });
+      }
+
+      @action
+      onRotateDown = (e: React.PointerEvent): void => {
+            const rotateUndo = UndoManager.StartBatch("rotatedown");
+            const selectedInk = SelectionManager.Views().filter(i => i.ComponentView instanceof InkingStroke);
+            const centerPoint = !selectedInk.length ? { X: this.Bounds.x, Y: this.Bounds.y } : { X: this.Bounds.c?.X ?? (this.Bounds.x + this.Bounds.r) / 2, Y: this.Bounds.c?.Y ?? (this.Bounds.y + this.Bounds.b) / 2 };
+            setupMoveUpEvents(this, e,
+                  (e: PointerEvent, down: number[], delta: number[]) => {
+                        const previousPoint = { X: e.clientX, Y: e.clientY };
+                        const movedPoint = { X: e.clientX - delta[0], Y: e.clientY - delta[1] };
+                        const angle = InkStrokeProperties.angleChange(previousPoint, movedPoint, centerPoint);
+                        if (selectedInk.length) {
+                              angle && InkStrokeProperties.Instance.rotateInk(selectedInk, -angle, centerPoint);
                         } else {
-                            if (!doc._fitWidth) {
-                                actualdW = nwidth / nheight * actualdH;
-                                doc._width = actualdW;
-                            }
-                            else if (!modifyNativeDim || dragBotRight) doc._width = actualdW;
+                              SelectionManager.Views().forEach(dv => dv.rootDoc._jitterRotation = NumCast(dv.rootDoc._jitterRotation) - angle * 180 / Math.PI);
                         }
-                        if (!modifyNativeDim) {
-                            actualdH = Math.min(nheight / nwidth * NumCast(doc._width), actualdH);
-                            doc._height = actualdH;
+                        return false;
+                  },
+                  () => {
+                        rotateUndo?.end();
+                        UndoManager.FilterBatches(["data", "x", "y", "width", "height"]);
+                  },
+                  emptyFunction);
+      }
+
+      @action
+      onPointerDown = (e: React.PointerEvent): void => {
+            DragManager.docsBeingDragged = SelectionManager.Views().map(dv => dv.rootDoc);
+            this._inkDragDocs = DragManager.docsBeingDragged
+                  .filter(doc => doc.type === DocumentType.INK)
+                  .map(doc => {
+                        if (InkStrokeProperties.Instance._lock) {
+                              Doc.SetNativeHeight(doc, NumCast(doc._height));
+                              Doc.SetNativeWidth(doc, NumCast(doc._width));
                         }
-                        else doc._height = actualdH;
-                    }
-                } else {
-                    dH && (doc._height = actualdH);
-                    dW && (doc._width = actualdW);
-                    dH && (doc._autoHeight = false);
-                }
-                doc.x = (doc.x || 0) + dX * (actualdW - docwidth);
-                doc.y = (doc.y || 0) + dY * (actualdH - docheight);
-                doc._lastModified = new DateField();
-            }
-            const val = this._dragHeights.get(docView.layoutDoc);
-            if (val) this._dragHeights.set(docView.layoutDoc, { start: val.start, lowest: Math.min(val.lowest, NumCast(docView.layoutDoc._height)) });
-        }));
-        return false;
-    }
-
-    @action
-    onPointerUp = (e: PointerEvent): void => {
-        this._resizeHdlId = "";
-        this.Interacting = false;
-        this._resizeUndo?.end();
-        SnappingManager.clearSnapLines();
-
-        // detect autoHeight gesture and apply
-        SelectionManager.Views().map(docView => ({ doc: docView.layoutDoc, hgts: this._dragHeights.get(docView.layoutDoc) }))
-            .filter(pair => pair.hgts && pair.hgts.lowest < pair.hgts.start && pair.hgts.lowest <= 20)
-            .forEach(pair => pair.doc._autoHeight = true);
-        //need to change points for resize, or else rotation/control points will fail.
-        this._inkDragDocs.map(oldbds => ({ oldbds, inkPts: Cast(oldbds.doc.data, InkField)?.inkData || [] }))
-            .forEach(({ oldbds: { doc, x, y, width, height }, inkPts }) => {
-                Doc.GetProto(doc).data = new InkField(inkPts.map(ipt =>  // (new x — oldx) + newWidth * (oldxpoint /oldWidth)
-                ({
-                    X: (NumCast(doc.x) - x) + NumCast(doc.width) * ipt.X / width,
-                    Y: (NumCast(doc.y) - y) + NumCast(doc.height) * ipt.Y / height
-                })));
-                Doc.SetNativeWidth(doc, undefined);
-                Doc.SetNativeHeight(doc, undefined);
+                        return ({ doc, x: NumCast(doc.x), y: NumCast(doc.y), width: NumCast(doc._width), height: NumCast(doc._height) });
+                  });
+
+            setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction);
+            this.Interacting = true; // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them
+            this._resizeHdlId = e.currentTarget.className;
+            const bounds = e.currentTarget.getBoundingClientRect();
+            this._offX = this._resizeHdlId.toLowerCase().includes("left") ? bounds.right - e.clientX : bounds.left - e.clientX;
+            this._offY = this._resizeHdlId.toLowerCase().includes("top") ? bounds.bottom - e.clientY : bounds.top - e.clientY;
+            this._resizeUndo = UndoManager.StartBatch("DocDecs resize");
+            this._snapX = e.pageX;
+            this._snapY = e.pageY;
+            const ffviewSet = new Set<CollectionFreeFormView>();
+            SelectionManager.Views().forEach(docView => {
+                  const ffview = docView.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView;
+                  ffview && ffviewSet.add(ffview);
+                  this._dragHeights.set(docView.layoutDoc, { start: NumCast(docView.rootDoc._height), lowest: NumCast(docView.rootDoc._height) });
             });
-    }
-
-    @computed
-    get selectionTitle(): string {
-        if (SelectionManager.Views().length === 1) {
-            const selected = SelectionManager.Views()[0];
-            if (selected.ComponentView?.getTitle?.()) {
-                return selected.ComponentView.getTitle();
+            Array.from(ffviewSet).map(ffview => ffview.setupDragLines(false));
+      }
+
+      onPointerMove = (e: PointerEvent, down: number[], move: number[]): boolean => {
+            const first = SelectionManager.Views()[0];
+            let thisPt = { x: e.clientX - this._offX, y: e.clientY - this._offY };
+            var fixedAspect = Doc.NativeAspect(first.layoutDoc);
+            InkStrokeProperties.Instance._lock && SelectionManager.Views().filter(dv => dv.rootDoc.type === DocumentType.INK)
+                  .forEach(dv => fixedAspect = Doc.NativeAspect(dv.rootDoc));
+
+            const resizeHdl = this._resizeHdlId.split(" ")[0];
+            if (fixedAspect && (resizeHdl === "documentDecorations-bottomRightResizer" || resizeHdl === "documentDecorations-topLeftResizer")) { // need to generalize for bl and tr drag handles
+                  const project = (p: number[], a: number[], b: number[]) => {
+                        const atob = [b[0] - a[0], b[1] - a[1]];
+                        const atop = [p[0] - a[0], p[1] - a[1]];
+                        const len = atob[0] * atob[0] + atob[1] * atob[1];
+                        let dot = atop[0] * atob[0] + atop[1] * atob[1];
+                        const t = dot / len;
+                        dot = (b[0] - a[0]) * (p[1] - a[1]) - (b[1] - a[1]) * (p[0] - a[0]);
+                        return [a[0] + atob[0] * t, a[1] + atob[1] * t];
+                  };
+                  const tl = first.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
+                  const drag = project([e.clientX + this._offX, e.clientY + this._offY], tl, [tl[0] + fixedAspect, tl[1] + 1]);
+                  thisPt = DragManager.snapDragAspect(drag, fixedAspect);
+            } else {
+                  thisPt = DragManager.snapDrag(e, -this._offX, -this._offY, this._offX, this._offY);
             }
-            if (this._titleControlString.startsWith("=")) {
-                return ScriptField.MakeFunction(this._titleControlString.substring(1), { doc: Doc.name })!.script.run({ self: selected.rootDoc, this: selected.layoutDoc }, console.log).result?.toString() || "";
+
+            move[0] = thisPt.x - this._snapX;
+            move[1] = thisPt.y - this._snapY;
+            this._snapX = thisPt.x;
+            this._snapY = thisPt.y;
+            let dragBottom = false, dragRight = false, dragBotRight = false;
+            let dX = 0, dY = 0, dW = 0, dH = 0;
+            switch (this._resizeHdlId.split(" ")[0]) {
+                  case "": break;
+                  case "documentDecorations-topLeftResizer":
+                        dX = -1;
+                        dY = -1;
+                        dW = -move[0];
+                        dH = -move[1];
+                        break;
+                  case "documentDecorations-topRightResizer":
+                        dW = move[0];
+                        dY = -1;
+                        dH = -move[1];
+                        break;
+                  case "documentDecorations-topResizer":
+                        dY = -1;
+                        dH = -move[1];
+                        dragBottom = true;
+                        break;
+                  case "documentDecorations-bottomLeftResizer":
+                        dX = -1;
+                        dW = -move[0];
+                        dH = move[1];
+                        break;
+                  case "documentDecorations-bottomRightResizer":
+                        dW = move[0];
+                        dH = move[1];
+                        dragBotRight = true;
+                        break;
+                  case "documentDecorations-bottomResizer":
+                        dH = move[1];
+                        dragBottom = true;
+                        break;
+                  case "documentDecorations-leftResizer":
+                        dX = -1;
+                        dW = -move[0];
+                        break;
+                  case "documentDecorations-rightResizer":
+                        dW = move[0];
+                        dragRight = true;
+                        break;
             }
-            if (this._titleControlString.startsWith("#")) {
-                return Field.toString(selected.props.Document[this._titleControlString.substring(1)] as Field) || "-unset-";
+
+            SelectionManager.Views().forEach(action((docView: DocumentView) => {
+                  if (e.ctrlKey && !Doc.NativeHeight(docView.props.Document)) docView.toggleNativeDimensions();
+                  if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) {
+                        const doc = Document(docView.rootDoc);
+                        const nwidth = docView.nativeWidth;
+                        const nheight = docView.nativeHeight;
+                        const docheight = doc._height || 0;
+                        const docwidth = doc._width || 0;
+                        const width = docwidth;
+                        let height = (docheight || (nheight / nwidth * width));
+                        height = !height || isNaN(height) ? 20 : height;
+                        const scale = docView.props.ScreenToLocalTransform().Scale;
+                        const modifyNativeDim = (e.ctrlKey || doc.forceReflow) && doc.nativeDimModifiable;
+                        if (nwidth && nheight) {
+                              if (nwidth / nheight !== width / height && !dragBottom) {
+                                    height = nheight / nwidth * width;
+                              }
+                              if (modifyNativeDim && !dragBottom) { // ctrl key enables modification of the nativeWidth or nativeHeight durin the interaction
+                                    if (Math.abs(dW) > Math.abs(dH)) dH = dW * nheight / nwidth;
+                                    else dW = dH * nwidth / nheight;
+                              }
+                        }
+                        let actualdW = Math.max(width + (dW * scale), 20);
+                        let actualdH = Math.max(height + (dH * scale), 20);
+                        const fixedAspect = (nwidth && nheight && !doc._fitWidth);
+                        if (fixedAspect) {
+                              if ((Math.abs(dW) > Math.abs(dH) && (!dragBottom || !modifyNativeDim)) || dragRight) {
+                                    if (dragRight && modifyNativeDim) {
+                                          doc._nativeWidth = actualdW / (doc._width || 1) * Doc.NativeWidth(doc);
+                                    } else {
+                                          if (!doc._fitWidth) {
+                                                actualdH = nheight / nwidth * actualdW;
+                                                doc._height = actualdH;
+                                          }
+                                          else if (!modifyNativeDim || dragBotRight) doc._height = actualdH;
+                                    }
+                                    doc._width = actualdW;
+                              }
+                              else {
+                                    if (dragBottom && (modifyNativeDim ||
+                                          (docView.layoutDoc.nativeHeightUnfrozen && docView.layoutDoc._fitWidth))) { // frozen web pages, PDFs, and some RTFS have frozen nativewidth/height.  But they are marked to allow their nativeHeight to be explicitly modified with fitWidth and vertical resizing. (ie, with fitWidth they can't grow horizontally to match a vertical resize so it makes more sense to change their nativeheight even if the ctrl key isn't used)
+                                          doc._nativeHeight = actualdH / (doc._height || 1) * Doc.NativeHeight(doc);
+                                          doc._autoHeight = false;
+                                    } else {
+                                          if (!doc._fitWidth) {
+                                                actualdW = nwidth / nheight * actualdH;
+                                                doc._width = actualdW;
+                                          }
+                                          else if (!modifyNativeDim || dragBotRight) doc._width = actualdW;
+                                    }
+                                    if (!modifyNativeDim) {
+                                          actualdH = Math.min(nheight / nwidth * NumCast(doc._width), actualdH);
+                                          doc._height = actualdH;
+                                    }
+                                    else doc._height = actualdH;
+                              }
+                        } else {
+                              dH && (doc._height = actualdH);
+                              dW && (doc._width = actualdW);
+                              dH && (doc._autoHeight = false);
+                        }
+                        doc.x = (doc.x || 0) + dX * (actualdW - docwidth);
+                        doc.y = (doc.y || 0) + dY * (actualdH - docheight);
+                        doc._lastModified = new DateField();
+                  }
+                  const val = this._dragHeights.get(docView.layoutDoc);
+                  if (val) this._dragHeights.set(docView.layoutDoc, { start: val.start, lowest: Math.min(val.lowest, NumCast(docView.layoutDoc._height)) });
+            }));
+            return false;
+      }
+
+      @action
+      onPointerUp = (e: PointerEvent): void => {
+            this._resizeHdlId = "";
+            this.Interacting = false;
+            this._resizeUndo?.end();
+            SnappingManager.clearSnapLines();
+
+            // detect autoHeight gesture and apply
+            SelectionManager.Views().map(docView => ({ doc: docView.layoutDoc, hgts: this._dragHeights.get(docView.layoutDoc) }))
+                  .filter(pair => pair.hgts && pair.hgts.lowest < pair.hgts.start && pair.hgts.lowest <= 20)
+                  .forEach(pair => pair.doc._autoHeight = true);
+            //need to change points for resize, or else rotation/control points will fail.
+            this._inkDragDocs.map(oldbds => ({ oldbds, inkPts: Cast(oldbds.doc.data, InkField)?.inkData || [] }))
+                  .forEach(({ oldbds: { doc, x, y, width, height }, inkPts }) => {
+                        Doc.GetProto(doc).data = new InkField(inkPts.map(ipt =>  // (new x — oldx) + newWidth * (oldxpoint /oldWidth)
+                        ({
+                              X: (NumCast(doc.x) - x) + NumCast(doc.width) * ipt.X / width,
+                              Y: (NumCast(doc.y) - y) + NumCast(doc.height) * ipt.Y / height
+                        })));
+                        Doc.SetNativeWidth(doc, undefined);
+                        Doc.SetNativeHeight(doc, undefined);
+                  });
+      }
+
+      @computed
+      get selectionTitle(): string {
+            if (SelectionManager.Views().length === 1) {
+                  const selected = SelectionManager.Views()[0];
+                  if (selected.ComponentView?.getTitle?.()) {
+                        return selected.ComponentView.getTitle();
+                  }
+                  if (this._titleControlString.startsWith("=")) {
+                        return ScriptField.MakeFunction(this._titleControlString.substring(1), { doc: Doc.name })!.script.run({ self: selected.rootDoc, this: selected.layoutDoc }, console.log).result?.toString() || "";
+                  }
+                  if (this._titleControlString.startsWith("#")) {
+                        return Field.toString(selected.props.Document[this._titleControlString.substring(1)] as Field) || "-unset-";
+                  }
+                  return this._accumulatedTitle;
+            }
+            return SelectionManager.Views().length > 1 ? "-multiple-" : "-unset-";
+      }
+
+      @computed get canDelete() {
+            return SelectionManager.Views().some(docView => {
+                  if (docView.rootDoc.stayInCollection) return false;
+                  const collectionAcl = docView.props.ContainingCollectionView ? GetEffectiveAcl(docView.props.ContainingCollectionDoc?.[DataSym]) : AclEdit;
+                  //return (!docView.rootDoc._stayInCollection || docView.rootDoc.isInkMask) &&
+                  return (collectionAcl === AclAdmin || collectionAcl === AclEdit || GetEffectiveAcl(docView.rootDoc) === AclAdmin);
+            });
+      }
+      @computed get hasIcons() {
+            return SelectionManager.Views().some(docView => docView.rootDoc.layoutKey === "layout_icon");
+      }
+
+      render() {
+            const bounds = this.Bounds;
+            const seldoc = SelectionManager.Views().slice(-1)[0];
+            if (SnappingManager.GetIsDragging() || bounds.r - bounds.x < 1 || bounds.x === Number.MAX_VALUE || !seldoc || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) {
+                  return (null);
             }
-            return this._accumulatedTitle;
-        }
-        return SelectionManager.Views().length > 1 ? "-multiple-" : "-unset-";
-    }
-
-    @computed get canDelete() {
-        return SelectionManager.Views().some(docView => {
-            if (docView.rootDoc.stayInCollection) return false;
-            const collectionAcl = docView.props.ContainingCollectionView ? GetEffectiveAcl(docView.props.ContainingCollectionDoc?.[DataSym]) : AclEdit;
-            //return (!docView.rootDoc._stayInCollection || docView.rootDoc.isInkMask) &&
-            return (collectionAcl === AclAdmin || collectionAcl === AclEdit || GetEffectiveAcl(docView.rootDoc) === AclAdmin);
-        });
-    }
-    @computed get hasIcons() {
-        return SelectionManager.Views().some(docView => docView.rootDoc.layoutKey === "layout_icon");
-    }
-
-    render() {
-        const bounds = this.Bounds;
-        const seldoc = SelectionManager.Views().slice(-1)[0];
-        if (SnappingManager.GetIsDragging() || bounds.r - bounds.x < 1 || bounds.x === Number.MAX_VALUE || !seldoc || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) {
-            return (null);
-        }
-        const hideResizers = seldoc.props.hideResizeHandles || seldoc.rootDoc.hideResizeHandles || seldoc.rootDoc._isGroup;
-        const hideTitle = seldoc.props.hideDecorationTitle || seldoc.rootDoc.hideDecorationTitle;
-        const canOpen = SelectionManager.Views().some(docView => !docView.props.Document._stayInCollection && !docView.props.Document.isGroup && !docView.props.Document.hideOpenButton);
-        const canDelete = this.canDelete;
-        const topBtn = (key: string, icon: string, pointerDown: undefined | ((e: React.PointerEvent) => void), click: undefined | ((e: any) => void), title: string) => (
-            <Tooltip key={key} title={<div className="dash-tooltip">{title}</div>} placement="top">
-                <div className={`documentDecorations-${key}Button`} onContextMenu={e => e.preventDefault()}
-                    onPointerDown={pointerDown ?? (e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(e => click!(e))))} >
-                    <FontAwesomeIcon icon={icon as any} />
-                </div>
-            </Tooltip>);
-
-        const colorScheme = StrCast(CurrentUserUtils.ActiveDashboard?.colorScheme);
-        const titleArea = hideTitle ? <div className="documentDecorations-title" onPointerDown={this.onTitleDown} key="title" /> :
-            this._edtingTitle ?
-                <input ref={this._keyinput} className={`documentDecorations-title${colorScheme}`}
-                    type="text" name="dynbox" autoComplete="on"
-                    value={this._accumulatedTitle}
-                    onBlur={e => this.titleBlur()}
-                    onChange={action(e => this._accumulatedTitle = e.target.value)}
-                    onKeyDown={this.titleEntered} /> :
-                <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown} >
-                    <span className={`documentDecorations-titleSpan${colorScheme}`}>{`${this.selectionTitle}`}</span>
-                </div>;
-
-
-        const leftBounds = this.props.boundsLeft;
-        const topBounds = LightboxView.LightboxDoc ? 0 : this.props.boundsTop;
-        bounds.x = Math.max(leftBounds, bounds.x - this._resizeBorderWidth / 2) + this._resizeBorderWidth / 2;
-        bounds.y = Math.max(topBounds, bounds.y - this._resizeBorderWidth / 2 - this._titleHeight) + this._resizeBorderWidth / 2 + this._titleHeight;
-        const borderRadiusDraggerWidth = 15;
-        bounds.r = Math.max(bounds.x, Math.max(leftBounds, Math.min(window.innerWidth, bounds.r + borderRadiusDraggerWidth + this._resizeBorderWidth / 2) - this._resizeBorderWidth / 2 - borderRadiusDraggerWidth));
-        bounds.b = Math.max(bounds.y, Math.max(topBounds, Math.min(window.innerHeight, bounds.b + this._resizeBorderWidth / 2 + this._linkBoxHeight) - this._resizeBorderWidth / 2 - this._linkBoxHeight));
-
-        const useRotation = seldoc.ComponentView instanceof InkingStroke || seldoc.ComponentView instanceof ImageBox;
-        const resizerScheme = colorScheme ? "documentDecorations-resizer" + colorScheme : "";
-
-        const rotation = NumCast(seldoc.rootDoc._jitterRotation);
-
-        return (<div className={`documentDecorations${colorScheme}`}>
-            <div className="documentDecorations-background" style={{
-                transform: `rotate(${rotation}deg)`,
-                transformOrigin: "top  left",
-                width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
-                height: (bounds.b - bounds.y + this._resizeBorderWidth) + "px",
-                left: bounds.x - this._resizeBorderWidth / 2,
-                top: bounds.y - this._resizeBorderWidth / 2,
-                pointerEvents: DocumentDecorations.Instance.AddToSelection || this.Interacting ? "none" : "all",
-                display: SelectionManager.Views().length <= 1 ? "none" : undefined
-            }} onPointerDown={this.onBackgroundDown} onContextMenu={e => { e.preventDefault(); e.stopPropagation(); }} />
-            {bounds.r - bounds.x < 15 && bounds.b - bounds.y < 15 ? (null) : <>
-                <div className="documentDecorations-container" key="container" style={{
-                    transform: ` translate(${bounds.x - this._resizeBorderWidth / 2}px, ${bounds.y - this._resizeBorderWidth / 2 - this._titleHeight}px) rotate(${rotation}deg)`,
-                    transformOrigin: `8px 26px`,
-                    width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
-                    height: (bounds.b - bounds.y + this._resizeBorderWidth + this._titleHeight) + "px",
-                }}>
-                    {!canDelete ? <div /> : topBtn("close", this.hasIcons ? "times" : "window-maximize", undefined, e => this.onCloseClick(this.hasIcons ? true : undefined), "Close")}
-                    {titleArea}
-                    {!canOpen ? (null) : topBtn("open", "external-link-alt", this.onMaximizeDown, undefined, "Open in Tab (ctrl: as alias, shift: in new collection)")}
-                    {hideResizers ? (null) :
-                        <>
-                            <div key="tl" className={`documentDecorations-topLeftResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
-                            <div key="t" className={`documentDecorations-topResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
-                            <div key="tr" className={`documentDecorations-topRightResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
-                            <div key="l" className={`documentDecorations-leftResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
-                            <div key="c" className={`documentDecorations-centerCont ${resizerScheme}`}></div>
-                            <div key="r" className={`documentDecorations-rightResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
-                            <div key="bl" className={`documentDecorations-bottomLeftResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
-                            <div key="b" className={`documentDecorations-bottomResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
-                            <div key="br" className={`documentDecorations-bottomRightResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
-
-                            {seldoc.props.renderDepth <= 1 || !seldoc.props.ContainingCollectionView ? (null) :
-                                topBtn("selector", "arrow-alt-circle-up", undefined, this.onSelectorClick, "tap to select containing document")}
-                            <div key="rot" className={`documentDecorations-${useRotation ? "rotation" : "borderRadius"}`}
-                                onPointerDown={useRotation ? this.onRotateDown : this.onRadiusDown}
-                                onContextMenu={e => e.preventDefault()}>{useRotation && "⟲"}</div>
-                        </>
-                    }
-                    {seldoc?.Document.type === DocumentType.FONTICON ? (null) :
-                        <div className="link-button-container" key="links"
-                            style={{
-                                transform: ` translate(${- this._resizeBorderWidth / 2 + 10}px, ${this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `,
-                            }}>
-                            <DocumentButtonBar views={SelectionManager.Views} />
-                        </div>}
-                </div >
-            </>}
-        </div >
-        );
-    }
+            // hide the decorations if the parent chooses to hide it or if the document itself hides it
+            const hideResizers = seldoc.props.hideResizeHandles || seldoc.rootDoc.hideResizeHandles || seldoc.rootDoc._isGroup;
+            const hideTitle = seldoc.props.hideDecorationTitle || seldoc.rootDoc.hideDecorationTitle;
+            const hideDocumentButtonBar = seldoc.props.hideDocumentButtonBar || seldoc.rootDoc.hideDocumentButtonBar;
+            // if multiple documents have been opened at the same time, then don't show open button
+            const canOpen = SelectionManager.Views().some(docView => !docView.props.Document._stayInCollection && !docView.props.Document.isGroup && !docView.props.Document.hideOpenButton);
+            const canDelete = this.canDelete;
+            const topBtn = (key: string, icon: string, pointerDown: undefined | ((e: React.PointerEvent) => void), click: undefined | ((e: any) => void), title: string) => (
+                  <Tooltip key={key} title={<div className="dash-tooltip">{title}</div>} placement="top">
+                        <div className={`documentDecorations-${key}Button`} onContextMenu={e => e.preventDefault()}
+                              onPointerDown={pointerDown ?? (e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(e => click!(e))))} >
+                              <FontAwesomeIcon icon={icon as any} />
+                        </div>
+                  </Tooltip>);
+
+            const colorScheme = StrCast(CurrentUserUtils.ActiveDashboard?.colorScheme);
+            const titleArea = hideTitle ? <div className="documentDecorations-title" onPointerDown={this.onTitleDown} key="title" /> :
+                  this._edtingTitle ?
+                        <input ref={this._keyinput} className={`documentDecorations-title${colorScheme}`}
+                              type="text" name="dynbox" autoComplete="on"
+                              value={this._accumulatedTitle}
+                              onBlur={e => this.titleBlur()}
+                              onChange={action(e => this._accumulatedTitle = e.target.value)}
+                              onKeyDown={this.titleEntered} /> :
+                        <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown} >
+                              <span className={`documentDecorations-titleSpan${colorScheme}`}>{`${this.selectionTitle}`}</span>
+                        </div>;
+
+
+            const leftBounds = this.props.boundsLeft;
+            const topBounds = LightboxView.LightboxDoc ? 0 : this.props.boundsTop;
+            bounds.x = Math.max(leftBounds, bounds.x - this._resizeBorderWidth / 2) + this._resizeBorderWidth / 2;
+            bounds.y = Math.max(topBounds, bounds.y - this._resizeBorderWidth / 2 - this._titleHeight) + this._resizeBorderWidth / 2 + this._titleHeight;
+            const borderRadiusDraggerWidth = 15;
+            bounds.r = Math.max(bounds.x, Math.max(leftBounds, Math.min(window.innerWidth, bounds.r + borderRadiusDraggerWidth + this._resizeBorderWidth / 2) - this._resizeBorderWidth / 2 - borderRadiusDraggerWidth));
+            bounds.b = Math.max(bounds.y, Math.max(topBounds, Math.min(window.innerHeight, bounds.b + this._resizeBorderWidth / 2 + this._linkBoxHeight) - this._resizeBorderWidth / 2 - this._linkBoxHeight));
+
+            const useRotation = seldoc.ComponentView instanceof InkingStroke || seldoc.ComponentView instanceof ImageBox;
+            const resizerScheme = colorScheme ? "documentDecorations-resizer" + colorScheme : "";
+
+            const rotation = NumCast(seldoc.rootDoc._jitterRotation);
+
+            return (<div className={`documentDecorations${colorScheme}`}>
+                  <div className="documentDecorations-background" style={{
+                        transform: `rotate(${rotation}deg)`,
+                        transformOrigin: "top  left",
+                        width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
+                        height: (bounds.b - bounds.y + this._resizeBorderWidth) + "px",
+                        left: bounds.x - this._resizeBorderWidth / 2,
+                        top: bounds.y - this._resizeBorderWidth / 2,
+                        pointerEvents: DocumentDecorations.Instance.AddToSelection || this.Interacting ? "none" : "all",
+                        display: SelectionManager.Views().length <= 1 ? "none" : undefined
+                  }} onPointerDown={this.onBackgroundDown} onContextMenu={e => { e.preventDefault(); e.stopPropagation(); }} />
+                  {bounds.r - bounds.x < 15 && bounds.b - bounds.y < 15 ? (null) : <>
+                        <div className="documentDecorations-container" key="container" style={{
+                              transform: ` translate(${bounds.x - this._resizeBorderWidth / 2}px, ${bounds.y - this._resizeBorderWidth / 2 - this._titleHeight}px) rotate(${rotation}deg)`,
+                              transformOrigin: `8px 26px`,
+                              width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
+                              height: (bounds.b - bounds.y + this._resizeBorderWidth + this._titleHeight) + "px",
+                        }}>
+                              {!canDelete ? <div /> : topBtn("close", this.hasIcons ? "times" : "window-maximize", undefined, e => this.onCloseClick(this.hasIcons ? true : undefined), "Close")}
+                              {titleArea}
+                              {!canOpen ? (null) : topBtn("open", "external-link-alt", this.onMaximizeDown, undefined, "Open in Tab (ctrl: as alias, shift: in new collection)")}
+                              {hideResizers ? (null) :
+                                    <>
+                                          <div key="tl" className={`documentDecorations-topLeftResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
+                                          <div key="t" className={`documentDecorations-topResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
+                                          <div key="tr" className={`documentDecorations-topRightResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
+                                          <div key="l" className={`documentDecorations-leftResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
+                                          <div key="c" className={`documentDecorations-centerCont ${resizerScheme}`}></div>
+                                          <div key="r" className={`documentDecorations-rightResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
+                                          <div key="bl" className={`documentDecorations-bottomLeftResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
+                                          <div key="b" className={`documentDecorations-bottomResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
+                                          <div key="br" className={`documentDecorations-bottomRightResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
+
+                                          {seldoc.props.renderDepth <= 1 || !seldoc.props.ContainingCollectionView ? (null) :
+                                                topBtn("selector", "arrow-alt-circle-up", undefined, this.onSelectorClick, "tap to select containing document")}
+                                          <div key="rot" className={`documentDecorations-${useRotation ? "rotation" : "borderRadius"}`}
+                                                onPointerDown={useRotation ? this.onRotateDown : this.onRadiusDown}
+                                                onContextMenu={e => e.preventDefault()}>{useRotation && "⟲"}</div>
+                                    </>
+                              }
+
+                              {hideDocumentButtonBar ? (null) :
+                                    <div className="link-button-container" key="links"
+                                          style={{
+                                                transform: ` translate(${- this._resizeBorderWidth / 2 + 10}px, ${this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `,
+                                          }}>
+                                          <DocumentButtonBar views={SelectionManager.Views} />
+                                    </div>}
+                        </div >
+                  </>}
+            </div >
+            );
+      }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 373e3ee57..96c989e77 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -54,1344 +54,1345 @@ import { FieldViewProps } from "./FieldView";
 const { Howl } = require('howler');
 
 interface Window {
-    MediaRecorder: MediaRecorder;
+      MediaRecorder: MediaRecorder;
 }
 
 declare class MediaRecorder {
-    // whatever MediaRecorder has
-    constructor(e: any);
+      // whatever MediaRecorder has
+      constructor(e: any);
 }
 
 export enum ViewAdjustment {
-    resetView = 1,
-    doNothing = 0
+      resetView = 1,
+      doNothing = 0
 }
 
 export const ViewSpecPrefix = "viewSpec";  // field prefix for anchor fields that are immediately copied over to the target document when link is followed.  Other anchor properties will be copied over in the specific setViewSpec() method on their view (which allows for seting preview values instead of writing to the document)
 
 export interface DocFocusOptions {
-    originalTarget?: Doc; // set in JumpToDocument, used by TabDocView to determine whether to fit contents to tab
-    willZoom?: boolean;   // determines whether to zoom in on target document
-    scale?: number;       // percent of containing frame to zoom into document
-    afterFocus?: DocAfterFocusFunc;  // function to call after focusing on a document
-    docTransform?: Transform; // when a document can't be panned and zoomed within its own container (say a group), then we need to continue to move up the render hierarchy to find something that can pan and zoom.  when this happens the docTransform must accumulate all the transforms of each level of the hierarchy
-    instant?: boolean; // whether focus should happen instantly (as opposed to smooth zoom)
+      originalTarget?: Doc; // set in JumpToDocument, used by TabDocView to determine whether to fit contents to tab
+      willZoom?: boolean;   // determines whether to zoom in on target document
+      scale?: number;       // percent of containing frame to zoom into document
+      afterFocus?: DocAfterFocusFunc;  // function to call after focusing on a document
+      docTransform?: Transform; // when a document can't be panned and zoomed within its own container (say a group), then we need to continue to move up the render hierarchy to find something that can pan and zoom.  when this happens the docTransform must accumulate all the transforms of each level of the hierarchy
+      instant?: boolean; // whether focus should happen instantly (as opposed to smooth zoom)
 }
 export type DocAfterFocusFunc = (notFocused: boolean) => Promise<ViewAdjustment>;
 export type DocFocusFunc = (doc: Doc, options?: DocFocusOptions) => void;
 export type StyleProviderFunc = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string) => any;
 export interface DocComponentView {
-    updateIcon?: () => void; // updates the icon representation of the document
-    getAnchor?: () => Doc; // returns an Anchor Doc that represents the current state of the doc's componentview (e.g., the current playhead location of a an audio/video box)
-    scrollFocus?: (doc: Doc, smooth: boolean) => Opt<number>; // returns the duration of the focus
-    setViewSpec?: (anchor: Doc, preview: boolean) => void;  // sets viewing information for a componentview, typically when following a link. 'preview' tells the view to use the values without writing to the document
-    reverseNativeScaling?: () => boolean; // DocumentView's setup screenToLocal based on the doc having a nativeWidth/Height.  However, some content views (e.g., FreeFormView w/ fitToBox set) may ignore the native dimensions so this flags the DocumentView to not do Nativre scaling.
-    shrinkWrap?: () => void;  // requests a document to display all of its contents with no white space.  currently only implemented (needed?) for freeform views
-    menuControls?: () => JSX.Element; // controls to display in the top menu bar when the document is selected.
-    isAnyChildContentActive?: () => boolean; // is any child content of the document active
-    getKeyFrameEditing?: () => boolean; // whether the document is in keyframe editing mode (if it is, then all hidden documents that are not active at the keyframe time will still be shown)
-    setKeyFrameEditing?: (set: boolean) => void; // whether the document is in keyframe editing mode (if it is, then all hidden documents that are not active at the keyframe time will still be shown)
-    playFrom?: (time: number, endTime?: number) => void;
-    Pause?: () => void;
-    setFocus?: () => void;
-    componentUI?: (boundsLeft: number, boundsTop: number) => JSX.Element | null;
-    fieldKey?: string;
-    annotationKey?: string;
-    getTitle?: () => string;
-    getScrollHeight?: () => number;
-    getCenter?: (xf: Transform) => { X: number, Y: number };
-    ptToScreen?: (pt: { X: number, Y: number }) => { X: number, Y: number };
-    ptFromScreen?: (pt: { X: number, Y: number }) => { X: number, Y: number };
-    snapPt?: (pt: { X: number, Y: number }, excludeSegs?: number[]) => { nearestPt: { X: number, Y: number }, distance: number };
-    search?: (str: string, bwd?: boolean, clear?: boolean) => boolean;
+      updateIcon?: () => void; // updates the icon representation of the document
+      getAnchor?: () => Doc; // returns an Anchor Doc that represents the current state of the doc's componentview (e.g., the current playhead location of a an audio/video box)
+      scrollFocus?: (doc: Doc, smooth: boolean) => Opt<number>; // returns the duration of the focus
+      setViewSpec?: (anchor: Doc, preview: boolean) => void;  // sets viewing information for a componentview, typically when following a link. 'preview' tells the view to use the values without writing to the document
+      reverseNativeScaling?: () => boolean; // DocumentView's setup screenToLocal based on the doc having a nativeWidth/Height.  However, some content views (e.g., FreeFormView w/ fitToBox set) may ignore the native dimensions so this flags the DocumentView to not do Nativre scaling.
+      shrinkWrap?: () => void;  // requests a document to display all of its contents with no white space.  currently only implemented (needed?) for freeform views
+      menuControls?: () => JSX.Element; // controls to display in the top menu bar when the document is selected.
+      isAnyChildContentActive?: () => boolean; // is any child content of the document active
+      getKeyFrameEditing?: () => boolean; // whether the document is in keyframe editing mode (if it is, then all hidden documents that are not active at the keyframe time will still be shown)
+      setKeyFrameEditing?: (set: boolean) => void; // whether the document is in keyframe editing mode (if it is, then all hidden documents that are not active at the keyframe time will still be shown)
+      playFrom?: (time: number, endTime?: number) => void;
+      Pause?: () => void;
+      setFocus?: () => void;
+      componentUI?: (boundsLeft: number, boundsTop: number) => JSX.Element | null;
+      fieldKey?: string;
+      annotationKey?: string;
+      getTitle?: () => string;
+      getScrollHeight?: () => number;
+      getCenter?: (xf: Transform) => { X: number, Y: number };
+      ptToScreen?: (pt: { X: number, Y: number }) => { X: number, Y: number };
+      ptFromScreen?: (pt: { X: number, Y: number }) => { X: number, Y: number };
+      snapPt?: (pt: { X: number, Y: number }, excludeSegs?: number[]) => { nearestPt: { X: number, Y: number }, distance: number };
+      search?: (str: string, bwd?: boolean, clear?: boolean) => boolean;
 }
 // These props are passed to both FieldViews and DocumentViews 
 export interface DocumentViewSharedProps {
-    fieldKey?: string; // only used by FieldViews but helpful here to allow styleProviders to access fieldKey of FieldViewProps.  In priniciple, passing a fieldKey to a documentView could override or be the default fieldKey for fieldViews
-    DocumentView?: () => DocumentView;
-    renderDepth: number;
-    Document: Doc;
-    DataDoc?: Doc;
-    fitContentsToDoc?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _fitToBox property on a Document
-    ContainingCollectionView: Opt<CollectionView>;
-    ContainingCollectionDoc: Opt<Doc>;
-    suppressSetHeight?: boolean;
-    thumbShown?: () => boolean;
-    isHovering?: () => boolean;
-    setContentView?: (view: DocComponentView) => any;
-    CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView;
-    PanelWidth: () => number;
-    PanelHeight: () => number;
-    docViewPath: () => DocumentView[];
-    childHideDecorationTitle?: () => boolean;
-    childHideResizeHandles?: () => boolean;
-    dataTransition?: string; // specifies animation transition - used by collectionPile and potentially other layout engines when changing the size of documents so that the change won't be abrupt
-    styleProvider: Opt<StyleProviderFunc>;
-    focus: DocFocusFunc;
-    fitWidth?: (doc: Doc) => boolean;
-    docFilters: () => string[];
-    docRangeFilters: () => string[];
-    searchFilterDocs: () => Doc[];
-    showTitle?: () => string;
-    whenChildContentsActiveChanged: (isActive: boolean) => void;
-    rootSelected: (outsideReaction?: boolean) => boolean; // whether the root of a template has been selected
-    addDocTab: (doc: Doc, where: string) => boolean;
-    filterAddDocument?: (doc: Doc[]) => boolean;  // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example)
-    addDocument?: (doc: Doc | Doc[]) => boolean;
-    removeDocument?: (doc: Doc | Doc[]) => boolean;
-    moveDocument?: (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean;
-    pinToPres: (document: Doc) => void;
-    ScreenToLocalTransform: () => Transform;
-    bringToFront: (doc: Doc, sendToBack?: boolean) => void;
-    dropAction?: dropActionType;
-    dontRegisterView?: boolean;
-    hideLinkButton?: boolean;
-    hideCaptions?: boolean;
-    ignoreAutoHeight?: boolean;
-    forceAutoHeight?: boolean;
-    disableDocBrushing?: boolean; // should highlighting for this view be disabled when same document in another view is hovered over.
-    pointerEvents?: () => Opt<string>;
-    scriptContext?: any; // can be assigned anything and will be passed as 'scriptContext' to any OnClick script that executes on this document
-    createNewFilterDoc?: () => void;
-    updateFilterDoc?: (doc: Doc) => void;
+      fieldKey?: string; // only used by FieldViews but helpful here to allow styleProviders to access fieldKey of FieldViewProps.  In priniciple, passing a fieldKey to a documentView could override or be the default fieldKey for fieldViews
+      DocumentView?: () => DocumentView;
+      renderDepth: number;
+      Document: Doc;
+      DataDoc?: Doc;
+      fitContentsToDoc?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _fitToBox property on a Document
+      ContainingCollectionView: Opt<CollectionView>;
+      ContainingCollectionDoc: Opt<Doc>;
+      suppressSetHeight?: boolean;
+      thumbShown?: () => boolean;
+      isHovering?: () => boolean;
+      setContentView?: (view: DocComponentView) => any;
+      CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView;
+      PanelWidth: () => number;
+      PanelHeight: () => number;
+      docViewPath: () => DocumentView[];
+      childHideDecorationTitle?: () => boolean;
+      childHideResizeHandles?: () => boolean;
+      dataTransition?: string; // specifies animation transition - used by collectionPile and potentially other layout engines when changing the size of documents so that the change won't be abrupt
+      styleProvider: Opt<StyleProviderFunc>;
+      focus: DocFocusFunc;
+      fitWidth?: (doc: Doc) => boolean;
+      docFilters: () => string[];
+      docRangeFilters: () => string[];
+      searchFilterDocs: () => Doc[];
+      showTitle?: () => string;
+      whenChildContentsActiveChanged: (isActive: boolean) => void;
+      rootSelected: (outsideReaction?: boolean) => boolean; // whether the root of a template has been selected
+      addDocTab: (doc: Doc, where: string) => boolean;
+      filterAddDocument?: (doc: Doc[]) => boolean;  // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example)
+      addDocument?: (doc: Doc | Doc[]) => boolean;
+      removeDocument?: (doc: Doc | Doc[]) => boolean;
+      moveDocument?: (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean;
+      pinToPres: (document: Doc) => void;
+      ScreenToLocalTransform: () => Transform;
+      bringToFront: (doc: Doc, sendToBack?: boolean) => void;
+      dropAction?: dropActionType;
+      dontRegisterView?: boolean;
+      hideLinkButton?: boolean;
+      hideCaptions?: boolean;
+      ignoreAutoHeight?: boolean;
+      forceAutoHeight?: boolean;
+      disableDocBrushing?: boolean; // should highlighting for this view be disabled when same document in another view is hovered over.
+      pointerEvents?: () => Opt<string>;
+      scriptContext?: any; // can be assigned anything and will be passed as 'scriptContext' to any OnClick script that executes on this document
+      createNewFilterDoc?: () => void;
+      updateFilterDoc?: (doc: Doc) => void;
 }
 
 // these props are specific to DocuentViews
 export interface DocumentViewProps extends DocumentViewSharedProps {
-    // properties specific to DocumentViews but not to FieldView
-    freezeDimensions?: boolean;
-    hideResizeHandles?: boolean; // whether to suppress DocumentDecorations when this document is selected
-    hideTitle?: boolean;  // forces suppression of title. e.g, treeView document labels suppress titles in case they are globally active via settings
-    hideDecorationTitle?: boolean;  // forces suppression of title. e.g, treeView document labels suppress titles in case they are globally active via settings
-    treeViewDoc?: Doc;
-    isDocumentActive?: () => boolean | undefined; // whether a document should handle pointer events
-    isContentActive: () => boolean | undefined; // whether document contents should handle pointer events
-    contentPointerEvents?: string; // pointer events allowed for content of a document view.  eg. set to "none" in menuSidebar for sharedDocs so that you can select a document, but not interact with its contents
-    radialMenu?: String[];
-    LayoutTemplateString?: string;
-    dontCenter?: "x" | "y" | "xy";
-    dontScaleFilter?: (doc: Doc) => boolean; // decides whether a document can be scaled to fit its container vs native size with scrolling
-    ContentScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal
-    NativeWidth?: () => number;
-    NativeHeight?: () => number;
-    LayoutTemplate?: () => Opt<Doc>;
-    contextMenuItems?: () => { script: ScriptField, filter?: ScriptField, label: string, icon: string }[];
-    onClick?: () => ScriptField;
-    onDoubleClick?: () => ScriptField;
-    onPointerDown?: () => ScriptField;
-    onPointerUp?: () => ScriptField;
-    onBrowseClick?: () => (ScriptField | undefined);
-    onKey?: (e: React.KeyboardEvent, fieldProps: FieldViewProps) => (boolean | undefined);
+      // properties specific to DocumentViews but not to FieldView
+      freezeDimensions?: boolean;
+      hideResizeHandles?: boolean; // whether to suppress DocumentDecorations when this document is selected
+      hideTitle?: boolean;  // forces suppression of title. e.g, treeView document labels suppress titles in case they are globally active via settings
+      hideDecorationTitle?: boolean;  // forces suppression of title. e.g, treeView document labels suppress titles in case they are globally active via settings
+      hideDocumentButtonBar?: boolean;
+      treeViewDoc?: Doc;
+      isDocumentActive?: () => boolean | undefined; // whether a document should handle pointer events
+      isContentActive: () => boolean | undefined; // whether document contents should handle pointer events
+      contentPointerEvents?: string; // pointer events allowed for content of a document view.  eg. set to "none" in menuSidebar for sharedDocs so that you can select a document, but not interact with its contents
+      radialMenu?: String[];
+      LayoutTemplateString?: string;
+      dontCenter?: "x" | "y" | "xy";
+      dontScaleFilter?: (doc: Doc) => boolean; // decides whether a document can be scaled to fit its container vs native size with scrolling
+      ContentScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal
+      NativeWidth?: () => number;
+      NativeHeight?: () => number;
+      LayoutTemplate?: () => Opt<Doc>;
+      contextMenuItems?: () => { script: ScriptField, filter?: ScriptField, label: string, icon: string }[];
+      onClick?: () => ScriptField;
+      onDoubleClick?: () => ScriptField;
+      onPointerDown?: () => ScriptField;
+      onPointerUp?: () => ScriptField;
+      onBrowseClick?: () => (ScriptField | undefined);
+      onKey?: (e: React.KeyboardEvent, fieldProps: FieldViewProps) => (boolean | undefined);
 }
 
 // these props are only available in DocumentViewIntenral
 export interface DocumentViewInternalProps extends DocumentViewProps {
-    NativeWidth: () => number;
-    NativeHeight: () => number;
-    isSelected: (outsideReaction?: boolean) => boolean;
-    select: (ctrlPressed: boolean) => void;
-    DocumentView: () => DocumentView;
-    viewPath: () => DocumentView[];
+      NativeWidth: () => number;
+      NativeHeight: () => number;
+      isSelected: (outsideReaction?: boolean) => boolean;
+      select: (ctrlPressed: boolean) => void;
+      DocumentView: () => DocumentView;
+      viewPath: () => DocumentView[];
 }
 
 @observer
 export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps>() {
-    public static SelectAfterContextMenu = true; //  whether a document should be selected after it's contextmenu is triggered.
-    _animateScaleTime = 300; // milliseconds;
-    @observable _animateScalingTo = 0;
-    @observable _mediaState = 0;
-    @observable _pendingDoubleClick = false;
-    private _disposers: { [name: string]: IReactionDisposer } = {};
-    private _downX: number = 0;
-    private _downY: number = 0;
-    private _firstX: number = -1;
-    private _firstY: number = -1;
-    private _lastTap: number = 0;
-    private _doubleTap = false;
-    private _mainCont = React.createRef<HTMLDivElement>();
-    private _titleRef = React.createRef<EditableView>();
-    private _timeout: NodeJS.Timeout | undefined;
-    private _dropDisposer?: DragManager.DragDropDisposer;
-    private _holdDisposer?: InteractionUtils.MultiTouchEventDisposer;
-    protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
-    @observable _componentView: Opt<DocComponentView>; // needs to be accessed from DocumentView wrapper class
-
-    private get topMost() { return this.props.renderDepth === 0 && !LightboxView.LightboxDoc; }
-    public get displayName() { return "DocumentView(" + this.props.Document.title + ")"; } // this makes mobx trace() statements more descriptive
-    public get ContentDiv() { return this._mainCont.current; }
-    public get LayoutFieldKey() { return Doc.LayoutFieldKey(this.layoutDoc); }
-    @computed get ShowTitle() { return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.ShowTitle) as (Opt<string>); }
-    @computed get ContentScale() { return this.props.ContentScaling?.() || 1; }
-    @computed get thumb() { return ImageCast(this.layoutDoc["thumb-frozen"], ImageCast(this.layoutDoc.thumb))?.url.href.replace(".png", "_m.png"); }
-    @computed get hidden() { return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Hidden); }
-    @computed get opacity() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Opacity); }
-    @computed get boxShadow() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BoxShadow); }
-    @computed get borderRounding() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BorderRounding); }
-    @computed get hideLinkButton() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HideLinkButton + (this.props.isSelected() ? ":selected" : "")); }
-    @computed get widgetDecorations() { return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Decorations + (this.props.isSelected() ? ":selected" : "")); }
-    @computed get backgroundColor() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor); }
-    @computed get docContents() { return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.DocContents); }
-    @computed get headerMargin() { return this.props?.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin) || 0; }
-    @computed get titleHeight() { return this.props?.styleProvider?.(this.layoutDoc, this.props, StyleProp.TitleHeight) || 0; }
-    @computed get pointerEvents() { return this.props.styleProvider?.(this.Document, this.props, StyleProp.PointerEvents + (this.props.isSelected() ? ":selected" : "")); }
-    @computed get finalLayoutKey() { return StrCast(this.Document.layoutKey, "layout"); }
-    @computed get nativeWidth() { return this.props.NativeWidth(); }
-    @computed get nativeHeight() { return this.props.NativeHeight(); }
-    @computed get onClickHandler() { return this.props.onClick?.() ?? (this.props.onBrowseClick?.() ?? Cast(this.Document.onClick, ScriptField, Cast(this.layoutDoc.onClick, ScriptField, null))); }
-    @computed get onDoubleClickHandler() { return this.props.onDoubleClick?.() ?? (Cast(this.layoutDoc.onDoubleClick, ScriptField, null) ?? this.Document.onDoubleClick); }
-    @computed get onPointerDownHandler() { return this.props.onPointerDown?.() ?? ScriptCast(this.Document.onPointerDown); }
-    @computed get onPointerUpHandler() { return this.props.onPointerUp?.() ?? ScriptCast(this.Document.onPointerUp); }
-
-
-    componentWillUnmount() { this.cleanupHandlers(true); }
-    componentDidMount() { this.setupHandlers(); }
-    //componentDidUpdate() { this.setupHandlers(); }
-    setupHandlers() {
-        this.cleanupHandlers(false);
-        if (this._mainCont.current) {
-            this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this), this.props.Document);
-            this._multiTouchDisposer = InteractionUtils.MakeMultiTouchTarget(this._mainCont.current, this.onTouchStart.bind(this));
-            this._holdDisposer = InteractionUtils.MakeHoldTouchTarget(this._mainCont.current, this.handle1PointerHoldStart.bind(this));
-        }
-    }
-    @action
-    cleanupHandlers(unbrush: boolean) {
-        this._dropDisposer?.();
-        this._multiTouchDisposer?.();
-        this._holdDisposer?.();
-        unbrush && Doc.UnBrushDoc(this.props.Document);
-        Object.values(this._disposers).forEach(disposer => disposer?.());
-    }
-
-    handle1PointerHoldStart = (e: Event, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>): any => {
-        this.removeMoveListeners();
-        this.removeEndListeners();
-        document.removeEventListener("pointermove", this.onPointerMove);
-        document.removeEventListener("pointerup", this.onPointerUp);
-        if (RadialMenu.Instance._display === false) {
-            this.addHoldMoveListeners();
-            this.addHoldEndListeners();
-            this.onRadialMenu(e, me);
+      public static SelectAfterContextMenu = true; //  whether a document should be selected after it's contextmenu is triggered.
+      _animateScaleTime = 300; // milliseconds;
+      @observable _animateScalingTo = 0;
+      @observable _mediaState = 0;
+      @observable _pendingDoubleClick = false;
+      private _disposers: { [name: string]: IReactionDisposer } = {};
+      private _downX: number = 0;
+      private _downY: number = 0;
+      private _firstX: number = -1;
+      private _firstY: number = -1;
+      private _lastTap: number = 0;
+      private _doubleTap = false;
+      private _mainCont = React.createRef<HTMLDivElement>();
+      private _titleRef = React.createRef<EditableView>();
+      private _timeout: NodeJS.Timeout | undefined;
+      private _dropDisposer?: DragManager.DragDropDisposer;
+      private _holdDisposer?: InteractionUtils.MultiTouchEventDisposer;
+      protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
+      @observable _componentView: Opt<DocComponentView>; // needs to be accessed from DocumentView wrapper class
+
+      private get topMost() { return this.props.renderDepth === 0 && !LightboxView.LightboxDoc; }
+      public get displayName() { return "DocumentView(" + this.props.Document.title + ")"; } // this makes mobx trace() statements more descriptive
+      public get ContentDiv() { return this._mainCont.current; }
+      public get LayoutFieldKey() { return Doc.LayoutFieldKey(this.layoutDoc); }
+      @computed get ShowTitle() { return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.ShowTitle) as (Opt<string>); }
+      @computed get ContentScale() { return this.props.ContentScaling?.() || 1; }
+      @computed get thumb() { return ImageCast(this.layoutDoc["thumb-frozen"], ImageCast(this.layoutDoc.thumb))?.url.href.replace(".png", "_m.png"); }
+      @computed get hidden() { return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Hidden); }
+      @computed get opacity() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Opacity); }
+      @computed get boxShadow() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BoxShadow); }
+      @computed get borderRounding() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BorderRounding); }
+      @computed get hideLinkButton() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HideLinkButton + (this.props.isSelected() ? ":selected" : "")); }
+      @computed get widgetDecorations() { return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Decorations + (this.props.isSelected() ? ":selected" : "")); }
+      @computed get backgroundColor() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor); }
+      @computed get docContents() { return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.DocContents); }
+      @computed get headerMargin() { return this.props?.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin) || 0; }
+      @computed get titleHeight() { return this.props?.styleProvider?.(this.layoutDoc, this.props, StyleProp.TitleHeight) || 0; }
+      @computed get pointerEvents() { return this.props.styleProvider?.(this.Document, this.props, StyleProp.PointerEvents + (this.props.isSelected() ? ":selected" : "")); }
+      @computed get finalLayoutKey() { return StrCast(this.Document.layoutKey, "layout"); }
+      @computed get nativeWidth() { return this.props.NativeWidth(); }
+      @computed get nativeHeight() { return this.props.NativeHeight(); }
+      @computed get onClickHandler() { return this.props.onClick?.() ?? (this.props.onBrowseClick?.() ?? Cast(this.Document.onClick, ScriptField, Cast(this.layoutDoc.onClick, ScriptField, null))); }
+      @computed get onDoubleClickHandler() { return this.props.onDoubleClick?.() ?? (Cast(this.layoutDoc.onDoubleClick, ScriptField, null) ?? this.Document.onDoubleClick); }
+      @computed get onPointerDownHandler() { return this.props.onPointerDown?.() ?? ScriptCast(this.Document.onPointerDown); }
+      @computed get onPointerUpHandler() { return this.props.onPointerUp?.() ?? ScriptCast(this.Document.onPointerUp); }
+
+
+      componentWillUnmount() { this.cleanupHandlers(true); }
+      componentDidMount() { this.setupHandlers(); }
+      //componentDidUpdate() { this.setupHandlers(); }
+      setupHandlers() {
+            this.cleanupHandlers(false);
+            if (this._mainCont.current) {
+                  this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this), this.props.Document);
+                  this._multiTouchDisposer = InteractionUtils.MakeMultiTouchTarget(this._mainCont.current, this.onTouchStart.bind(this));
+                  this._holdDisposer = InteractionUtils.MakeHoldTouchTarget(this._mainCont.current, this.handle1PointerHoldStart.bind(this));
+            }
+      }
+      @action
+      cleanupHandlers(unbrush: boolean) {
+            this._dropDisposer?.();
+            this._multiTouchDisposer?.();
+            this._holdDisposer?.();
+            unbrush && Doc.UnBrushDoc(this.props.Document);
+            Object.values(this._disposers).forEach(disposer => disposer?.());
+      }
+
+      handle1PointerHoldStart = (e: Event, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>): any => {
+            this.removeMoveListeners();
+            this.removeEndListeners();
+            document.removeEventListener("pointermove", this.onPointerMove);
+            document.removeEventListener("pointerup", this.onPointerUp);
+            if (RadialMenu.Instance._display === false) {
+                  this.addHoldMoveListeners();
+                  this.addHoldEndListeners();
+                  this.onRadialMenu(e, me);
+                  const pt = me.touchEvent.touches[me.touchEvent.touches.length - 1];
+                  this._firstX = pt.pageX;
+                  this._firstY = pt.pageY;
+            }
+      }
+
+      handle1PointerHoldMove = (e: Event, me: InteractionUtils.MultiTouchEvent<TouchEvent>): void => {
             const pt = me.touchEvent.touches[me.touchEvent.touches.length - 1];
-            this._firstX = pt.pageX;
-            this._firstY = pt.pageY;
-        }
-    }
-
-    handle1PointerHoldMove = (e: Event, me: InteractionUtils.MultiTouchEvent<TouchEvent>): void => {
-        const pt = me.touchEvent.touches[me.touchEvent.touches.length - 1];
-
-        if (this._firstX === -1 || this._firstY === -1) {
-            return;
-        }
-        if (Math.abs(pt.pageX - this._firstX) > 150 || Math.abs(pt.pageY - this._firstY) > 150) {
-            this.handle1PointerHoldEnd(e, me);
-        }
-    }
-
-    handle1PointerHoldEnd = (e: Event, me: InteractionUtils.MultiTouchEvent<TouchEvent>): void => {
-        this.removeHoldMoveListeners();
-        this.removeHoldEndListeners();
-        RadialMenu.Instance.closeMenu();
-        this._firstX = -1;
-        this._firstY = -1;
-        SelectionManager.DeselectAll();
-        me.touchEvent.stopPropagation();
-        me.touchEvent.preventDefault();
-        e.stopPropagation();
-        if (RadialMenu.Instance.used) {
-            this.onContextMenu(undefined, me.touches[0].pageX, me.touches[0].pageY);
-        }
-    }
-
-    handle2PointersDown = (e: React.TouchEvent, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>) => {
-        if (!e.nativeEvent.cancelBubble && !this.props.isSelected()) {
+
+            if (this._firstX === -1 || this._firstY === -1) {
+                  return;
+            }
+            if (Math.abs(pt.pageX - this._firstX) > 150 || Math.abs(pt.pageY - this._firstY) > 150) {
+                  this.handle1PointerHoldEnd(e, me);
+            }
+      }
+
+      handle1PointerHoldEnd = (e: Event, me: InteractionUtils.MultiTouchEvent<TouchEvent>): void => {
+            this.removeHoldMoveListeners();
+            this.removeHoldEndListeners();
+            RadialMenu.Instance.closeMenu();
+            this._firstX = -1;
+            this._firstY = -1;
+            SelectionManager.DeselectAll();
+            me.touchEvent.stopPropagation();
+            me.touchEvent.preventDefault();
             e.stopPropagation();
-            e.preventDefault();
+            if (RadialMenu.Instance.used) {
+                  this.onContextMenu(undefined, me.touches[0].pageX, me.touches[0].pageY);
+            }
+      }
 
-            this.removeMoveListeners();
-            this.addMoveListeners();
-            this.removeEndListeners();
-            this.addEndListeners();
-        }
-    }
-
-    handle1PointerDown = (e: React.TouchEvent, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>) => {
-        SelectionManager.DeselectAll();
-        if (this.Document.onPointerDown) return;
-        const touch = me.touchEvent.changedTouches.item(0);
-        if (touch) {
-            this._downX = touch.clientX;
-            this._downY = touch.clientY;
-            if (!e.nativeEvent.cancelBubble) {
-                if ((this.props.isDocumentActive?.() || this.layoutDoc.onDragStart || this.onClickHandler) && !e.ctrlKey && !this.layoutDoc._lockedPosition && !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) e.stopPropagation();
-                this.removeMoveListeners();
-                this.addMoveListeners();
-                this.removeEndListeners();
-                this.addEndListeners();
-                e.stopPropagation();
+      handle2PointersDown = (e: React.TouchEvent, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>) => {
+            if (!e.nativeEvent.cancelBubble && !this.props.isSelected()) {
+                  e.stopPropagation();
+                  e.preventDefault();
+
+                  this.removeMoveListeners();
+                  this.addMoveListeners();
+                  this.removeEndListeners();
+                  this.addEndListeners();
             }
-        }
-    }
+      }
 
-    handle1PointerMove = (e: TouchEvent, me: InteractionUtils.MultiTouchEvent<TouchEvent>) => {
-        if (e.cancelBubble && this.props.isDocumentActive?.()) {
-            this.removeMoveListeners();
-        }
-        else if (!e.cancelBubble && (this.props.isDocumentActive?.() || this.layoutDoc.onDragStart || this.onClickHandler) && !this.layoutDoc._lockedPosition && !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) {
+      handle1PointerDown = (e: React.TouchEvent, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>) => {
+            SelectionManager.DeselectAll();
+            if (this.Document.onPointerDown) return;
             const touch = me.touchEvent.changedTouches.item(0);
-            if (touch && (Math.abs(this._downX - touch.clientX) > 3 || Math.abs(this._downY - touch.clientY) > 3)) {
-                if (!e.altKey && (!this.topMost || this.layoutDoc.onDragStart || this.onClickHandler)) {
-                    this.cleanUpInteractions();
-                    this.startDragging(this._downX, this._downY, this.Document.dropAction ? this.Document.dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined);
-                }
+            if (touch) {
+                  this._downX = touch.clientX;
+                  this._downY = touch.clientY;
+                  if (!e.nativeEvent.cancelBubble) {
+                        if ((this.props.isDocumentActive?.() || this.layoutDoc.onDragStart || this.onClickHandler) && !e.ctrlKey && !this.layoutDoc._lockedPosition && !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) e.stopPropagation();
+                        this.removeMoveListeners();
+                        this.addMoveListeners();
+                        this.removeEndListeners();
+                        this.addEndListeners();
+                        e.stopPropagation();
+                  }
             }
-            e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document'  however it does mark the event as cancelBubble=true which we test for in the move event handlers
-            e.preventDefault();
-        }
-    }
-
-    @action
-    handle2PointersMove = (e: TouchEvent, me: InteractionUtils.MultiTouchEvent<TouchEvent>) => {
-        const myTouches = InteractionUtils.GetMyTargetTouches(me, this.prevPoints, true);
-        const pt1 = myTouches[0];
-        const pt2 = myTouches[1];
-        const oldPoint1 = this.prevPoints.get(pt1.identifier);
-        const oldPoint2 = this.prevPoints.get(pt2.identifier);
-        const pinching = InteractionUtils.Pinning(pt1, pt2, oldPoint1!, oldPoint2!);
-        if (pinching !== 0 && oldPoint1 && oldPoint2) {
-            const dW = (Math.abs(pt1.clientX - pt2.clientX) - Math.abs(oldPoint1.clientX - oldPoint2.clientX));
-            const dH = (Math.abs(pt1.clientY - pt2.clientY) - Math.abs(oldPoint1.clientY - oldPoint2.clientY));
-            const dX = -1 * Math.sign(dW);
-            const dY = -1 * Math.sign(dH);
-
-            if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) {
-                const doc = Document(this.props.Document);
-                const layoutDoc = Document(Doc.Layout(this.props.Document));
-                let nwidth = Doc.NativeWidth(layoutDoc);
-                let nheight = Doc.NativeHeight(layoutDoc);
-                const width = (layoutDoc._width || 0);
-                const height = (layoutDoc._height || (nheight / nwidth * width));
-                const scale = this.props.ScreenToLocalTransform().Scale * this.ContentScale;
-                const actualdW = Math.max(width + (dW * scale), 20);
-                const actualdH = Math.max(height + (dH * scale), 20);
-                doc.x = (doc.x || 0) + dX * (actualdW - width);
-                doc.y = (doc.y || 0) + dY * (actualdH - height);
-                const fixedAspect = e.ctrlKey || (nwidth && nheight);
-                if (fixedAspect && (!nwidth || !nheight)) {
-                    Doc.SetNativeWidth(layoutDoc, nwidth = layoutDoc._width || 0);
-                    Doc.SetNativeHeight(layoutDoc, nheight = layoutDoc._height || 0);
-                }
-                if (nwidth > 0 && nheight > 0) {
-                    if (Math.abs(dW) > Math.abs(dH)) {
-                        if (!fixedAspect) {
-                            Doc.SetNativeWidth(layoutDoc, actualdW / (layoutDoc._width || 1) * Doc.NativeWidth(layoutDoc));
+      }
+
+      handle1PointerMove = (e: TouchEvent, me: InteractionUtils.MultiTouchEvent<TouchEvent>) => {
+            if (e.cancelBubble && this.props.isDocumentActive?.()) {
+                  this.removeMoveListeners();
+            }
+            else if (!e.cancelBubble && (this.props.isDocumentActive?.() || this.layoutDoc.onDragStart || this.onClickHandler) && !this.layoutDoc._lockedPosition && !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) {
+                  const touch = me.touchEvent.changedTouches.item(0);
+                  if (touch && (Math.abs(this._downX - touch.clientX) > 3 || Math.abs(this._downY - touch.clientY) > 3)) {
+                        if (!e.altKey && (!this.topMost || this.layoutDoc.onDragStart || this.onClickHandler)) {
+                              this.cleanUpInteractions();
+                              this.startDragging(this._downX, this._downY, this.Document.dropAction ? this.Document.dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined);
+                        }
+                  }
+                  e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document'  however it does mark the event as cancelBubble=true which we test for in the move event handlers
+                  e.preventDefault();
+            }
+      }
+
+      @action
+      handle2PointersMove = (e: TouchEvent, me: InteractionUtils.MultiTouchEvent<TouchEvent>) => {
+            const myTouches = InteractionUtils.GetMyTargetTouches(me, this.prevPoints, true);
+            const pt1 = myTouches[0];
+            const pt2 = myTouches[1];
+            const oldPoint1 = this.prevPoints.get(pt1.identifier);
+            const oldPoint2 = this.prevPoints.get(pt2.identifier);
+            const pinching = InteractionUtils.Pinning(pt1, pt2, oldPoint1!, oldPoint2!);
+            if (pinching !== 0 && oldPoint1 && oldPoint2) {
+                  const dW = (Math.abs(pt1.clientX - pt2.clientX) - Math.abs(oldPoint1.clientX - oldPoint2.clientX));
+                  const dH = (Math.abs(pt1.clientY - pt2.clientY) - Math.abs(oldPoint1.clientY - oldPoint2.clientY));
+                  const dX = -1 * Math.sign(dW);
+                  const dY = -1 * Math.sign(dH);
+
+                  if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) {
+                        const doc = Document(this.props.Document);
+                        const layoutDoc = Document(Doc.Layout(this.props.Document));
+                        let nwidth = Doc.NativeWidth(layoutDoc);
+                        let nheight = Doc.NativeHeight(layoutDoc);
+                        const width = (layoutDoc._width || 0);
+                        const height = (layoutDoc._height || (nheight / nwidth * width));
+                        const scale = this.props.ScreenToLocalTransform().Scale * this.ContentScale;
+                        const actualdW = Math.max(width + (dW * scale), 20);
+                        const actualdH = Math.max(height + (dH * scale), 20);
+                        doc.x = (doc.x || 0) + dX * (actualdW - width);
+                        doc.y = (doc.y || 0) + dY * (actualdH - height);
+                        const fixedAspect = e.ctrlKey || (nwidth && nheight);
+                        if (fixedAspect && (!nwidth || !nheight)) {
+                              Doc.SetNativeWidth(layoutDoc, nwidth = layoutDoc._width || 0);
+                              Doc.SetNativeHeight(layoutDoc, nheight = layoutDoc._height || 0);
                         }
-                        layoutDoc._width = actualdW;
-                        if (fixedAspect && !this.props.DocumentView().fitWidth) layoutDoc._height = nheight / nwidth * layoutDoc._width;
-                        else layoutDoc._height = actualdH;
-                    }
-                    else {
-                        if (!fixedAspect) {
-                            Doc.SetNativeHeight(layoutDoc, actualdH / (layoutDoc._height || 1) * Doc.NativeHeight(doc));
+                        if (nwidth > 0 && nheight > 0) {
+                              if (Math.abs(dW) > Math.abs(dH)) {
+                                    if (!fixedAspect) {
+                                          Doc.SetNativeWidth(layoutDoc, actualdW / (layoutDoc._width || 1) * Doc.NativeWidth(layoutDoc));
+                                    }
+                                    layoutDoc._width = actualdW;
+                                    if (fixedAspect && !this.props.DocumentView().fitWidth) layoutDoc._height = nheight / nwidth * layoutDoc._width;
+                                    else layoutDoc._height = actualdH;
+                              }
+                              else {
+                                    if (!fixedAspect) {
+                                          Doc.SetNativeHeight(layoutDoc, actualdH / (layoutDoc._height || 1) * Doc.NativeHeight(doc));
+                                    }
+                                    layoutDoc._height = actualdH;
+                                    if (fixedAspect && !this.props.DocumentView().fitWidth) layoutDoc._width = nwidth / nheight * layoutDoc._height;
+                                    else layoutDoc._width = actualdW;
+                              }
+                        } else {
+                              dW && (layoutDoc._width = actualdW);
+                              dH && (layoutDoc._height = actualdH);
+                              dH && layoutDoc._autoHeight && (layoutDoc._autoHeight = false);
                         }
-                        layoutDoc._height = actualdH;
-                        if (fixedAspect && !this.props.DocumentView().fitWidth) layoutDoc._width = nwidth / nheight * layoutDoc._height;
-                        else layoutDoc._width = actualdW;
-                    }
-                } else {
-                    dW && (layoutDoc._width = actualdW);
-                    dH && (layoutDoc._height = actualdH);
-                    dH && layoutDoc._autoHeight && (layoutDoc._autoHeight = false);
-                }
+                  }
+                  e.stopPropagation();
+                  e.preventDefault();
             }
-            e.stopPropagation();
-            e.preventDefault();
-        }
-    }
-
-    @action
-    onRadialMenu = (e: Event, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>): void => {
-        const pt = me.touchEvent.touches[me.touchEvent.touches.length - 1];
-        RadialMenu.Instance.openMenu(pt.pageX - 15, pt.pageY - 15);
-
-        // RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "add:right"), icon: "map-pin", selected: -1 });
-        const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]);
-        (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) && RadialMenu.Instance.addItem({ description: "Delete", event: () => { this.props.ContainingCollectionView?.removeDocument(this.props.Document), RadialMenu.Instance.closeMenu(); }, icon: "external-link-square-alt", selected: -1 });
-        // RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, "add:right"), icon: "trash", selected: -1 });
-        RadialMenu.Instance.addItem({ description: "Pin", event: () => this.props.pinToPres(this.props.Document), icon: "map-pin", selected: -1 });
-        RadialMenu.Instance.addItem({ description: "Open", event: () => MobileInterface.Instance.handleClick(this.props.Document), icon: "trash", selected: -1 });
-
-        SelectionManager.DeselectAll();
-    }
-
-    startDragging(x: number, y: number, dropAction: dropActionType, hideSource = false) {
-        if (this._mainCont.current) {
-            const dragData = new DragManager.DocumentDragData([this.props.Document]);
-            const [left, top] = this.props.ScreenToLocalTransform().scale(this.ContentScale).inverse().transformPoint(0, 0);
-            dragData.offset = this.props.ScreenToLocalTransform().scale(this.ContentScale).transformDirection(x - left, y - top);
-            dragData.offset[0] = Math.min(this.rootDoc[WidthSym](), dragData.offset[0]);
-            dragData.offset[1] = Math.min(this.rootDoc[HeightSym](), dragData.offset[1]);
-            dragData.dropAction = dropAction;
-            dragData.treeViewDoc = this.props.treeViewDoc;
-            dragData.removeDocument = this.props.removeDocument;
-            dragData.moveDocument = this.props.moveDocument;
-            const ffview = this.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView;
-            ffview && runInAction(() => (ffview.ChildDrag = this.props.DocumentView()));
-            DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: hideSource || (!dropAction && !this.layoutDoc.onDragStart) },
-                () => setTimeout(action(() => ffview && (ffview.ChildDrag = undefined)))); // this needs to happen after the drop event is processed.
-            ffview?.setupDragLines(false);
-        }
-    }
-
-    onKeyDown = (e: React.KeyboardEvent) => {
-        if (e.altKey && !e.nativeEvent.cancelBubble) {
-            e.stopPropagation();
-            e.preventDefault();
-            if (e.key === "†" || e.key === "t") {
-                if (!StrCast(this.layoutDoc._showTitle)) this.layoutDoc._showTitle = "title";
-                if (!this._titleRef.current) setTimeout(() => this._titleRef.current?.setIsFocused(true), 0);
-                else if (!this._titleRef.current.setIsFocused(true)) { // if focus didn't change, focus on interior text...
-                    this._titleRef.current?.setIsFocused(false);
-                    this._componentView?.setFocus?.();
-                }
+      }
+
+      @action
+      onRadialMenu = (e: Event, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>): void => {
+            const pt = me.touchEvent.touches[me.touchEvent.touches.length - 1];
+            RadialMenu.Instance.openMenu(pt.pageX - 15, pt.pageY - 15);
+
+            // RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "add:right"), icon: "map-pin", selected: -1 });
+            const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]);
+            (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) && RadialMenu.Instance.addItem({ description: "Delete", event: () => { this.props.ContainingCollectionView?.removeDocument(this.props.Document), RadialMenu.Instance.closeMenu(); }, icon: "external-link-square-alt", selected: -1 });
+            // RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, "add:right"), icon: "trash", selected: -1 });
+            RadialMenu.Instance.addItem({ description: "Pin", event: () => this.props.pinToPres(this.props.Document), icon: "map-pin", selected: -1 });
+            RadialMenu.Instance.addItem({ description: "Open", event: () => MobileInterface.Instance.handleClick(this.props.Document), icon: "trash", selected: -1 });
+
+            SelectionManager.DeselectAll();
+      }
+
+      startDragging(x: number, y: number, dropAction: dropActionType, hideSource = false) {
+            if (this._mainCont.current) {
+                  const dragData = new DragManager.DocumentDragData([this.props.Document]);
+                  const [left, top] = this.props.ScreenToLocalTransform().scale(this.ContentScale).inverse().transformPoint(0, 0);
+                  dragData.offset = this.props.ScreenToLocalTransform().scale(this.ContentScale).transformDirection(x - left, y - top);
+                  dragData.offset[0] = Math.min(this.rootDoc[WidthSym](), dragData.offset[0]);
+                  dragData.offset[1] = Math.min(this.rootDoc[HeightSym](), dragData.offset[1]);
+                  dragData.dropAction = dropAction;
+                  dragData.treeViewDoc = this.props.treeViewDoc;
+                  dragData.removeDocument = this.props.removeDocument;
+                  dragData.moveDocument = this.props.moveDocument;
+                  const ffview = this.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView;
+                  ffview && runInAction(() => (ffview.ChildDrag = this.props.DocumentView()));
+                  DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: hideSource || (!dropAction && !this.layoutDoc.onDragStart) },
+                        () => setTimeout(action(() => ffview && (ffview.ChildDrag = undefined)))); // this needs to happen after the drop event is processed.
+                  ffview?.setupDragLines(false);
             }
-        }
-    }
-
-    focus = (anchor: Doc, options?: DocFocusOptions) => {
-        LightboxView.SetCookie(StrCast(anchor["cookies-set"]));
-        // copying over VIEW fields immediately allows the view type to switch to create the right _componentView
-        Array.from(Object.keys(Doc.GetProto(anchor))).filter(key => key.startsWith(ViewSpecPrefix)).forEach(spec => {
-            this.layoutDoc[spec.replace(ViewSpecPrefix, "")] = ((field) => field instanceof ObjectField ? ObjectField.MakeCopy(field) : field)(anchor[spec]);
-        });
-        // after  a timeout, the right _componentView should have been created, so call it to update its view spec values
-        setTimeout(() => this._componentView?.setViewSpec?.(anchor, LinkDocPreview.LinkInfo ? true : false));
-        const focusSpeed = this._componentView?.scrollFocus?.(anchor, !options?.instant || !LinkDocPreview.LinkInfo); // bcz: smooth parameter should really be passed into focus() instead of inferred here
-        const endFocus = focusSpeed === undefined ? options?.afterFocus : async (moved: boolean) => options?.afterFocus ? options?.afterFocus(true) : ViewAdjustment.doNothing;
-        this.props.focus(options?.docTransform ? anchor : this.rootDoc, {
-            ...options, afterFocus: (didFocus: boolean) =>
-                new Promise<ViewAdjustment>(res => setTimeout(async () => res(endFocus ? await endFocus(didFocus) : ViewAdjustment.doNothing), focusSpeed ?? 0))
-        });
-
-    }
-    onClick = action((e: React.MouseEvent | React.PointerEvent) => {
-        if (!e.nativeEvent.cancelBubble && !this.Document.ignoreClick && this.props.renderDepth >= 0 &&
-            (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) {
-            let stopPropagate = true;
-            let preventDefault = true;
-            (this.rootDoc._raiseWhenDragged === undefined ? Doc.UserDoc()._raiseWhenDragged : this.rootDoc._raiseWhenDragged) && this.props.bringToFront(this.rootDoc);
-            if (this._doubleTap && (this.props.Document.type !== DocumentType.FONTICON || this.onDoubleClickHandler)) {// && !this.onClickHandler?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click
-                if (this._timeout) {
-                    clearTimeout(this._timeout);
-                    this._pendingDoubleClick = false;
-                    this._timeout = undefined;
-                }
-                if (this.onDoubleClickHandler?.script && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes(ScriptingBox.name)) { // bcz: hack? don't execute script if you're clicking on a scripting box itself
-                    const { clientX, clientY, shiftKey } = e;
-                    const func = () => this.onDoubleClickHandler.script.run({
-                        this: this.layoutDoc,
-                        self: this.rootDoc,
-                        scriptContext: this.props.scriptContext,
-                        thisContainer: this.props.ContainingCollectionDoc,
-                        documentView: this.props.DocumentView(),
-                        clientX, clientY, shiftKey
-                    }, console.log);
-                    UndoManager.RunInBatch(() => func().result?.select === true ? this.props.select(false) : "", "on double click");
-                } else if (!Doc.IsSystem(this.rootDoc)) {
-                    UndoManager.RunInBatch(() =>
-                        LightboxView.AddDocTab(this.rootDoc, "lightbox", this.props.LayoutTemplate?.())
-                        , "double tap");
-                    SelectionManager.DeselectAll();
-                    Doc.UnBrushDoc(this.props.Document);
-                }
-            } else if (this.onClickHandler?.script && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes(ScriptingBox.name)) { // bcz: hack? don't execute script if you're clicking on a scripting box itself
-                const { clientX, clientY, shiftKey } = e;
-                const func = () => this.onClickHandler.script.run({
-                    this: this.layoutDoc,
-                    self: this.rootDoc,
-                    _readOnly_: false,
-                    scriptContext: this.props.scriptContext,
-                    thisContainer: this.props.ContainingCollectionDoc,
-                    documentView: this.props.DocumentView(),
-                    clientX, clientY, shiftKey
-                }, console.log).result?.select === true ? this.props.select(false) : "";
-                const clickFunc = () => this.props.Document.dontUndo ? func() : UndoManager.RunInBatch(func, "on click");
-                if (this.onDoubleClickHandler) {
-                    runInAction(() => this._pendingDoubleClick = true);
-                    this._timeout = setTimeout(() => { this._timeout = undefined; clickFunc(); }, 350);
-                } else clickFunc();
-            } else if (this.allLinks && this.Document.type !== DocumentType.LINK && this.Document.isLinkButton && !e.shiftKey && !e.ctrlKey) {
-                this.allLinks.length && LinkManager.FollowLink(undefined, this.props.Document, this.props, e.altKey);
-            } else {
-                if ((this.layoutDoc.onDragStart || this.props.Document.rootDocument) && !(e.ctrlKey || e.button > 0)) {  // onDragStart implies a button doc that we don't want to select when clicking.   RootDocument & isTemplaetForField implies we're clicking on part of a template instance and we want to select the whole template, not the part
-                    stopPropagate = false; // don't stop propagation for field templates -- want the selection to propagate up to the root document of the template
-                } else {
-                    runInAction(() => this._pendingDoubleClick = true);
-                    this._timeout = setTimeout(action(() => { this._pendingDoubleClick = false; this._timeout = undefined; }), 350);
-                    this.props.select(e.ctrlKey || e.shiftKey);
-                }
-                preventDefault = false;
+      }
+
+      onKeyDown = (e: React.KeyboardEvent) => {
+            if (e.altKey && !e.nativeEvent.cancelBubble) {
+                  e.stopPropagation();
+                  e.preventDefault();
+                  if (e.key === "†" || e.key === "t") {
+                        if (!StrCast(this.layoutDoc._showTitle)) this.layoutDoc._showTitle = "title";
+                        if (!this._titleRef.current) setTimeout(() => this._titleRef.current?.setIsFocused(true), 0);
+                        else if (!this._titleRef.current.setIsFocused(true)) { // if focus didn't change, focus on interior text...
+                              this._titleRef.current?.setIsFocused(false);
+                              this._componentView?.setFocus?.();
+                        }
+                  }
             }
-            stopPropagate && e.stopPropagation();
-            preventDefault && e.preventDefault();
-        }
-    });
-
-    onPointerDown = (e: React.PointerEvent): void => {
-        if (this.rootDoc.type === DocumentType.INK && CurrentUserUtils.SelectedTool === InkTool.Eraser) return;
-        // continue if the event hasn't been canceled AND we are using a mouse or this has an onClick or onDragStart function (meaning it is a button document)
-        if (!(InteractionUtils.IsType(e, InteractionUtils.MOUSETYPE) || [InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.SelectedTool))) {
-            if (!InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) {
-                e.stopPropagation();
-                if (SelectionManager.IsSelected(this.props.DocumentView(), true) && this.props.Document._viewType !== CollectionViewType.Docking) e.preventDefault(); // goldenlayout needs to be able to move its tabs, so can't preventDefault for it
-                // TODO: check here for panning/inking
+      }
+
+      focus = (anchor: Doc, options?: DocFocusOptions) => {
+            LightboxView.SetCookie(StrCast(anchor["cookies-set"]));
+            // copying over VIEW fields immediately allows the view type to switch to create the right _componentView
+            Array.from(Object.keys(Doc.GetProto(anchor))).filter(key => key.startsWith(ViewSpecPrefix)).forEach(spec => {
+                  this.layoutDoc[spec.replace(ViewSpecPrefix, "")] = ((field) => field instanceof ObjectField ? ObjectField.MakeCopy(field) : field)(anchor[spec]);
+            });
+            // after  a timeout, the right _componentView should have been created, so call it to update its view spec values
+            setTimeout(() => this._componentView?.setViewSpec?.(anchor, LinkDocPreview.LinkInfo ? true : false));
+            const focusSpeed = this._componentView?.scrollFocus?.(anchor, !options?.instant || !LinkDocPreview.LinkInfo); // bcz: smooth parameter should really be passed into focus() instead of inferred here
+            const endFocus = focusSpeed === undefined ? options?.afterFocus : async (moved: boolean) => options?.afterFocus ? options?.afterFocus(true) : ViewAdjustment.doNothing;
+            this.props.focus(options?.docTransform ? anchor : this.rootDoc, {
+                  ...options, afterFocus: (didFocus: boolean) =>
+                        new Promise<ViewAdjustment>(res => setTimeout(async () => res(endFocus ? await endFocus(didFocus) : ViewAdjustment.doNothing), focusSpeed ?? 0))
+            });
+
+      }
+      onClick = action((e: React.MouseEvent | React.PointerEvent) => {
+            if (!e.nativeEvent.cancelBubble && !this.Document.ignoreClick && this.props.renderDepth >= 0 &&
+                  (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) {
+                  let stopPropagate = true;
+                  let preventDefault = true;
+                  (this.rootDoc._raiseWhenDragged === undefined ? Doc.UserDoc()._raiseWhenDragged : this.rootDoc._raiseWhenDragged) && this.props.bringToFront(this.rootDoc);
+                  if (this._doubleTap && (this.props.Document.type !== DocumentType.FONTICON || this.onDoubleClickHandler)) {// && !this.onClickHandler?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click
+                        if (this._timeout) {
+                              clearTimeout(this._timeout);
+                              this._pendingDoubleClick = false;
+                              this._timeout = undefined;
+                        }
+                        if (this.onDoubleClickHandler?.script && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes(ScriptingBox.name)) { // bcz: hack? don't execute script if you're clicking on a scripting box itself
+                              const { clientX, clientY, shiftKey } = e;
+                              const func = () => this.onDoubleClickHandler.script.run({
+                                    this: this.layoutDoc,
+                                    self: this.rootDoc,
+                                    scriptContext: this.props.scriptContext,
+                                    thisContainer: this.props.ContainingCollectionDoc,
+                                    documentView: this.props.DocumentView(),
+                                    clientX, clientY, shiftKey
+                              }, console.log);
+                              UndoManager.RunInBatch(() => func().result?.select === true ? this.props.select(false) : "", "on double click");
+                        } else if (!Doc.IsSystem(this.rootDoc)) {
+                              UndoManager.RunInBatch(() =>
+                                    LightboxView.AddDocTab(this.rootDoc, "lightbox", this.props.LayoutTemplate?.())
+                                    , "double tap");
+                              SelectionManager.DeselectAll();
+                              Doc.UnBrushDoc(this.props.Document);
+                        }
+                  } else if (this.onClickHandler?.script && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes(ScriptingBox.name)) { // bcz: hack? don't execute script if you're clicking on a scripting box itself
+                        const { clientX, clientY, shiftKey } = e;
+                        const func = () => this.onClickHandler.script.run({
+                              this: this.layoutDoc,
+                              self: this.rootDoc,
+                              _readOnly_: false,
+                              scriptContext: this.props.scriptContext,
+                              thisContainer: this.props.ContainingCollectionDoc,
+                              documentView: this.props.DocumentView(),
+                              clientX, clientY, shiftKey
+                        }, console.log).result?.select === true ? this.props.select(false) : "";
+                        const clickFunc = () => this.props.Document.dontUndo ? func() : UndoManager.RunInBatch(func, "on click");
+                        if (this.onDoubleClickHandler) {
+                              runInAction(() => this._pendingDoubleClick = true);
+                              this._timeout = setTimeout(() => { this._timeout = undefined; clickFunc(); }, 350);
+                        } else clickFunc();
+                  } else if (this.allLinks && this.Document.type !== DocumentType.LINK && this.Document.isLinkButton && !e.shiftKey && !e.ctrlKey) {
+                        this.allLinks.length && LinkManager.FollowLink(undefined, this.props.Document, this.props, e.altKey);
+                  } else {
+                        if ((this.layoutDoc.onDragStart || this.props.Document.rootDocument) && !(e.ctrlKey || e.button > 0)) {  // onDragStart implies a button doc that we don't want to select when clicking.   RootDocument & isTemplaetForField implies we're clicking on part of a template instance and we want to select the whole template, not the part
+                              stopPropagate = false; // don't stop propagation for field templates -- want the selection to propagate up to the root document of the template
+                        } else {
+                              runInAction(() => this._pendingDoubleClick = true);
+                              this._timeout = setTimeout(action(() => { this._pendingDoubleClick = false; this._timeout = undefined; }), 350);
+                              this.props.select(e.ctrlKey || e.shiftKey);
+                        }
+                        preventDefault = false;
+                  }
+                  stopPropagate && e.stopPropagation();
+                  preventDefault && e.preventDefault();
             }
-            return;
-        }
-        this._downX = e.clientX;
-        this._downY = e.clientY;
-        if ((!e.nativeEvent.cancelBubble || this.onClickHandler || this.layoutDoc.onDragStart) &&
-            // if this is part of a template, let the event go up to the tempalte root unless right/ctrl clicking
-            !(this.props.Document.rootDocument && !(e.ctrlKey || e.button > 0))) {
-            if ((this.props.isDocumentActive?.() || this.layoutDoc.onDragStart) &&
-                !this.props.onBrowseClick?.() &&
-                !this.Document.ignoreClick &&
-                !e.ctrlKey &&
-                (e.button === 0 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) &&
-                !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) {
-                e.stopPropagation();
-                // don't preventDefault anymore.  Goldenlayout, PDF text selection and RTF text selection all need it to go though
-                //if (this.props.isSelected(true) && this.rootDoc.type !== DocumentType.PDF && this.layoutDoc._viewType !== CollectionViewType.Docking) e.preventDefault();
+      });
+
+      onPointerDown = (e: React.PointerEvent): void => {
+            if (this.rootDoc.type === DocumentType.INK && CurrentUserUtils.SelectedTool === InkTool.Eraser) return;
+            // continue if the event hasn't been canceled AND we are using a mouse or this has an onClick or onDragStart function (meaning it is a button document)
+            if (!(InteractionUtils.IsType(e, InteractionUtils.MOUSETYPE) || [InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.SelectedTool))) {
+                  if (!InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) {
+                        e.stopPropagation();
+                        if (SelectionManager.IsSelected(this.props.DocumentView(), true) && this.props.Document._viewType !== CollectionViewType.Docking) e.preventDefault(); // goldenlayout needs to be able to move its tabs, so can't preventDefault for it
+                        // TODO: check here for panning/inking
+                  }
+                  return;
             }
-            if (this.props.isDocumentActive?.()) {
-                document.removeEventListener("pointermove", this.onPointerMove);
-                document.addEventListener("pointermove", this.onPointerMove);
+            this._downX = e.clientX;
+            this._downY = e.clientY;
+            if ((!e.nativeEvent.cancelBubble || this.onClickHandler || this.layoutDoc.onDragStart) &&
+                  // if this is part of a template, let the event go up to the tempalte root unless right/ctrl clicking
+                  !(this.props.Document.rootDocument && !(e.ctrlKey || e.button > 0))) {
+                  if ((this.props.isDocumentActive?.() || this.layoutDoc.onDragStart) &&
+                        !this.props.onBrowseClick?.() &&
+                        !this.Document.ignoreClick &&
+                        !e.ctrlKey &&
+                        (e.button === 0 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) &&
+                        !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) {
+                        e.stopPropagation();
+                        // don't preventDefault anymore.  Goldenlayout, PDF text selection and RTF text selection all need it to go though
+                        //if (this.props.isSelected(true) && this.rootDoc.type !== DocumentType.PDF && this.layoutDoc._viewType !== CollectionViewType.Docking) e.preventDefault();
+                  }
+                  if (this.props.isDocumentActive?.()) {
+                        document.removeEventListener("pointermove", this.onPointerMove);
+                        document.addEventListener("pointermove", this.onPointerMove);
+                  }
+                  document.removeEventListener("pointerup", this.onPointerUp);
+                  document.addEventListener("pointerup", this.onPointerUp);
             }
+      }
+
+      onPointerMove = (e: PointerEvent): void => {
+            if (e.cancelBubble) return;
+            if ((InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || [InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.SelectedTool))) return;
+
+            if ((this.props.isDocumentActive?.() || this.layoutDoc.onDragStart) && !this.layoutDoc._lockedPosition && !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) {
+                  if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) {
+                        if (!e.altKey && (!this.topMost || this.layoutDoc.onDragStart || this.onClickHandler) && (e.buttons === 1 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE))) {
+                              document.removeEventListener("pointermove", this.onPointerMove);
+                              document.removeEventListener("pointerup", this.onPointerUp);
+                              this.startDragging(this._downX, this._downY, ((e.ctrlKey || e.altKey) && "alias") || (this.props.dropAction || this.Document.dropAction || undefined) as dropActionType);
+                        }
+                  }
+                  e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document'  however it does mark the event as cancelBubble=true which we test for in the move event handlers
+                  e.preventDefault();
+            }
+      }
+
+      cleanupPointerEvents = () => {
+            this.cleanUpInteractions();
+            document.removeEventListener("pointermove", this.onPointerMove);
             document.removeEventListener("pointerup", this.onPointerUp);
-            document.addEventListener("pointerup", this.onPointerUp);
-        }
-    }
-
-    onPointerMove = (e: PointerEvent): void => {
-        if (e.cancelBubble) return;
-        if ((InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || [InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.SelectedTool))) return;
-
-        if ((this.props.isDocumentActive?.() || this.layoutDoc.onDragStart) && !this.layoutDoc._lockedPosition && !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) {
-            if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) {
-                if (!e.altKey && (!this.topMost || this.layoutDoc.onDragStart || this.onClickHandler) && (e.buttons === 1 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE))) {
-                    document.removeEventListener("pointermove", this.onPointerMove);
-                    document.removeEventListener("pointerup", this.onPointerUp);
-                    this.startDragging(this._downX, this._downY, ((e.ctrlKey || e.altKey) && "alias") || (this.props.dropAction || this.Document.dropAction || undefined) as dropActionType);
-                }
+      }
+
+      onPointerUp = (e: PointerEvent): void => {
+            this.cleanupPointerEvents();
+
+            if (this.onPointerUpHandler?.script && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) {
+                  this.onPointerUpHandler.script.run({ self: this.rootDoc, this: this.layoutDoc }, console.log);
+            } else {
+                  this._doubleTap = (Date.now() - this._lastTap < 300 && e.button === 0 && Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2);
+                  // bcz: this is a placeholder.  documents, when selected, should stopPropagation on doubleClicks if they want to keep the DocumentView from getting them
+                  if (!this.props.isSelected(true) || ![DocumentType.PDF, DocumentType.RTF].includes(StrCast(this.rootDoc.type) as any)) this._lastTap = Date.now();// don't want to process the start of a double tap if the doucment is selected
+            }
+      }
+
+      @undoBatch @action
+      toggleFollowLink = (location: Opt<string>, zoom?: boolean, setPushpin?: boolean): void => {
+            this.Document.ignoreClick = false;
+            if (setPushpin) {
+                  this.Document.isPushpin = !this.Document.isPushpin;
+                  this.Document._isLinkButton = this.Document.isPushpin || this.Document._isLinkButton;
+            } else {
+                  this.Document._isLinkButton = !this.Document._isLinkButton;
             }
-            e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document'  however it does mark the event as cancelBubble=true which we test for in the move event handlers
-            e.preventDefault();
-        }
-    }
-
-    cleanupPointerEvents = () => {
-        this.cleanUpInteractions();
-        document.removeEventListener("pointermove", this.onPointerMove);
-        document.removeEventListener("pointerup", this.onPointerUp);
-    }
-
-    onPointerUp = (e: PointerEvent): void => {
-        this.cleanupPointerEvents();
-
-        if (this.onPointerUpHandler?.script && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) {
-            this.onPointerUpHandler.script.run({ self: this.rootDoc, this: this.layoutDoc }, console.log);
-        } else {
-            this._doubleTap = (Date.now() - this._lastTap < 300 && e.button === 0 && Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2);
-            // bcz: this is a placeholder.  documents, when selected, should stopPropagation on doubleClicks if they want to keep the DocumentView from getting them
-            if (!this.props.isSelected(true) || ![DocumentType.PDF, DocumentType.RTF].includes(StrCast(this.rootDoc.type) as any)) this._lastTap = Date.now();// don't want to process the start of a double tap if the doucment is selected
-        }
-    }
-
-    @undoBatch @action
-    toggleFollowLink = (location: Opt<string>, zoom?: boolean, setPushpin?: boolean): void => {
-        this.Document.ignoreClick = false;
-        if (setPushpin) {
-            this.Document.isPushpin = !this.Document.isPushpin;
-            this.Document._isLinkButton = this.Document.isPushpin || this.Document._isLinkButton;
-        } else {
-            this.Document._isLinkButton = !this.Document._isLinkButton;
-        }
-        if (this.Document._isLinkButton && !this.onClickHandler) {
-            zoom !== undefined && (this.Document.followLinkZoom = zoom);
+            if (this.Document._isLinkButton && !this.onClickHandler) {
+                  zoom !== undefined && (this.Document.followLinkZoom = zoom);
+                  this.Document.followLinkLocation = location;
+            } else if (this.Document._isLinkButton && this.onClickHandler) {
+                  this.Document._isLinkButton = false;
+                  this.Document["onClick-rawScript"] = this.dataDoc["onClick-rawScript"] = this.dataDoc.onClick = this.Document.onClick = this.layoutDoc.onClick = undefined;
+            }
+      }
+      @undoBatch @action
+      toggleTargetOnClick = (): void => {
+            this.Document.ignoreClick = false;
+            this.Document._isLinkButton = true;
+            this.Document.isPushpin = true;
+      }
+      @undoBatch @action
+      followLinkOnClick = (location: Opt<string>, zoom: boolean,): void => {
+            this.Document.ignoreClick = false;
+            this.Document._isLinkButton = true;
+            this.Document.isPushpin = false;
+            this.Document.followLinkZoom = zoom;
             this.Document.followLinkLocation = location;
-        } else if (this.Document._isLinkButton && this.onClickHandler) {
+      }
+      @undoBatch @action
+      selectOnClick = (): void => {
+            this.Document.ignoreClick = false;
             this.Document._isLinkButton = false;
-            this.Document["onClick-rawScript"] = this.dataDoc["onClick-rawScript"] = this.dataDoc.onClick = this.Document.onClick = this.layoutDoc.onClick = undefined;
-        }
-    }
-    @undoBatch @action
-    toggleTargetOnClick = (): void => {
-        this.Document.ignoreClick = false;
-        this.Document._isLinkButton = true;
-        this.Document.isPushpin = true;
-    }
-    @undoBatch @action
-    followLinkOnClick = (location: Opt<string>, zoom: boolean,): void => {
-        this.Document.ignoreClick = false;
-        this.Document._isLinkButton = true;
-        this.Document.isPushpin = false;
-        this.Document.followLinkZoom = zoom;
-        this.Document.followLinkLocation = location;
-    }
-    @undoBatch @action
-    selectOnClick = (): void => {
-        this.Document.ignoreClick = false;
-        this.Document._isLinkButton = false;
-        this.Document.isPushpin = false;
-        this.Document.onClick = this.layoutDoc.onClick = undefined;
-    }
-    @undoBatch
-    noOnClick = (): void => {
-        this.Document.ignoreClick = false;
-        this.Document._isLinkButton = false;
-    }
-
-    @undoBatch deleteClicked = () => this.props.removeDocument?.(this.props.Document);
-    @undoBatch setToggleDetail = () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(documentView, "${StrCast(this.Document.layoutKey).replace("layout_", "")}")`, { documentView: "any" });
-
-    @undoBatch @action
-    drop = async (e: Event, de: DragManager.DropEvent) => {
-        if (this.props.dontRegisterView || this.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) return;
-        if (this.props.Document === CurrentUserUtils.ActiveDashboard) {
-            alert((e.target as any)?.closest?.("*.lm_content") ?
-                "You can't perform this move most likely because you don't have permission to modify the destination." :
-                "Linking to document tabs not yet supported. Drop link on document content.");
-            return;
-        }
-        const linkdrag = de.complete.annoDragData ?? de.complete.linkDragData;
-        if (linkdrag) linkdrag.linkSourceDoc = linkdrag.linkSourceGetAnchor();
-        if (linkdrag?.linkSourceDoc) {
-            e.stopPropagation();
-            if (de.complete.annoDragData && !de.complete.annoDragData.dropDocument) {
-                de.complete.annoDragData.dropDocument = de.complete.annoDragData.dropDocCreator(undefined);
+            this.Document.isPushpin = false;
+            this.Document.onClick = this.layoutDoc.onClick = undefined;
+      }
+      @undoBatch
+      noOnClick = (): void => {
+            this.Document.ignoreClick = false;
+            this.Document._isLinkButton = false;
+      }
+
+      @undoBatch deleteClicked = () => this.props.removeDocument?.(this.props.Document);
+      @undoBatch setToggleDetail = () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(documentView, "${StrCast(this.Document.layoutKey).replace("layout_", "")}")`, { documentView: "any" });
+
+      @undoBatch @action
+      drop = async (e: Event, de: DragManager.DropEvent) => {
+            if (this.props.dontRegisterView || this.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) return;
+            if (this.props.Document === CurrentUserUtils.ActiveDashboard) {
+                  alert((e.target as any)?.closest?.("*.lm_content") ?
+                        "You can't perform this move most likely because you don't have permission to modify the destination." :
+                        "Linking to document tabs not yet supported. Drop link on document content.");
+                  return;
             }
-            if (de.complete.annoDragData || this.rootDoc !== linkdrag.linkSourceDoc.context) {
-                const dropDoc = de.complete.annoDragData?.dropDocument ?? this._componentView?.getAnchor?.() ?? this.props.Document;
-                de.complete.linkDocument = DocUtils.MakeLink({ doc: linkdrag.linkSourceDoc }, { doc: dropDoc }, undefined, undefined, undefined, undefined, [de.x, de.y - 50]);
+            const linkdrag = de.complete.annoDragData ?? de.complete.linkDragData;
+            if (linkdrag) linkdrag.linkSourceDoc = linkdrag.linkSourceGetAnchor();
+            if (linkdrag?.linkSourceDoc) {
+                  e.stopPropagation();
+                  if (de.complete.annoDragData && !de.complete.annoDragData.dropDocument) {
+                        de.complete.annoDragData.dropDocument = de.complete.annoDragData.dropDocCreator(undefined);
+                  }
+                  if (de.complete.annoDragData || this.rootDoc !== linkdrag.linkSourceDoc.context) {
+                        const dropDoc = de.complete.annoDragData?.dropDocument ?? this._componentView?.getAnchor?.() ?? this.props.Document;
+                        de.complete.linkDocument = DocUtils.MakeLink({ doc: linkdrag.linkSourceDoc }, { doc: dropDoc }, undefined, undefined, undefined, undefined, [de.x, de.y - 50]);
+                  }
             }
-        }
-    }
-
-    @undoBatch
-    @action
-    makeIntoPortal = async () => {
-        const portalLink = this.allLinks.find(d => d.anchor1 === this.props.Document);
-        if (!portalLink) {
-            const portal = Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _fitWidth: true, title: StrCast(this.props.Document.title) + " [Portal]" });
-            DocUtils.MakeLink({ doc: this.props.Document }, { doc: portal }, "portal to:portal from");
-        }
-        this.Document.followLinkLocation = "inPlace";
-        this.Document.followLinkZoom = true;
-        this.Document._isLinkButton = true;
-    }
-
-    @action
-    onContextMenu = (e?: React.MouseEvent, pageX?: number, pageY?: number) => {
-        if (e && this.rootDoc._hideContextMenu && Doc.UserDoc().noviceMode) {
-            e.preventDefault();
-            e.stopPropagation();
-            //!this.props.isSelected(true) && SelectionManager.SelectView(this.props.DocumentView(), false);
-        }
-        // the touch onContextMenu is button 0, the pointer onContextMenu is button 2
-        if (e) {
-            if (e.button === 0 && !e.ctrlKey || e.isDefaultPrevented()) {
-                e.preventDefault();
-                return;
+      }
+
+      @undoBatch
+      @action
+      makeIntoPortal = async () => {
+            const portalLink = this.allLinks.find(d => d.anchor1 === this.props.Document);
+            if (!portalLink) {
+                  const portal = Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _fitWidth: true, title: StrCast(this.props.Document.title) + " [Portal]" });
+                  DocUtils.MakeLink({ doc: this.props.Document }, { doc: portal }, "portal to:portal from");
             }
-            e.preventDefault();
-            e.stopPropagation();
-            e.persist();
-
-            if (!navigator.userAgent.includes("Mozilla") && (Math.abs(this._downX - e?.clientX) > 3 || Math.abs(this._downY - e?.clientY) > 3)) {
-                return;
+            this.Document.followLinkLocation = "inPlace";
+            this.Document.followLinkZoom = true;
+            this.Document._isLinkButton = true;
+      }
+
+      @action
+      onContextMenu = (e?: React.MouseEvent, pageX?: number, pageY?: number) => {
+            if (e && this.rootDoc._hideContextMenu && Doc.UserDoc().noviceMode) {
+                  e.preventDefault();
+                  e.stopPropagation();
+                  //!this.props.isSelected(true) && SelectionManager.SelectView(this.props.DocumentView(), false);
             }
-        }
-
-        const cm = ContextMenu.Instance;
-        if (!cm || (e as any)?.nativeEvent?.SchemaHandled) return;
-
-        if (e && !(e.nativeEvent as any).dash) {
-            const onDisplay = () => setTimeout(() => {
-                DocumentViewInternal.SelectAfterContextMenu && !this.props.isSelected(true) && SelectionManager.SelectView(this.props.DocumentView(), false); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up.  by delaying the selection until hopefully after the pointer up, the context menu will appear.
-                setTimeout(() => {
-                    const ele = document.elementFromPoint(e.clientX, e.clientY);
-                    simulateMouseClick(ele, e.clientX, e.clientY, e.screenX, e.screenY);
-                });
-            });
-            if (navigator.userAgent.includes("Macintosh")) {
-                cm.displayMenu((e?.pageX || pageX || 0) - 15, (e?.pageY || pageY || 0) - 15, undefined, undefined, onDisplay);
-            }
-            else {
-                onDisplay();
-            }
-            return;
-        }
-
-        const customScripts = Cast(this.props.Document.contextMenuScripts, listSpec(ScriptField), []);
-        StrListCast(this.Document.contextMenuLabels).forEach((label, i) =>
-            cm.addItem({ description: label, event: () => customScripts[i]?.script.run({ documentView: this, this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: "sticky-note" }));
-        this.props.contextMenuItems?.().forEach(item =>
-            item.label && cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: item.icon as IconProp }));
-
-        if (!this.props.Document.isFolder) {
-            const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null);
-            const appearance = cm.findByDescription("UI Controls...");
-            const appearanceItems: ContextMenuProps[] = appearance && "subitems" in appearance ? appearance.subitems : [];
-            !Doc.UserDoc().noviceMode && templateDoc && appearanceItems.push({ description: "Open Template   ", event: () => this.props.addDocTab(templateDoc, "add:right"), icon: "eye" });
-            !Doc.UserDoc().noviceMode && appearanceItems.push({
-                description: "Add a Field", event: () => {
-                    const alias = Doc.MakeAlias(this.rootDoc);
-                    alias.layout = FormattedTextBox.LayoutString("newfield");
-                    alias.title = "newfield";
-                    alias._height = 35;
-                    alias._width = 100;
-                    alias.syncLayoutFieldWithTitle = true;
-                    alias.x = NumCast(this.rootDoc.x) + NumCast(this.rootDoc.width);
-                    alias.y = NumCast(this.rootDoc.y);
-                    this.props.addDocument?.(alias);
-                }, icon: "eye"
-            });
-            DocListCast(this.Document.links).length && appearanceItems.splice(0, 0, { description: `${this.layoutDoc.hideLinkButton ? "Show" : "Hide"} Link Button`, event: action(() => this.layoutDoc.hideLinkButton = !this.layoutDoc.hideLinkButton), icon: "eye" });
-            !appearance && cm.addItem({ description: "UI Controls...", subitems: appearanceItems, icon: "compass" });
-
-            if (!Doc.IsSystem(this.rootDoc) && this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Tree) {
-                !Doc.UserDoc().noviceMode && appearanceItems.splice(0, 0, { description: `${!this.layoutDoc._showAudio ? "Show" : "Hide"} Audio Button`, event: action(() => this.layoutDoc._showAudio = !this.layoutDoc._showAudio), icon: "microphone" });
-                const existingOnClick = cm.findByDescription("OnClick...");
-                const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
-
-                const zorders = cm.findByDescription("ZOrder...");
-                const zorderItems: ContextMenuProps[] = zorders && "subitems" in zorders ? zorders.subitems : [];
-                if (this.props.bringToFront !== emptyFunction) {
-                    zorderItems.push({ description: "Bring to Front", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: "expand-arrows-alt" });
-                    zorderItems.push({ description: "Send to Back", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: "expand-arrows-alt" });
-                    zorderItems.push({ description: this.rootDoc._raiseWhenDragged !== false ? "Keep ZIndex when dragged" : "Allow ZIndex to change when dragged", event: undoBatch(action(() => this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined)), icon: "expand-arrows-alt" });
-                }
-                !zorders && cm.addItem({ description: "ZOrder...", noexpand: true, subitems: zorderItems, icon: "compass" });
-
-                !Doc.UserDoc().noviceMode && onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" });
-                !Doc.UserDoc().noviceMode && onClicks.push({ description: "Toggle Detail", event: this.setToggleDetail, icon: "concierge-bell" });
-                this.props.CollectionFreeFormDocumentView && onClicks.push({ description: (this.Document.followLinkZoom ? "Don't" : "") + " zoom following link", event: () => this.Document.followLinkZoom = !this.Document.followLinkZoom, icon: this.Document.ignoreClick ? "unlock" : "lock" });
-
-                if (!this.Document.annotationOn) {
-                    const options = cm.findByDescription("Options...");
-                    const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : [];
-                    !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" });
-
-                    onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" });
-                    onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: () => this.toggleFollowLink("inPlace", true, false), icon: "link" });
-                    !this.Document.isLinkButton && onClicks.push({ description: "Follow Link on Right", event: () => this.toggleFollowLink("add:right", false, false), icon: "link" });
-                    onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? "Remove Click Behavior" : "Follow Link", event: () => this.toggleFollowLink(undefined, false, false), icon: "link" });
-                    onClicks.push({ description: (this.Document.isPushpin ? "Remove" : "Make") + " Pushpin", event: () => this.toggleFollowLink(undefined, false, true), icon: "map-pin" });
-                    onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "terminal" });
-                    !existingOnClick && cm.addItem({ description: "OnClick...", addDivider: true, noexpand: true, subitems: onClicks, icon: "mouse-pointer" });
-                } else if (DocListCast(this.Document.links).length) {
-                    onClicks.push({ description: "Select on Click", event: () => this.selectOnClick(), icon: "link" });
-                    onClicks.push({ description: "Follow Link on Click", event: () => this.followLinkOnClick(undefined, false), icon: "link" });
-                    onClicks.push({ description: "Toggle Link Target on Click", event: () => this.toggleTargetOnClick(), icon: "map-pin" });
-                    !existingOnClick && cm.addItem({ description: "OnClick...", addDivider: true, subitems: onClicks, icon: "mouse-pointer" });
-                }
+            // the touch onContextMenu is button 0, the pointer onContextMenu is button 2
+            if (e) {
+                  if (e.button === 0 && !e.ctrlKey || e.isDefaultPrevented()) {
+                        e.preventDefault();
+                        return;
+                  }
+                  e.preventDefault();
+                  e.stopPropagation();
+                  e.persist();
+
+                  if (!navigator.userAgent.includes("Mozilla") && (Math.abs(this._downX - e?.clientX) > 3 || Math.abs(this._downY - e?.clientY) > 3)) {
+                        return;
+                  }
             }
 
-            const funcs: ContextMenuProps[] = [];
-            if (!Doc.UserDoc().noviceMode && this.layoutDoc.onDragStart) {
-                funcs.push({ description: "Drag an Alias", icon: "edit", event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) });
-                funcs.push({ description: "Drag a Copy", icon: "edit", event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) });
-                funcs.push({ description: "Drag Document", icon: "edit", event: () => this.layoutDoc.onDragStart = undefined });
-                cm.addItem({ description: "OnDrag...", noexpand: true, subitems: funcs, icon: "asterisk" });
+            const cm = ContextMenu.Instance;
+            if (!cm || (e as any)?.nativeEvent?.SchemaHandled) return;
+
+            if (e && !(e.nativeEvent as any).dash) {
+                  const onDisplay = () => setTimeout(() => {
+                        DocumentViewInternal.SelectAfterContextMenu && !this.props.isSelected(true) && SelectionManager.SelectView(this.props.DocumentView(), false); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up.  by delaying the selection until hopefully after the pointer up, the context menu will appear.
+                        setTimeout(() => {
+                              const ele = document.elementFromPoint(e.clientX, e.clientY);
+                              simulateMouseClick(ele, e.clientX, e.clientY, e.screenX, e.screenY);
+                        });
+                  });
+                  if (navigator.userAgent.includes("Macintosh")) {
+                        cm.displayMenu((e?.pageX || pageX || 0) - 15, (e?.pageY || pageY || 0) - 15, undefined, undefined, onDisplay);
+                  }
+                  else {
+                        onDisplay();
+                  }
+                  return;
             }
 
-            const more = cm.findByDescription("More...");
-            const moreItems = more && "subitems" in more ? more.subitems : [];
-            if (!Doc.IsSystem(this.rootDoc)) {
-                (this.rootDoc._viewType !== CollectionViewType.Docking || !Doc.UserDoc().noviceMode) && moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: "users" });
-                if (!Doc.UserDoc().noviceMode) {
-                    moreItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: "concierge-bell" });
-                    moreItems.push({ description: `${this.Document._chromeHidden ? "Show" : "Hide"} Chrome`, event: () => this.Document._chromeHidden = !this.Document._chromeHidden, icon: "project-diagram" });
-
-                    if (Cast(Doc.GetProto(this.props.Document).data, listSpec(Doc))) {
-                        moreItems.push({ description: "Export to Google Photos Album", event: () => GooglePhotos.Export.CollectionToAlbum({ collection: this.props.Document }).then(console.log), icon: "caret-square-right" });
-                        moreItems.push({ description: "Tag Child Images via Google Photos", event: () => GooglePhotos.Query.TagChildImages(this.props.Document), icon: "caret-square-right" });
-                        moreItems.push({ description: "Write Back Link to Album", event: () => GooglePhotos.Transactions.AddTextEnrichment(this.props.Document), icon: "caret-square-right" });
-                    }
-                    moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Doc.globalServerPath(this.props.Document)), icon: "fingerprint" });
-                }
+            const customScripts = Cast(this.props.Document.contextMenuScripts, listSpec(ScriptField), []);
+            StrListCast(this.Document.contextMenuLabels).forEach((label, i) =>
+                  cm.addItem({ description: label, event: () => customScripts[i]?.script.run({ documentView: this, this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: "sticky-note" }));
+            this.props.contextMenuItems?.().forEach(item =>
+                  item.label && cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: item.icon as IconProp }));
+
+            if (!this.props.Document.isFolder) {
+                  const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null);
+                  const appearance = cm.findByDescription("UI Controls...");
+                  const appearanceItems: ContextMenuProps[] = appearance && "subitems" in appearance ? appearance.subitems : [];
+                  !Doc.UserDoc().noviceMode && templateDoc && appearanceItems.push({ description: "Open Template   ", event: () => this.props.addDocTab(templateDoc, "add:right"), icon: "eye" });
+                  !Doc.UserDoc().noviceMode && appearanceItems.push({
+                        description: "Add a Field", event: () => {
+                              const alias = Doc.MakeAlias(this.rootDoc);
+                              alias.layout = FormattedTextBox.LayoutString("newfield");
+                              alias.title = "newfield";
+                              alias._height = 35;
+                              alias._width = 100;
+                              alias.syncLayoutFieldWithTitle = true;
+                              alias.x = NumCast(this.rootDoc.x) + NumCast(this.rootDoc.width);
+                              alias.y = NumCast(this.rootDoc.y);
+                              this.props.addDocument?.(alias);
+                        }, icon: "eye"
+                  });
+                  DocListCast(this.Document.links).length && appearanceItems.splice(0, 0, { description: `${this.layoutDoc.hideLinkButton ? "Show" : "Hide"} Link Button`, event: action(() => this.layoutDoc.hideLinkButton = !this.layoutDoc.hideLinkButton), icon: "eye" });
+                  !appearance && cm.addItem({ description: "UI Controls...", subitems: appearanceItems, icon: "compass" });
+
+                  if (!Doc.IsSystem(this.rootDoc) && this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Tree) {
+                        !Doc.UserDoc().noviceMode && appearanceItems.splice(0, 0, { description: `${!this.layoutDoc._showAudio ? "Show" : "Hide"} Audio Button`, event: action(() => this.layoutDoc._showAudio = !this.layoutDoc._showAudio), icon: "microphone" });
+                        const existingOnClick = cm.findByDescription("OnClick...");
+                        const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
+
+                        const zorders = cm.findByDescription("ZOrder...");
+                        const zorderItems: ContextMenuProps[] = zorders && "subitems" in zorders ? zorders.subitems : [];
+                        if (this.props.bringToFront !== emptyFunction) {
+                              zorderItems.push({ description: "Bring to Front", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: "expand-arrows-alt" });
+                              zorderItems.push({ description: "Send to Back", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: "expand-arrows-alt" });
+                              zorderItems.push({ description: this.rootDoc._raiseWhenDragged !== false ? "Keep ZIndex when dragged" : "Allow ZIndex to change when dragged", event: undoBatch(action(() => this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined)), icon: "expand-arrows-alt" });
+                        }
+                        !zorders && cm.addItem({ description: "ZOrder...", noexpand: true, subitems: zorderItems, icon: "compass" });
+
+                        !Doc.UserDoc().noviceMode && onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" });
+                        !Doc.UserDoc().noviceMode && onClicks.push({ description: "Toggle Detail", event: this.setToggleDetail, icon: "concierge-bell" });
+                        this.props.CollectionFreeFormDocumentView && onClicks.push({ description: (this.Document.followLinkZoom ? "Don't" : "") + " zoom following link", event: () => this.Document.followLinkZoom = !this.Document.followLinkZoom, icon: this.Document.ignoreClick ? "unlock" : "lock" });
+
+                        if (!this.Document.annotationOn) {
+                              const options = cm.findByDescription("Options...");
+                              const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : [];
+                              !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" });
+
+                              onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" });
+                              onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: () => this.toggleFollowLink("inPlace", true, false), icon: "link" });
+                              !this.Document.isLinkButton && onClicks.push({ description: "Follow Link on Right", event: () => this.toggleFollowLink("add:right", false, false), icon: "link" });
+                              onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? "Remove Click Behavior" : "Follow Link", event: () => this.toggleFollowLink(undefined, false, false), icon: "link" });
+                              onClicks.push({ description: (this.Document.isPushpin ? "Remove" : "Make") + " Pushpin", event: () => this.toggleFollowLink(undefined, false, true), icon: "map-pin" });
+                              onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "terminal" });
+                              !existingOnClick && cm.addItem({ description: "OnClick...", addDivider: true, noexpand: true, subitems: onClicks, icon: "mouse-pointer" });
+                        } else if (DocListCast(this.Document.links).length) {
+                              onClicks.push({ description: "Select on Click", event: () => this.selectOnClick(), icon: "link" });
+                              onClicks.push({ description: "Follow Link on Click", event: () => this.followLinkOnClick(undefined, false), icon: "link" });
+                              onClicks.push({ description: "Toggle Link Target on Click", event: () => this.toggleTargetOnClick(), icon: "map-pin" });
+                              !existingOnClick && cm.addItem({ description: "OnClick...", addDivider: true, subitems: onClicks, icon: "mouse-pointer" });
+                        }
+                  }
+
+                  const funcs: ContextMenuProps[] = [];
+                  if (!Doc.UserDoc().noviceMode && this.layoutDoc.onDragStart) {
+                        funcs.push({ description: "Drag an Alias", icon: "edit", event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) });
+                        funcs.push({ description: "Drag a Copy", icon: "edit", event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) });
+                        funcs.push({ description: "Drag Document", icon: "edit", event: () => this.layoutDoc.onDragStart = undefined });
+                        cm.addItem({ description: "OnDrag...", noexpand: true, subitems: funcs, icon: "asterisk" });
+                  }
+
+                  const more = cm.findByDescription("More...");
+                  const moreItems = more && "subitems" in more ? more.subitems : [];
+                  if (!Doc.IsSystem(this.rootDoc)) {
+                        (this.rootDoc._viewType !== CollectionViewType.Docking || !Doc.UserDoc().noviceMode) && moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: "users" });
+                        if (!Doc.UserDoc().noviceMode) {
+                              moreItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: "concierge-bell" });
+                              moreItems.push({ description: `${this.Document._chromeHidden ? "Show" : "Hide"} Chrome`, event: () => this.Document._chromeHidden = !this.Document._chromeHidden, icon: "project-diagram" });
+
+                              if (Cast(Doc.GetProto(this.props.Document).data, listSpec(Doc))) {
+                                    moreItems.push({ description: "Export to Google Photos Album", event: () => GooglePhotos.Export.CollectionToAlbum({ collection: this.props.Document }).then(console.log), icon: "caret-square-right" });
+                                    moreItems.push({ description: "Tag Child Images via Google Photos", event: () => GooglePhotos.Query.TagChildImages(this.props.Document), icon: "caret-square-right" });
+                                    moreItems.push({ description: "Write Back Link to Album", event: () => GooglePhotos.Transactions.AddTextEnrichment(this.props.Document), icon: "caret-square-right" });
+                              }
+                              moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Doc.globalServerPath(this.props.Document)), icon: "fingerprint" });
+                        }
+                  }
+
+                  if (this.props.removeDocument && !Doc.IsSystem(this.rootDoc) && CurrentUserUtils.ActiveDashboard !== this.props.Document) { // need option to gray out menu items ... preferably with a '?' that explains why they're grayed out (eg., no permissions)
+                        moreItems.push({ description: "Close", event: this.deleteClicked, icon: "times" });
+                  }
+                  !more && moreItems.length && cm.addItem({ description: "More...", subitems: moreItems, icon: "compass" });
+
+                  const help = cm.findByDescription("Help...");
+                  const helpItems: ContextMenuProps[] = help && "subitems" in help ? help.subitems : [];
+                  !Doc.UserDoc().novice && helpItems.push({ description: "Show Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "add:right"), icon: "layer-group" });
+                  helpItems.push({ description: "Text Shortcuts Ctrl+/", event: () => this.props.addDocTab(Docs.Create.PdfDocument("/assets/cheat-sheet.pdf", { _width: 300, _height: 300 }), "add:right"), icon: "keyboard" });
+                  !Doc.UserDoc().novice && helpItems.push({ description: "Print Document in Console", event: () => console.log(this.props.Document), icon: "hand-point-right" });
+                  !Doc.UserDoc().novice && helpItems.push({ description: "Print DataDoc in Console", event: () => console.log(this.props.Document[DataSym]), icon: "hand-point-right" });
+                  cm.addItem({ description: "Help...", noexpand: true, subitems: helpItems, icon: "question" });
             }
 
-            if (this.props.removeDocument && !Doc.IsSystem(this.rootDoc) && CurrentUserUtils.ActiveDashboard !== this.props.Document) { // need option to gray out menu items ... preferably with a '?' that explains why they're grayed out (eg., no permissions)
-                moreItems.push({ description: "Close", event: this.deleteClicked, icon: "times" });
-            }
-            !more && moreItems.length && cm.addItem({ description: "More...", subitems: moreItems, icon: "compass" });
-
-            const help = cm.findByDescription("Help...");
-            const helpItems: ContextMenuProps[] = help && "subitems" in help ? help.subitems : [];
-            !Doc.UserDoc().novice && helpItems.push({ description: "Show Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "add:right"), icon: "layer-group" });
-            helpItems.push({ description: "Text Shortcuts Ctrl+/", event: () => this.props.addDocTab(Docs.Create.PdfDocument("/assets/cheat-sheet.pdf", { _width: 300, _height: 300 }), "add:right"), icon: "keyboard" });
-            !Doc.UserDoc().novice && helpItems.push({ description: "Print Document in Console", event: () => console.log(this.props.Document), icon: "hand-point-right" });
-            !Doc.UserDoc().novice && helpItems.push({ description: "Print DataDoc in Console", event: () => console.log(this.props.Document[DataSym]), icon: "hand-point-right" });
-            cm.addItem({ description: "Help...", noexpand: true, subitems: helpItems, icon: "question" });
-        }
-
-        if (!this.topMost) e?.stopPropagation(); // DocumentViews should stop propagation of this event
-        cm.displayMenu((e?.pageX || pageX || 0) - 15, (e?.pageY || pageY || 0) - 15);
-    }
-
-    collectionFilters = () => StrListCast(this.props.Document._docFilters);
-    collectionRangeDocFilters = () => StrListCast(this.props.Document._docRangeFilters);
-    @computed get showFilterIcon() {
-        return this.collectionFilters().length || this.collectionRangeDocFilters().length ? "hasFilter" :
-            this.props.docFilters?.().filter(f => Utils.IsRecursiveFilter(f)).length || this.props.docRangeFilters().length ? "inheritsFilter" : undefined;
-    }
-    rootSelected = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false;
-    panelHeight = () => this.props.PanelHeight() - this.headerMargin;
-    screenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -this.headerMargin);
-    contentScaling = () => this.ContentScale;
-    onClickFunc = () => this.onClickHandler;
-    setHeight = (height: number) => this.layoutDoc._height = height;
-    setContentView = action((view: { getAnchor?: () => Doc, forward?: () => boolean, back?: () => boolean }) => this._componentView = view);
-    isContentActive = (outsideReaction?: boolean) => {
-        return this.props.isContentActive() === false ? false : (
-            CurrentUserUtils.SelectedTool !== InkTool.None ||
-            SnappingManager.GetIsDragging() ||
-            this.rootSelected() ||
-            this.props.Document.forceActive ||
-            this.props.isSelected(outsideReaction) ||
-            this._componentView?.isAnyChildContentActive?.() ||
-            this.props.isContentActive()) ? true : undefined;
-    }
-    @observable _retryThumb = 1;
-    thumbShown = () => {
-        return !this.props.isSelected() && LightboxView.LightboxDoc !== this.rootDoc && this.thumb &&
-            !Doc.AreProtosEqual(DocumentLinksButton.StartLink, this.rootDoc) &&
-            !Doc.isBrushedHighlightedDegree(this.props.Document) &&
-            !this._componentView?.isAnyChildContentActive?.() ? true : false;
-    }
-    @computed get contents() {
-        TraceMobx();
-        const audioView = !this.layoutDoc._showAudio ? (null) :
-            <div className="documentView-audioBackground" onPointerDown={this.recordAudioAnnotation} onPointerEnter={this.onPointerEnter} >
-                <FontAwesomeIcon className="documentView-audioFont"
-                    style={{ color: [DocListCast(this.dataDoc[this.LayoutFieldKey + "-audioAnnotations"]).length ? "blue" : "gray", "green", "red"][this._mediaState] }}
-                    icon={!DocListCast(this.dataDoc[this.LayoutFieldKey + "-audioAnnotations"]).length ? "microphone" : "file-audio"} size="sm" />
+            if (!this.topMost) e?.stopPropagation(); // DocumentViews should stop propagation of this event
+            cm.displayMenu((e?.pageX || pageX || 0) - 15, (e?.pageY || pageY || 0) - 15);
+      }
+
+      collectionFilters = () => StrListCast(this.props.Document._docFilters);
+      collectionRangeDocFilters = () => StrListCast(this.props.Document._docRangeFilters);
+      @computed get showFilterIcon() {
+            return this.collectionFilters().length || this.collectionRangeDocFilters().length ? "hasFilter" :
+                  this.props.docFilters?.().filter(f => Utils.IsRecursiveFilter(f)).length || this.props.docRangeFilters().length ? "inheritsFilter" : undefined;
+      }
+      rootSelected = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false;
+      panelHeight = () => this.props.PanelHeight() - this.headerMargin;
+      screenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -this.headerMargin);
+      contentScaling = () => this.ContentScale;
+      onClickFunc = () => this.onClickHandler;
+      setHeight = (height: number) => this.layoutDoc._height = height;
+      setContentView = action((view: { getAnchor?: () => Doc, forward?: () => boolean, back?: () => boolean }) => this._componentView = view);
+      isContentActive = (outsideReaction?: boolean) => {
+            return this.props.isContentActive() === false ? false : (
+                  CurrentUserUtils.SelectedTool !== InkTool.None ||
+                  SnappingManager.GetIsDragging() ||
+                  this.rootSelected() ||
+                  this.props.Document.forceActive ||
+                  this.props.isSelected(outsideReaction) ||
+                  this._componentView?.isAnyChildContentActive?.() ||
+                  this.props.isContentActive()) ? true : undefined;
+      }
+      @observable _retryThumb = 1;
+      thumbShown = () => {
+            return !this.props.isSelected() && LightboxView.LightboxDoc !== this.rootDoc && this.thumb &&
+                  !Doc.AreProtosEqual(DocumentLinksButton.StartLink, this.rootDoc) &&
+                  !Doc.isBrushedHighlightedDegree(this.props.Document) &&
+                  !this._componentView?.isAnyChildContentActive?.() ? true : false;
+      }
+      @computed get contents() {
+            TraceMobx();
+            const audioView = !this.layoutDoc._showAudio ? (null) :
+                  <div className="documentView-audioBackground" onPointerDown={this.recordAudioAnnotation} onPointerEnter={this.onPointerEnter} >
+                        <FontAwesomeIcon className="documentView-audioFont"
+                              style={{ color: [DocListCast(this.dataDoc[this.LayoutFieldKey + "-audioAnnotations"]).length ? "blue" : "gray", "green", "red"][this._mediaState] }}
+                              icon={!DocListCast(this.dataDoc[this.LayoutFieldKey + "-audioAnnotations"]).length ? "microphone" : "file-audio"} size="sm" />
+                  </div>;
+
+            return <div className="documentView-contentsView"
+                  style={{
+                        pointerEvents: this.props.pointerEvents?.() as any ?? this.rootDoc.layoutKey === "layout_icon" ? "none" :
+                              this.props.contentPointerEvents as any ? this.props.contentPointerEvents as any :
+                                    this.rootDoc.type !== DocumentType.INK && this.isContentActive() ? "all" :
+                                          "none",
+                        height: this.headerMargin ? `calc(100% - ${this.headerMargin}px)` : undefined,
+                  }}>
+                  {!this._retryThumb || !this.thumbShown() ? (null) :
+                        <img style={{ background: "white", top: 0, position: "relative" }} src={this.thumb} // + '?d=' + (new Date()).getTime()}
+                              width={this.props.PanelWidth()} height={this.props.PanelHeight()}
+                              onError={(e: any) => {
+                                    setTimeout(action(() => this._retryThumb = 0), 0);
+                                    setTimeout(action(() => this._retryThumb = 1), 150);
+                              }} />}
+                  <DocumentContentsView key={1}
+                        {...this.props}
+                        docViewPath={this.props.viewPath}
+                        thumbShown={this.thumbShown}
+                        isHovering={this.isHovering}
+                        setContentView={this.setContentView}
+                        scaling={this.contentScaling}
+                        PanelHeight={this.panelHeight}
+                        setHeight={!this.props.suppressSetHeight ? this.setHeight : undefined}
+                        isContentActive={this.isContentActive}
+                        ScreenToLocalTransform={this.screenToLocal}
+                        rootSelected={this.rootSelected}
+                        onClick={this.onClickFunc}
+                        focus={this.focus}
+                        layoutKey={this.finalLayoutKey} />
+                  {this.layoutDoc.hideAllLinks ? (null) : this.allLinkEndpoints}
+                  {(!this.props.isSelected() && !this._isHovering) || this.hideLinkButton || this.props.renderDepth === -1 || SnappingManager.GetIsDragging() ? (null) :
+                        <DocumentLinksButton View={this.props.DocumentView()}
+                              ContentScaling={this.props.ContentScaling}
+                              Offset={[this.topMost ? 0 : !this.props.isSelected() ? - 15 : -30, undefined, undefined, this.topMost ? 10 : !this.props.isSelected() ? - 15 : -30]} />
+                  }
+                  {audioView}
             </div>;
-
-        return <div className="documentView-contentsView"
-            style={{
-                pointerEvents: this.props.pointerEvents?.() as any ?? this.rootDoc.layoutKey === "layout_icon" ? "none" :
-                    this.props.contentPointerEvents as any ? this.props.contentPointerEvents as any :
-                        this.rootDoc.type !== DocumentType.INK && this.isContentActive() ? "all" :
-                            "none",
-                height: this.headerMargin ? `calc(100% - ${this.headerMargin}px)` : undefined,
-            }}>
-            {!this._retryThumb || !this.thumbShown() ? (null) :
-                <img style={{ background: "white", top: 0, position: "relative" }} src={this.thumb} // + '?d=' + (new Date()).getTime()}
-                    width={this.props.PanelWidth()} height={this.props.PanelHeight()}
-                    onError={(e: any) => {
-                        setTimeout(action(() => this._retryThumb = 0), 0);
-                        setTimeout(action(() => this._retryThumb = 1), 150);
-                    }} />}
-            <DocumentContentsView key={1}
-                {...this.props}
-                docViewPath={this.props.viewPath}
-                thumbShown={this.thumbShown}
-                isHovering={this.isHovering}
-                setContentView={this.setContentView}
-                scaling={this.contentScaling}
-                PanelHeight={this.panelHeight}
-                setHeight={!this.props.suppressSetHeight ? this.setHeight : undefined}
-                isContentActive={this.isContentActive}
-                ScreenToLocalTransform={this.screenToLocal}
-                rootSelected={this.rootSelected}
-                onClick={this.onClickFunc}
-                focus={this.focus}
-                layoutKey={this.finalLayoutKey} />
-            {this.layoutDoc.hideAllLinks ? (null) : this.allLinkEndpoints}
-            {(!this.props.isSelected() && !this._isHovering) || this.hideLinkButton || this.props.renderDepth === -1 || SnappingManager.GetIsDragging() ? (null) :
-                <DocumentLinksButton View={this.props.DocumentView()}
-                    ContentScaling={this.props.ContentScaling}
-                    Offset={[this.topMost ? 0 : !this.props.isSelected() ? - 15 : -30, undefined, undefined, this.topMost ? 10 : !this.props.isSelected() ? - 15 : -30]} />
+      }
+
+      get indicatorIcon() {
+            if (this.props.Document["acl-Public"] !== SharingPermissions.None) return "globe-americas";
+            else if (this.props.Document.numGroupsShared || NumCast(this.props.Document.numUsersShared, 0) > 1) return "users";
+            else return "user";
+      }
+
+      @undoBatch
+      hideLinkAnchor = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && (doc.hidden = true), true)
+      anchorPanelWidth = () => this.props.PanelWidth() || 1;
+      anchorPanelHeight = () => this.props.PanelHeight() || 1;
+      anchorStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any => {
+            switch (property) {
+                  case StyleProp.ShowTitle: return "";
+                  case StyleProp.PointerEvents: return "none";
+                  case StyleProp.LinkSource: return this.props.Document;// pass the LinkSource to the LinkAnchorBox
+                  default: return this.props.styleProvider?.(doc, props, property);
             }
-            {audioView}
-        </div>;
-    }
-
-    get indicatorIcon() {
-        if (this.props.Document["acl-Public"] !== SharingPermissions.None) return "globe-americas";
-        else if (this.props.Document.numGroupsShared || NumCast(this.props.Document.numUsersShared, 0) > 1) return "users";
-        else return "user";
-    }
-
-    @undoBatch
-    hideLinkAnchor = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && (doc.hidden = true), true)
-    anchorPanelWidth = () => this.props.PanelWidth() || 1;
-    anchorPanelHeight = () => this.props.PanelHeight() || 1;
-    anchorStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any => {
-        switch (property) {
-            case StyleProp.ShowTitle: return "";
-            case StyleProp.PointerEvents: return "none";
-            case StyleProp.LinkSource: return this.props.Document;// pass the LinkSource to the LinkAnchorBox
-            default: return this.props.styleProvider?.(doc, props, property);
-        }
-    }
-    // We need to use allrelatedLinks to get not just links to the document as a whole, but links to 
-    // anchors that are not rendered as DocumentViews (marked as 'unrendered' with their 'annotationOn' set to this document).  e.g., 
-    //     - PDF text regions are rendered as an Annotations without generating a DocumentView, '
-    //     - RTF selections are rendered via Prosemirror and have a mark which contains the Document ID for the annotation link
-    //     - and links to PDF/Web docs at a certain scroll location never create an explicit view.
-    // For each of these, we create LinkAnchorBox's on the border of the DocumentView.
-    @computed get directLinks() {
-        TraceMobx(); return LinkManager.Instance.getAllRelatedLinks(this.rootDoc).filter(link =>
-            Doc.AreProtosEqual(link.anchor1 as Doc, this.rootDoc) ||
-            Doc.AreProtosEqual(link.anchor2 as Doc, this.rootDoc) ||
-            ((link.anchor1 as Doc).unrendered && Doc.AreProtosEqual((link.anchor1 as Doc).annotationOn as Doc, this.rootDoc)) ||
-            ((link.anchor2 as Doc).unrendered && Doc.AreProtosEqual((link.anchor2 as Doc).annotationOn as Doc, this.rootDoc))
-        );
-    }
-    @computed get allLinks() { TraceMobx(); return LinkManager.Instance.getAllRelatedLinks(this.rootDoc); }
-    @computed get allLinkEndpoints() {  // the small blue dots that mark the endpoints of links
-        TraceMobx();
-        if (this.layoutDoc.unrendered || this.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) return null;
-        if (this.layoutDoc.presBox || this.rootDoc.type === DocumentType.LINK || this.props.dontRegisterView) return (null);
-        const filtered = DocUtils.FilterDocs(this.directLinks, this.props.docFilters?.() ?? [], []).filter(d => !d.hidden);
-        return filtered.map((link, i) =>
-            <div className="documentView-anchorCont" key={link[Id]}>
-                <DocumentView {...this.props}
-                    Document={link}
-                    PanelWidth={this.anchorPanelWidth}
-                    PanelHeight={this.anchorPanelHeight}
-                    dontRegisterView={false}
-                    showTitle={returnEmptyString}
-                    hideCaptions={true}
-                    fitWidth={returnTrue}
-                    styleProvider={this.anchorStyleProvider}
-                    removeDocument={this.hideLinkAnchor}
-                    LayoutTemplate={undefined}
-                    LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(link, this.rootDoc)}`)} />
-            </div >);
-    }
-
-    @action
-    onPointerEnter = () => {
-        const self = this;
-        const audioAnnos = DocListCast(this.dataDoc[this.LayoutFieldKey + "-audioAnnotations"]);
-        if (audioAnnos && audioAnnos.length && this._mediaState === 0) {
-            const anno = audioAnnos[Math.floor(Math.random() * audioAnnos.length)];
-            anno.data instanceof AudioField && new Howl({
-                src: [anno.data.url.href],
-                format: ["mp3"],
-                autoplay: true,
-                loop: false,
-                volume: 0.5,
-                onend: function () {
-                    runInAction(() => self._mediaState = 0);
-                }
-            });
-            this._mediaState = 1;
-        }
-    }
-    recordAudioAnnotation = () => {
-        let gumStream: any;
-        let recorder: any;
-        const self = this;
-        navigator.mediaDevices.getUserMedia({
-            audio: true
-        }).then(function (stream) {
-            gumStream = stream;
-            recorder = new MediaRecorder(stream);
-            recorder.ondataavailable = async (e: any) => {
-                const [{ result }] = await Networking.UploadFilesToServer(e.data);
-                if (!(result instanceof Error)) {
-                    const audioDoc = Docs.Create.AudioDocument(result.accessPaths.agnostic.client, { title: "audio test", _width: 200, _height: 32 });
-                    audioDoc.treeViewExpandedView = "layout";
-                    const audioAnnos = Cast(self.dataDoc[self.LayoutFieldKey + "-audioAnnotations"], listSpec(Doc));
-                    if (audioAnnos === undefined) {
-                        self.dataDoc[self.LayoutFieldKey + "-audioAnnotations"] = new List([audioDoc]);
-                    } else {
-                        audioAnnos.push(audioDoc);
-                    }
-                }
-            };
-            runInAction(() => self._mediaState = 2);
-            recorder.start();
-            setTimeout(() => {
-                recorder.stop();
-                runInAction(() => self._mediaState = 0);
-                gumStream.getAudioTracks()[0].stop();
-            }, 5000);
-        });
-    }
-
-    captionStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewInternalProps>, property: string) => this.props?.styleProvider?.(doc, props, property + ":caption");
-    @computed get innards() {
-        TraceMobx();
-        const ffscale = () => (this.props.DocumentView().props.CollectionFreeFormDocumentView?.().props.ScreenToLocalTransform().Scale || 1);
-        const showTitle = this.ShowTitle?.split(":")[0];
-        const showTitleHover = this.ShowTitle?.includes(":hover");
-        const showCaption = !this.props.hideCaptions && this.Document._viewType !== CollectionViewType.Carousel ? StrCast(this.layoutDoc._showCaption) : undefined;
-        const captionView = !showCaption ? (null) :
-            <div className="documentView-captionWrapper"
-                style={{
-                    pointerEvents: this.onClickHandler || this.Document.ignoreClick ? "none" : this.isContentActive() || this.props.isDocumentActive?.() ? "all" : undefined,
-                    minWidth: 50 * ffscale(),
-                    maxHeight: `max(100%, ${20 * ffscale()}px)`
-                }}>
-                <FormattedTextBox {...OmitKeys(this.props, ['children']).omit}
-                    yPadding={10}
-                    xPadding={10}
-                    fieldKey={showCaption}
-                    fontSize={12 * Math.max(1, 2 * ffscale() / 3)}
-                    styleProvider={this.captionStyleProvider}
-                    dontRegisterView={true}
-                    noSidebar={true}
-                    dontScale={true}
-                    isContentActive={this.isContentActive}
-                    onClick={this.onClickFunc}
-                />
-            </div>;
-        const targetDoc = (showTitle?.startsWith("_") ? this.layoutDoc : this.rootDoc);
-        const background = StrCast(SharingManager.Instance.users.find(users => users.user.email === this.dataDoc.author)?.sharingDoc.userColor,
-            Doc.UserDoc().showTitle && [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().userColor) : "rgba(0,0,0,0.4)");
-        const titleView = !showTitle ? (null) :
-            <div className={`documentView-titleWrapper${showTitleHover ? "-hover" : ""}`} key="title" style={{
-                position: this.headerMargin ? "relative" : "absolute",
-                height: this.titleHeight,
-                color: lightOrDark(background),
-                background,
-                pointerEvents: this.onClickHandler || this.Document.ignoreClick ? "none" : this.isContentActive() || this.props.isDocumentActive?.() ? "all" : undefined,
-            }}>
-                <EditableView ref={this._titleRef}
-                    contents={showTitle.split(";").map(field => field.trim()).map(field => targetDoc[field]?.toString()).join("\\")}
-                    display={"block"}
-                    fontSize={10}
-                    GetValue={() => showTitle.split(";").length === 1 ? showTitle + "=" + Field.toString(targetDoc[showTitle.split(";")[0]] as any as Field) : "#" + showTitle}
-                    SetValue={undoBatch((input: string) => {
-                        if (input?.startsWith("#")) {
-                            if (this.props.showTitle) {
-                                this.rootDoc._showTitle = input?.substring(1) ? input.substring(1) : undefined;
-                            } else {
-                                Doc.UserDoc().showTitle = input?.substring(1) ? input.substring(1) : "creationDate";
-                            }
-                        } else {
-                            var value = input.replace(new RegExp(showTitle + "="), "") as string | number;
-                            if (showTitle !== "title" && Number(value).toString() === value) value = Number(value);
-                            if (showTitle.includes("Date") || showTitle === "author") return true;
-                            Doc.SetInPlace(targetDoc, showTitle, value, true);
+      }
+      // We need to use allrelatedLinks to get not just links to the document as a whole, but links to 
+      // anchors that are not rendered as DocumentViews (marked as 'unrendered' with their 'annotationOn' set to this document).  e.g., 
+      //     - PDF text regions are rendered as an Annotations without generating a DocumentView, '
+      //     - RTF selections are rendered via Prosemirror and have a mark which contains the Document ID for the annotation link
+      //     - and links to PDF/Web docs at a certain scroll location never create an explicit view.
+      // For each of these, we create LinkAnchorBox's on the border of the DocumentView.
+      @computed get directLinks() {
+            TraceMobx(); return LinkManager.Instance.getAllRelatedLinks(this.rootDoc).filter(link =>
+                  Doc.AreProtosEqual(link.anchor1 as Doc, this.rootDoc) ||
+                  Doc.AreProtosEqual(link.anchor2 as Doc, this.rootDoc) ||
+                  ((link.anchor1 as Doc).unrendered && Doc.AreProtosEqual((link.anchor1 as Doc).annotationOn as Doc, this.rootDoc)) ||
+                  ((link.anchor2 as Doc).unrendered && Doc.AreProtosEqual((link.anchor2 as Doc).annotationOn as Doc, this.rootDoc))
+            );
+      }
+      @computed get allLinks() { TraceMobx(); return LinkManager.Instance.getAllRelatedLinks(this.rootDoc); }
+      @computed get allLinkEndpoints() {  // the small blue dots that mark the endpoints of links
+            TraceMobx();
+            if (this.layoutDoc.unrendered || this.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) return null;
+            if (this.layoutDoc.presBox || this.rootDoc.type === DocumentType.LINK || this.props.dontRegisterView) return (null);
+            const filtered = DocUtils.FilterDocs(this.directLinks, this.props.docFilters?.() ?? [], []).filter(d => !d.hidden);
+            return filtered.map((link, i) =>
+                  <div className="documentView-anchorCont" key={link[Id]}>
+                        <DocumentView {...this.props}
+                              Document={link}
+                              PanelWidth={this.anchorPanelWidth}
+                              PanelHeight={this.anchorPanelHeight}
+                              dontRegisterView={false}
+                              showTitle={returnEmptyString}
+                              hideCaptions={true}
+                              fitWidth={returnTrue}
+                              styleProvider={this.anchorStyleProvider}
+                              removeDocument={this.hideLinkAnchor}
+                              LayoutTemplate={undefined}
+                              LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(link, this.rootDoc)}`)} />
+                  </div >);
+      }
+
+      @action
+      onPointerEnter = () => {
+            const self = this;
+            const audioAnnos = DocListCast(this.dataDoc[this.LayoutFieldKey + "-audioAnnotations"]);
+            if (audioAnnos && audioAnnos.length && this._mediaState === 0) {
+                  const anno = audioAnnos[Math.floor(Math.random() * audioAnnos.length)];
+                  anno.data instanceof AudioField && new Howl({
+                        src: [anno.data.url.href],
+                        format: ["mp3"],
+                        autoplay: true,
+                        loop: false,
+                        volume: 0.5,
+                        onend: function () {
+                              runInAction(() => self._mediaState = 0);
                         }
-                        return true;
-                    })}
-                />
-            </div>;
-        return this.props.hideTitle || (!showTitle && !showCaption) ?
-            this.contents :
-            <div className="documentView-styleWrapper" >
-                {!this.headerMargin ? <> {this.contents} {titleView} </> : <> {titleView} {this.contents} </>}
-                {captionView}
-            </div>;
-    }
-    isHovering = () => this._isHovering;
-    @observable _isHovering = false;
-    @observable _: string = "";
-    @computed get renderDoc() {
-        TraceMobx();
-        const thumb = ImageCast(this.layoutDoc["thumb-frozen"], ImageCast(this.layoutDoc.thumb))?.url.href.replace(".png", "_m.png");
-        const isButton = this.props.Document.type === DocumentType.FONTICON;
-        if (!(this.props.Document instanceof Doc) || GetEffectiveAcl(this.props.Document[DataSym]) === AclPrivate || (this.hidden && !this.props.treeViewDoc)) return null;
-        return this.docContents ??
-            <div className={`documentView-node${this.topMost ? "-topmost" : ""}`}
-                id={this.props.Document[Id]}
-                onPointerEnter={action(() => this._isHovering = true)}
-                onPointerLeave={action(() => this._isHovering = false)}
-                style={{
-                    background: isButton || thumb ? undefined : this.backgroundColor,
-                    opacity: this.opacity,
-                    color: StrCast(this.layoutDoc.color, "inherit"),
-                    fontFamily: StrCast(this.Document._fontFamily, "inherit"),
-                    fontSize: Cast(this.Document._fontSize, "string", null),
-                    transform: this._animateScalingTo ? `scale(${this._animateScalingTo})` : undefined,
-                    transition: !this._animateScalingTo ? StrCast(this.Document.dataTransition) : `transform ${this._animateScaleTime / 1000}s ease-${this._animateScalingTo < 1 ? "in" : "out"}`,
-                }}>
-
-                {this.innards}
-                {this.onClickHandler && this.props.ContainingCollectionView?.props.Document._viewType === CollectionViewType.Time ? <div className="documentView-contentBlocker" /> : (null)}
-                {this.widgetDecorations ?? null}
-            </div>;
-    }
-    render() {
-        TraceMobx();
-        const highlightIndex = this.props.LayoutTemplateString ? (Doc.IsHighlighted(this.props.Document) ? 6 : 0) : Doc.isBrushedHighlightedDegree(this.props.Document); // bcz: Argh!! need to identify a tree view doc better than a LayoutTemlatString
-        const highlightColor = ["transparent", "rgb(68, 118, 247)", "rgb(68, 118, 247)", "orange", "lightBlue"][highlightIndex];
-        const highlightStyle = ["solid", "dashed", "solid", "solid", "solid"][highlightIndex];
-        const excludeTypes = !this.props.treeViewDoc && highlightIndex < 3 ? [DocumentType.FONTICON, DocumentType.INK] : [DocumentType.FONTICON];
-        let highlighting = !this.props.disableDocBrushing && highlightIndex && !excludeTypes.includes(this.layoutDoc.type as any) && this.layoutDoc._viewType !== CollectionViewType.Linear;
-        highlighting = highlighting && this.props.focus !== emptyFunction && this.layoutDoc.title !== "[pres element template]";  // bcz: hack to turn off highlighting onsidebar panel documents.  need to flag a document as not highlightable in a more direct way
-
-        const borderPath = this.props.styleProvider?.(this.props.Document, this.props, StyleProp.BorderPath) || { path: undefined };
-        const internal = PresBox.EffectsProvider(this.layoutDoc, this.renderDoc) || this.renderDoc;
-        const boxShadow = this.props.treeViewDoc ? null : highlighting && this.borderRounding && highlightStyle !== "dashed" ? `0 0 0 ${highlightIndex}px ${highlightColor}` :
-            this.boxShadow || (this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" : undefined);
-
-        // Return surrounding highlight 
-        return <div className={`${DocumentView.ROOT_DIV} docView-hack`} ref={this._mainCont}
-            onContextMenu={this.onContextMenu}
-            onKeyDown={this.onKeyDown}
-            onPointerDown={this.onPointerDown}
-            onClick={this.onClick}
-            onPointerEnter={action(e => !SnappingManager.GetIsDragging() && Doc.BrushDoc(this.props.Document))}
-            onPointerLeave={action(e => !hasDescendantTarget(e.nativeEvent.x, e.nativeEvent.y, this.ContentDiv) && Doc.UnBrushDoc(this.props.Document))}
-            style={{
-                display: this.hidden ? "inline" : undefined,
-                borderRadius: this.borderRounding,
-                pointerEvents: this.pointerEvents,
-                outline: highlighting && !this.borderRounding ? `${highlightColor} ${highlightStyle} ${highlightIndex}px` : "solid 0px",
-                border: highlighting && this.borderRounding && highlightStyle === "dashed" ? `${highlightStyle} ${highlightColor} ${highlightIndex}px` : undefined,
-                boxShadow,
-                clipPath: borderPath.path ? `path('${borderPath.path}')` : undefined
-            }}>
-            {!borderPath.path ? internal :
-                <>
-                    {/* <div style={{ clipPath: `path('${borderPath.fill}')` }}>
+                  });
+                  this._mediaState = 1;
+            }
+      }
+      recordAudioAnnotation = () => {
+            let gumStream: any;
+            let recorder: any;
+            const self = this;
+            navigator.mediaDevices.getUserMedia({
+                  audio: true
+            }).then(function (stream) {
+                  gumStream = stream;
+                  recorder = new MediaRecorder(stream);
+                  recorder.ondataavailable = async (e: any) => {
+                        const [{ result }] = await Networking.UploadFilesToServer(e.data);
+                        if (!(result instanceof Error)) {
+                              const audioDoc = Docs.Create.AudioDocument(result.accessPaths.agnostic.client, { title: "audio test", _width: 200, _height: 32 });
+                              audioDoc.treeViewExpandedView = "layout";
+                              const audioAnnos = Cast(self.dataDoc[self.LayoutFieldKey + "-audioAnnotations"], listSpec(Doc));
+                              if (audioAnnos === undefined) {
+                                    self.dataDoc[self.LayoutFieldKey + "-audioAnnotations"] = new List([audioDoc]);
+                              } else {
+                                    audioAnnos.push(audioDoc);
+                              }
+                        }
+                  };
+                  runInAction(() => self._mediaState = 2);
+                  recorder.start();
+                  setTimeout(() => {
+                        recorder.stop();
+                        runInAction(() => self._mediaState = 0);
+                        gumStream.getAudioTracks()[0].stop();
+                  }, 5000);
+            });
+      }
+
+      captionStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewInternalProps>, property: string) => this.props?.styleProvider?.(doc, props, property + ":caption");
+      @computed get innards() {
+            TraceMobx();
+            const ffscale = () => (this.props.DocumentView().props.CollectionFreeFormDocumentView?.().props.ScreenToLocalTransform().Scale || 1);
+            const showTitle = this.ShowTitle?.split(":")[0];
+            const showTitleHover = this.ShowTitle?.includes(":hover");
+            const showCaption = !this.props.hideCaptions && this.Document._viewType !== CollectionViewType.Carousel ? StrCast(this.layoutDoc._showCaption) : undefined;
+            const captionView = !showCaption ? (null) :
+                  <div className="documentView-captionWrapper"
+                        style={{
+                              pointerEvents: this.onClickHandler || this.Document.ignoreClick ? "none" : this.isContentActive() || this.props.isDocumentActive?.() ? "all" : undefined,
+                              minWidth: 50 * ffscale(),
+                              maxHeight: `max(100%, ${20 * ffscale()}px)`
+                        }}>
+                        <FormattedTextBox {...OmitKeys(this.props, ['children']).omit}
+                              yPadding={10}
+                              xPadding={10}
+                              fieldKey={showCaption}
+                              fontSize={12 * Math.max(1, 2 * ffscale() / 3)}
+                              styleProvider={this.captionStyleProvider}
+                              dontRegisterView={true}
+                              noSidebar={true}
+                              dontScale={true}
+                              isContentActive={this.isContentActive}
+                              onClick={this.onClickFunc}
+                        />
+                  </div>;
+            const targetDoc = (showTitle?.startsWith("_") ? this.layoutDoc : this.rootDoc);
+            const background = StrCast(SharingManager.Instance.users.find(users => users.user.email === this.dataDoc.author)?.sharingDoc.userColor,
+                  Doc.UserDoc().showTitle && [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().userColor) : "rgba(0,0,0,0.4)");
+            const titleView = !showTitle ? (null) :
+                  <div className={`documentView-titleWrapper${showTitleHover ? "-hover" : ""}`} key="title" style={{
+                        position: this.headerMargin ? "relative" : "absolute",
+                        height: this.titleHeight,
+                        color: lightOrDark(background),
+                        background,
+                        pointerEvents: this.onClickHandler || this.Document.ignoreClick ? "none" : this.isContentActive() || this.props.isDocumentActive?.() ? "all" : undefined,
+                  }}>
+                        <EditableView ref={this._titleRef}
+                              contents={showTitle.split(";").map(field => field.trim()).map(field => targetDoc[field]?.toString()).join("\\")}
+                              display={"block"}
+                              fontSize={10}
+                              GetValue={() => showTitle.split(";").length === 1 ? showTitle + "=" + Field.toString(targetDoc[showTitle.split(";")[0]] as any as Field) : "#" + showTitle}
+                              SetValue={undoBatch((input: string) => {
+                                    if (input?.startsWith("#")) {
+                                          if (this.props.showTitle) {
+                                                this.rootDoc._showTitle = input?.substring(1) ? input.substring(1) : undefined;
+                                          } else {
+                                                Doc.UserDoc().showTitle = input?.substring(1) ? input.substring(1) : "creationDate";
+                                          }
+                                    } else {
+                                          var value = input.replace(new RegExp(showTitle + "="), "") as string | number;
+                                          if (showTitle !== "title" && Number(value).toString() === value) value = Number(value);
+                                          if (showTitle.includes("Date") || showTitle === "author") return true;
+                                          Doc.SetInPlace(targetDoc, showTitle, value, true);
+                                    }
+                                    return true;
+                              })}
+                        />
+                  </div>;
+            return this.props.hideTitle || (!showTitle && !showCaption) ?
+                  this.contents :
+                  <div className="documentView-styleWrapper" >
+                        {!this.headerMargin ? <> {this.contents} {titleView} </> : <> {titleView} {this.contents} </>}
+                        {captionView}
+                  </div>;
+      }
+      isHovering = () => this._isHovering;
+      @observable _isHovering = false;
+      @observable _: string = "";
+      @computed get renderDoc() {
+            TraceMobx();
+            const thumb = ImageCast(this.layoutDoc["thumb-frozen"], ImageCast(this.layoutDoc.thumb))?.url.href.replace(".png", "_m.png");
+            const isButton = this.props.Document.type === DocumentType.FONTICON;
+            if (!(this.props.Document instanceof Doc) || GetEffectiveAcl(this.props.Document[DataSym]) === AclPrivate || (this.hidden && !this.props.treeViewDoc)) return null;
+            return this.docContents ??
+                  <div className={`documentView-node${this.topMost ? "-topmost" : ""}`}
+                        id={this.props.Document[Id]}
+                        onPointerEnter={action(() => this._isHovering = true)}
+                        onPointerLeave={action(() => this._isHovering = false)}
+                        style={{
+                              background: isButton || thumb ? undefined : this.backgroundColor,
+                              opacity: this.opacity,
+                              color: StrCast(this.layoutDoc.color, "inherit"),
+                              fontFamily: StrCast(this.Document._fontFamily, "inherit"),
+                              fontSize: Cast(this.Document._fontSize, "string", null),
+                              transform: this._animateScalingTo ? `scale(${this._animateScalingTo})` : undefined,
+                              transition: !this._animateScalingTo ? StrCast(this.Document.dataTransition) : `transform ${this._animateScaleTime / 1000}s ease-${this._animateScalingTo < 1 ? "in" : "out"}`,
+                        }}>
+
+                        {this.innards}
+                        {this.onClickHandler && this.props.ContainingCollectionView?.props.Document._viewType === CollectionViewType.Time ? <div className="documentView-contentBlocker" /> : (null)}
+                        {this.widgetDecorations ?? null}
+                  </div>;
+      }
+      render() {
+            TraceMobx();
+            const highlightIndex = this.props.LayoutTemplateString ? (Doc.IsHighlighted(this.props.Document) ? 6 : 0) : Doc.isBrushedHighlightedDegree(this.props.Document); // bcz: Argh!! need to identify a tree view doc better than a LayoutTemlatString
+            const highlightColor = ["transparent", "rgb(68, 118, 247)", "rgb(68, 118, 247)", "orange", "lightBlue"][highlightIndex];
+            const highlightStyle = ["solid", "dashed", "solid", "solid", "solid"][highlightIndex];
+            const excludeTypes = !this.props.treeViewDoc && highlightIndex < 3 ? [DocumentType.FONTICON, DocumentType.INK] : [DocumentType.FONTICON];
+            let highlighting = !this.props.disableDocBrushing && highlightIndex && !excludeTypes.includes(this.layoutDoc.type as any) && this.layoutDoc._viewType !== CollectionViewType.Linear;
+            highlighting = highlighting && this.props.focus !== emptyFunction && this.layoutDoc.title !== "[pres element template]";  // bcz: hack to turn off highlighting onsidebar panel documents.  need to flag a document as not highlightable in a more direct way
+
+            const borderPath = this.props.styleProvider?.(this.props.Document, this.props, StyleProp.BorderPath) || { path: undefined };
+            const internal = PresBox.EffectsProvider(this.layoutDoc, this.renderDoc) || this.renderDoc;
+            const boxShadow = this.props.treeViewDoc ? null : highlighting && this.borderRounding && highlightStyle !== "dashed" ? `0 0 0 ${highlightIndex}px ${highlightColor}` :
+                  this.boxShadow || (this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" : undefined);
+
+            // Return surrounding highlight 
+            return <div className={`${DocumentView.ROOT_DIV} docView-hack`} ref={this._mainCont}
+                  onContextMenu={this.onContextMenu}
+                  onKeyDown={this.onKeyDown}
+                  onPointerDown={this.onPointerDown}
+                  onClick={this.onClick}
+                  onPointerEnter={action(e => !SnappingManager.GetIsDragging() && Doc.BrushDoc(this.props.Document))}
+                  onPointerLeave={action(e => !hasDescendantTarget(e.nativeEvent.x, e.nativeEvent.y, this.ContentDiv) && Doc.UnBrushDoc(this.props.Document))}
+                  style={{
+                        display: this.hidden ? "inline" : undefined,
+                        borderRadius: this.borderRounding,
+                        pointerEvents: this.pointerEvents,
+                        outline: highlighting && !this.borderRounding ? `${highlightColor} ${highlightStyle} ${highlightIndex}px` : "solid 0px",
+                        border: highlighting && this.borderRounding && highlightStyle === "dashed" ? `${highlightStyle} ${highlightColor} ${highlightIndex}px` : undefined,
+                        boxShadow,
+                        clipPath: borderPath.path ? `path('${borderPath.path}')` : undefined
+                  }}>
+                  {!borderPath.path ? internal :
+                        <>
+                              {/* <div style={{ clipPath: `path('${borderPath.fill}')` }}>
                         {internal}
                     </div> */}
-                    {internal}
-                    <div key="border2" className="documentView-customBorder" style={{ pointerEvents: "none" }} >
-                        <svg style={{ overflow: "visible" }} viewBox={`0 0 ${this.props.PanelWidth()} ${this.props.PanelHeight()}`}>
-                            <path d={borderPath.path} style={{ stroke: "black", fill: "transparent", strokeWidth: borderPath.width }} />
-                        </svg>
-                    </div>
-                </>
-            }
-            {this.showFilterIcon ?
-                <FontAwesomeIcon icon={"filter"} size="lg"
-                    style={{ position: 'absolute', top: '1%', right: '1%', cursor: "pointer", padding: 1, color: this.showFilterIcon === "hasFilter" ? '#18c718bd' : "orange", zIndex: 1 }}
-                    onPointerDown={action(e => { this.props.select(false); CurrentUserUtils.propertiesWidth = 250; e.stopPropagation(); })}
-                />
-                : (null)}
-        </div>;
-    }
+                              {internal}
+                              <div key="border2" className="documentView-customBorder" style={{ pointerEvents: "none" }} >
+                                    <svg style={{ overflow: "visible" }} viewBox={`0 0 ${this.props.PanelWidth()} ${this.props.PanelHeight()}`}>
+                                          <path d={borderPath.path} style={{ stroke: "black", fill: "transparent", strokeWidth: borderPath.width }} />
+                                    </svg>
+                              </div>
+                        </>
+                  }
+                  {this.showFilterIcon ?
+                        <FontAwesomeIcon icon={"filter"} size="lg"
+                              style={{ position: 'absolute', top: '1%', right: '1%', cursor: "pointer", padding: 1, color: this.showFilterIcon === "hasFilter" ? '#18c718bd' : "orange", zIndex: 1 }}
+                              onPointerDown={action(e => { this.props.select(false); CurrentUserUtils.propertiesWidth = 250; e.stopPropagation(); })}
+                        />
+                        : (null)}
+            </div>;
+      }
 }
 
 @observer
 export class DocumentView extends React.Component<DocumentViewProps> {
-    public static ROOT_DIV = "documentView-effectsWrapper";
-    public get displayName() { return "DocumentView(" + this.props.Document?.title + ")"; } // this makes mobx trace() statements more descriptive
-    public ContentRef = React.createRef<HTMLDivElement>();
-    private _disposers: { [name: string]: IReactionDisposer } = {};
-
-    public static showBackLinks(linkSource: Doc) {
-        const docid = Doc.CurrentUserEmail + Doc.GetProto(linkSource)[Id] + "-pivotish";
-        DocServer.GetRefField(docid).then(docx => {
-            const rootAlias = () => {
-                const rootAlias = Doc.MakeAlias(linkSource);
-                rootAlias.x = rootAlias.y = 0;
-                return rootAlias;
-            };
-            const linkCollection = ((docx instanceof Doc) && docx) || Docs.Create.StackingDocument([/*rootAlias()*/], { title: linkSource.title + "-pivot", _width: 500, _height: 500, }, docid);
-            linkCollection.linkSource = linkSource;
-            if (!linkCollection.reactionScript) linkCollection.reactionScript = ScriptField.MakeScript("updateLinkCollection(self)");
-            LightboxView.SetLightboxDoc(linkCollection);
-        });
-    }
-
-    @observable public docView: DocumentViewInternal | undefined | null;
-
-    get Document() { return this.props.Document; }
-    get topMost() { return this.props.renderDepth === 0; }
-    get rootDoc() { return this.docView?.rootDoc || this.Document; }
-    get dataDoc() { return this.docView?.dataDoc || this.Document; }
-    get finalLayoutKey() { return this.docView?.finalLayoutKey || "layout"; }
-    get ContentDiv() { return this.docView?.ContentDiv; }
-    get ComponentView() { return this.docView?._componentView; }
-    get allLinks() { return this.docView?.allLinks || []; }
-    get LayoutFieldKey() { return this.docView?.LayoutFieldKey || "layout"; }
-    get fitWidth() { return this.props.fitWidth?.(this.rootDoc) || this.layoutDoc.fitWidth; }
-
-    @computed get docViewPath(): DocumentView[] { return this.props.docViewPath ? [...this.props.docViewPath(), this] : [this]; }
-    @computed get layoutDoc() { return Doc.Layout(this.Document, this.props.LayoutTemplate?.()); }
-    @computed get nativeWidth() {
-        return this.docView?._componentView?.reverseNativeScaling?.() ? 0 :
-            returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions));
-    }
-    @computed get nativeHeight() {
-        return this.docView?._componentView?.reverseNativeScaling?.() ? 0 :
-            returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions));
-    }
-    @computed get shouldNotScale() {
-        return (this.fitWidth && !this.nativeWidth) ||
-            this.props.dontScaleFilter?.(this.Document) ||
-            this.props.treeViewDoc || [CollectionViewType.Docking].includes(this.Document._viewType as any);
-    }
-    @computed get effectiveNativeWidth() { return this.shouldNotScale ? 0 : (this.nativeWidth || NumCast(this.layoutDoc.width)); }
-    @computed get effectiveNativeHeight() { return this.shouldNotScale ? 0 : (this.nativeHeight || NumCast(this.layoutDoc.height)); }
-    @computed get nativeScaling() {
-        if (this.shouldNotScale) return 1;
-        const minTextScale = this.Document.type === DocumentType.RTF ? 0.1 : 0;
-        if (this.fitWidth || this.props.PanelHeight() / (this.effectiveNativeHeight || 1) > this.props.PanelWidth() / (this.effectiveNativeWidth || 1)) {
-            return Math.max(minTextScale, this.props.PanelWidth() / (this.effectiveNativeWidth || 1));  // width-limited or fitWidth
-        }
-        return Math.max(minTextScale, this.props.PanelHeight() / (this.effectiveNativeHeight || 1)); // height-limited or unscaled
-    }
-
-    @computed get panelWidth() { return this.effectiveNativeWidth ? this.effectiveNativeWidth * this.nativeScaling : this.props.PanelWidth(); }
-    @computed get panelHeight() {
-        if (this.effectiveNativeHeight) {
-            return Math.min(this.props.PanelHeight(), Math.max(this.ComponentView?.getScrollHeight?.() ?? NumCast(this.layoutDoc.scrollHeight), this.effectiveNativeHeight) * this.nativeScaling);
-        }
-        return this.props.PanelHeight();
-    }
-    @computed get Xshift() { return this.effectiveNativeWidth ? (this.props.PanelWidth() - this.effectiveNativeWidth * this.nativeScaling) / 2 : 0; }
-    @computed get Yshift() { return this.effectiveNativeWidth && this.effectiveNativeHeight && Math.abs(this.Xshift) < 0.001 ? (this.props.PanelHeight() - this.effectiveNativeHeight * this.nativeScaling) / 2 : 0; }
-    @computed get centeringX() { return this.props.dontCenter?.includes("x") ? 0 : this.Xshift; }
-    @computed get centeringY() { return this.fitWidth || this.props.dontCenter?.includes("y") ? 0 : this.Yshift; }
-
-    toggleNativeDimensions = () => this.docView && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.ContentScale, this.props.PanelWidth(), this.props.PanelHeight());
-    focus = (doc: Doc, options?: DocFocusOptions) => this.docView?.focus(doc, options);
-    getBounds = () => {
-        if (!this.docView || !this.docView.ContentDiv || this.docView.props.treeViewDoc || Doc.AreProtosEqual(this.props.Document, Doc.UserDoc())) {
-            return undefined;
-        }
-        const xf = (this.docView?.props.ScreenToLocalTransform().scale(this.nativeScaling)).inverse();
-        const [[left, top], [right, bottom]] = [xf.transformPoint(0, 0), xf.transformPoint(this.panelWidth, this.panelHeight)];
-        if (this.docView.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
-            const docuBox = this.docView.ContentDiv.getElementsByClassName("linkAnchorBox-cont");
-            if (docuBox.length) return { ...docuBox[0].getBoundingClientRect(), center: undefined };
-        }
-        return { left, top, right, bottom, center: this.ComponentView?.getCenter?.(xf) };
-    }
-
-    public iconify(finished?: () => void) {
-        this.ComponentView?.updateIcon?.();
-        const layoutKey = Cast(this.Document.layoutKey, "string", null);
-        if (layoutKey !== "layout_icon") {
-            this.switchViews(true, "icon", finished);
-            if (layoutKey && layoutKey !== "layout" && layoutKey !== "layout_icon") this.Document.deiconifyLayout = layoutKey.replace("layout_", "");
-        } else {
-            const deiconifyLayout = Cast(this.Document.deiconifyLayout, "string", null);
-            this.switchViews(deiconifyLayout ? true : false, deiconifyLayout, finished);
-            this.Document.deiconifyLayout = undefined;
-            this.props.bringToFront(this.rootDoc);
-        }
-    }
-    @undoBatch
-    @action
-    setCustomView = (custom: boolean, layout: string): void => {
-        Doc.setNativeView(this.props.Document);
-        custom && DocUtils.makeCustomViewClicked(this.props.Document, Docs.Create.StackingDocument, layout, undefined);
-    }
-    switchViews = action((custom: boolean, view: string, finished?: () => void) => {
-        this.docView && (this.docView._animateScalingTo = 0.1);  // shrink doc
-        setTimeout(action(() => {
-            this.setCustomView(custom, view);
-            this.docView && (this.docView._animateScalingTo = 1); // expand it
+      public static ROOT_DIV = "documentView-effectsWrapper";
+      public get displayName() { return "DocumentView(" + this.props.Document?.title + ")"; } // this makes mobx trace() statements more descriptive
+      public ContentRef = React.createRef<HTMLDivElement>();
+      private _disposers: { [name: string]: IReactionDisposer } = {};
+
+      public static showBackLinks(linkSource: Doc) {
+            const docid = Doc.CurrentUserEmail + Doc.GetProto(linkSource)[Id] + "-pivotish";
+            DocServer.GetRefField(docid).then(docx => {
+                  const rootAlias = () => {
+                        const rootAlias = Doc.MakeAlias(linkSource);
+                        rootAlias.x = rootAlias.y = 0;
+                        return rootAlias;
+                  };
+                  const linkCollection = ((docx instanceof Doc) && docx) || Docs.Create.StackingDocument([/*rootAlias()*/], { title: linkSource.title + "-pivot", _width: 500, _height: 500, }, docid);
+                  linkCollection.linkSource = linkSource;
+                  if (!linkCollection.reactionScript) linkCollection.reactionScript = ScriptField.MakeScript("updateLinkCollection(self)");
+                  LightboxView.SetLightboxDoc(linkCollection);
+            });
+      }
+
+      @observable public docView: DocumentViewInternal | undefined | null;
+
+      get Document() { return this.props.Document; }
+      get topMost() { return this.props.renderDepth === 0; }
+      get rootDoc() { return this.docView?.rootDoc || this.Document; }
+      get dataDoc() { return this.docView?.dataDoc || this.Document; }
+      get finalLayoutKey() { return this.docView?.finalLayoutKey || "layout"; }
+      get ContentDiv() { return this.docView?.ContentDiv; }
+      get ComponentView() { return this.docView?._componentView; }
+      get allLinks() { return this.docView?.allLinks || []; }
+      get LayoutFieldKey() { return this.docView?.LayoutFieldKey || "layout"; }
+      get fitWidth() { return this.props.fitWidth?.(this.rootDoc) || this.layoutDoc.fitWidth; }
+
+      @computed get docViewPath(): DocumentView[] { return this.props.docViewPath ? [...this.props.docViewPath(), this] : [this]; }
+      @computed get layoutDoc() { return Doc.Layout(this.Document, this.props.LayoutTemplate?.()); }
+      @computed get nativeWidth() {
+            return this.docView?._componentView?.reverseNativeScaling?.() ? 0 :
+                  returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions));
+      }
+      @computed get nativeHeight() {
+            return this.docView?._componentView?.reverseNativeScaling?.() ? 0 :
+                  returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions));
+      }
+      @computed get shouldNotScale() {
+            return (this.fitWidth && !this.nativeWidth) ||
+                  this.props.dontScaleFilter?.(this.Document) ||
+                  this.props.treeViewDoc || [CollectionViewType.Docking].includes(this.Document._viewType as any);
+      }
+      @computed get effectiveNativeWidth() { return this.shouldNotScale ? 0 : (this.nativeWidth || NumCast(this.layoutDoc.width)); }
+      @computed get effectiveNativeHeight() { return this.shouldNotScale ? 0 : (this.nativeHeight || NumCast(this.layoutDoc.height)); }
+      @computed get nativeScaling() {
+            if (this.shouldNotScale) return 1;
+            const minTextScale = this.Document.type === DocumentType.RTF ? 0.1 : 0;
+            if (this.fitWidth || this.props.PanelHeight() / (this.effectiveNativeHeight || 1) > this.props.PanelWidth() / (this.effectiveNativeWidth || 1)) {
+                  return Math.max(minTextScale, this.props.PanelWidth() / (this.effectiveNativeWidth || 1));  // width-limited or fitWidth
+            }
+            return Math.max(minTextScale, this.props.PanelHeight() / (this.effectiveNativeHeight || 1)); // height-limited or unscaled
+      }
+
+      @computed get panelWidth() { return this.effectiveNativeWidth ? this.effectiveNativeWidth * this.nativeScaling : this.props.PanelWidth(); }
+      @computed get panelHeight() {
+            if (this.effectiveNativeHeight) {
+                  return Math.min(this.props.PanelHeight(), Math.max(this.ComponentView?.getScrollHeight?.() ?? NumCast(this.layoutDoc.scrollHeight), this.effectiveNativeHeight) * this.nativeScaling);
+            }
+            return this.props.PanelHeight();
+      }
+      @computed get Xshift() { return this.effectiveNativeWidth ? (this.props.PanelWidth() - this.effectiveNativeWidth * this.nativeScaling) / 2 : 0; }
+      @computed get Yshift() { return this.effectiveNativeWidth && this.effectiveNativeHeight && Math.abs(this.Xshift) < 0.001 ? (this.props.PanelHeight() - this.effectiveNativeHeight * this.nativeScaling) / 2 : 0; }
+      @computed get centeringX() { return this.props.dontCenter?.includes("x") ? 0 : this.Xshift; }
+      @computed get centeringY() { return this.fitWidth || this.props.dontCenter?.includes("y") ? 0 : this.Yshift; }
+
+      toggleNativeDimensions = () => this.docView && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.ContentScale, this.props.PanelWidth(), this.props.PanelHeight());
+      focus = (doc: Doc, options?: DocFocusOptions) => this.docView?.focus(doc, options);
+      getBounds = () => {
+            if (!this.docView || !this.docView.ContentDiv || this.docView.props.treeViewDoc || Doc.AreProtosEqual(this.props.Document, Doc.UserDoc())) {
+                  return undefined;
+            }
+            const xf = (this.docView?.props.ScreenToLocalTransform().scale(this.nativeScaling)).inverse();
+            const [[left, top], [right, bottom]] = [xf.transformPoint(0, 0), xf.transformPoint(this.panelWidth, this.panelHeight)];
+            if (this.docView.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
+                  const docuBox = this.docView.ContentDiv.getElementsByClassName("linkAnchorBox-cont");
+                  if (docuBox.length) return { ...docuBox[0].getBoundingClientRect(), center: undefined };
+            }
+            return { left, top, right, bottom, center: this.ComponentView?.getCenter?.(xf) };
+      }
+
+      public iconify(finished?: () => void) {
+            this.ComponentView?.updateIcon?.();
+            const layoutKey = Cast(this.Document.layoutKey, "string", null);
+            if (layoutKey !== "layout_icon") {
+                  this.switchViews(true, "icon", finished);
+                  if (layoutKey && layoutKey !== "layout" && layoutKey !== "layout_icon") this.Document.deiconifyLayout = layoutKey.replace("layout_", "");
+            } else {
+                  const deiconifyLayout = Cast(this.Document.deiconifyLayout, "string", null);
+                  this.switchViews(deiconifyLayout ? true : false, deiconifyLayout, finished);
+                  this.Document.deiconifyLayout = undefined;
+                  this.props.bringToFront(this.rootDoc);
+            }
+      }
+      @undoBatch
+      @action
+      setCustomView = (custom: boolean, layout: string): void => {
+            Doc.setNativeView(this.props.Document);
+            custom && DocUtils.makeCustomViewClicked(this.props.Document, Docs.Create.StackingDocument, layout, undefined);
+      }
+      switchViews = action((custom: boolean, view: string, finished?: () => void) => {
+            this.docView && (this.docView._animateScalingTo = 0.1);  // shrink doc
             setTimeout(action(() => {
-                this.docView && (this.docView._animateScalingTo = 0);
-                finished?.();
+                  this.setCustomView(custom, view);
+                  this.docView && (this.docView._animateScalingTo = 1); // expand it
+                  setTimeout(action(() => {
+                        this.docView && (this.docView._animateScalingTo = 0);
+                        finished?.();
+                  }), this.docView!._animateScaleTime - 10);
             }), this.docView!._animateScaleTime - 10);
-        }), this.docView!._animateScaleTime - 10);
-    });
-
-    startDragging = (x: number, y: number, dropAction: dropActionType, hideSource = false) => this.docView?.startDragging(x, y, dropAction, hideSource);
-
-    docViewPathFunc = () => this.docViewPath;
-    isSelected = (outsideReaction?: boolean) => SelectionManager.IsSelected(this, outsideReaction);
-    select = (extendSelection: boolean) => SelectionManager.SelectView(this, !SelectionManager.Views().some(v => v.props.Document === this.props.ContainingCollectionDoc) && extendSelection);
-    NativeWidth = () => this.effectiveNativeWidth;
-    NativeHeight = () => this.effectiveNativeHeight;
-    PanelWidth = () => this.panelWidth;
-    PanelHeight = () => this.panelHeight;
-    ContentScale = () => this.nativeScaling;
-    selfView = () => this;
-    screenToLocalTransform = () => {
-        return this.props.ScreenToLocalTransform().translate(-this.centeringX, -this.centeringY).scale(1 / this.nativeScaling);
-    }
-    componentDidMount() {
-        this._disposers.reactionScript = reaction(
-            () => ScriptCast(this.rootDoc.reactionScript)?.script?.run({ this: this.props.Document, self: Cast(this.rootDoc, Doc, null) || this.props.Document }).result,
-            output => output
-        );
-        this._disposers.height = reaction(
-            () => NumCast(this.layoutDoc._height),
-            action(height => {
-                const docMax = NumCast(this.layoutDoc.docMaxAutoHeight);
-                if (docMax && docMax < height) this.layoutDoc.docMaxAutoHeight = height;
-            })
-        );
-        !BoolCast(this.props.Document.dontRegisterView, this.props.dontRegisterView) && DocumentManager.Instance.AddView(this);
-    }
-    componentWillUnmount() {
-        Object.values(this._disposers).forEach(disposer => disposer?.());
-        !BoolCast(this.props.Document.dontRegisterView, this.props.dontRegisterView) && DocumentManager.Instance.RemoveView(this);
-    }
-
-    render() {
-        TraceMobx();
-        const xshift = () => (this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Xshift) <= 0.001 ? this.props.PanelWidth() : undefined);
-        const yshift = () => (this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined);
-        const isPresTreeElement: boolean = this.props.treeViewDoc?.type === DocumentType.PRES;
-        const isButton: boolean = this.props.Document.type === DocumentType.FONTICON || this.props.Document._viewType === CollectionViewType.Linear;
-        return (<div className="contentFittingDocumentView">
-            {!this.props.Document || !this.props.PanelWidth() ? (null) : (
-                <div className="contentFittingDocumentView-previewDoc" ref={this.ContentRef}
-                    style={{
-                        transition: this.props.dataTransition,
-                        position: this.props.Document.isInkMask ? "absolute" : undefined,
-                        transform: isButton ? undefined : `translate(${this.centeringX}px, ${this.centeringY}px)`,
-                        width: isButton || isPresTreeElement ? "100%" : xshift() ?? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%`,
-                        height: isButton || this.props.forceAutoHeight ? undefined : yshift() ?? (this.fitWidth ? `${this.panelHeight}px` :
-                            `${100 * this.effectiveNativeHeight / this.effectiveNativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%`),
-                    }}>
-                    <DocumentViewInternal {...this.props}
-                        DocumentView={this.selfView}
-                        viewPath={this.docViewPathFunc}
-                        PanelWidth={this.PanelWidth}
-                        PanelHeight={this.PanelHeight}
-                        NativeWidth={this.NativeWidth}
-                        NativeHeight={this.NativeHeight}
-                        isSelected={this.isSelected}
-                        select={this.select}
-                        ContentScaling={this.ContentScale}
-                        ScreenToLocalTransform={this.screenToLocalTransform}
-                        focus={this.props.focus || emptyFunction}
-                        ref={action((r: DocumentViewInternal | null) => r && (this.docView = r))} />
-                </div>)}
-        </div>);
-    }
+      });
+
+      startDragging = (x: number, y: number, dropAction: dropActionType, hideSource = false) => this.docView?.startDragging(x, y, dropAction, hideSource);
+
+      docViewPathFunc = () => this.docViewPath;
+      isSelected = (outsideReaction?: boolean) => SelectionManager.IsSelected(this, outsideReaction);
+      select = (extendSelection: boolean) => SelectionManager.SelectView(this, !SelectionManager.Views().some(v => v.props.Document === this.props.ContainingCollectionDoc) && extendSelection);
+      NativeWidth = () => this.effectiveNativeWidth;
+      NativeHeight = () => this.effectiveNativeHeight;
+      PanelWidth = () => this.panelWidth;
+      PanelHeight = () => this.panelHeight;
+      ContentScale = () => this.nativeScaling;
+      selfView = () => this;
+      screenToLocalTransform = () => {
+            return this.props.ScreenToLocalTransform().translate(-this.centeringX, -this.centeringY).scale(1 / this.nativeScaling);
+      }
+      componentDidMount() {
+            this._disposers.reactionScript = reaction(
+                  () => ScriptCast(this.rootDoc.reactionScript)?.script?.run({ this: this.props.Document, self: Cast(this.rootDoc, Doc, null) || this.props.Document }).result,
+                  output => output
+            );
+            this._disposers.height = reaction(
+                  () => NumCast(this.layoutDoc._height),
+                  action(height => {
+                        const docMax = NumCast(this.layoutDoc.docMaxAutoHeight);
+                        if (docMax && docMax < height) this.layoutDoc.docMaxAutoHeight = height;
+                  })
+            );
+            !BoolCast(this.props.Document.dontRegisterView, this.props.dontRegisterView) && DocumentManager.Instance.AddView(this);
+      }
+      componentWillUnmount() {
+            Object.values(this._disposers).forEach(disposer => disposer?.());
+            !BoolCast(this.props.Document.dontRegisterView, this.props.dontRegisterView) && DocumentManager.Instance.RemoveView(this);
+      }
+
+      render() {
+            TraceMobx();
+            const xshift = () => (this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Xshift) <= 0.001 ? this.props.PanelWidth() : undefined);
+            const yshift = () => (this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined);
+            const isPresTreeElement: boolean = this.props.treeViewDoc?.type === DocumentType.PRES;
+            const isButton: boolean = this.props.Document.type === DocumentType.FONTICON || this.props.Document._viewType === CollectionViewType.Linear;
+            return (<div className="contentFittingDocumentView">
+                  {!this.props.Document || !this.props.PanelWidth() ? (null) : (
+                        <div className="contentFittingDocumentView-previewDoc" ref={this.ContentRef}
+                              style={{
+                                    transition: this.props.dataTransition,
+                                    position: this.props.Document.isInkMask ? "absolute" : undefined,
+                                    transform: isButton ? undefined : `translate(${this.centeringX}px, ${this.centeringY}px)`,
+                                    width: isButton || isPresTreeElement ? "100%" : xshift() ?? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%`,
+                                    height: isButton || this.props.forceAutoHeight ? undefined : yshift() ?? (this.fitWidth ? `${this.panelHeight}px` :
+                                          `${100 * this.effectiveNativeHeight / this.effectiveNativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%`),
+                              }}>
+                              <DocumentViewInternal {...this.props}
+                                    DocumentView={this.selfView}
+                                    viewPath={this.docViewPathFunc}
+                                    PanelWidth={this.PanelWidth}
+                                    PanelHeight={this.PanelHeight}
+                                    NativeWidth={this.NativeWidth}
+                                    NativeHeight={this.NativeHeight}
+                                    isSelected={this.isSelected}
+                                    select={this.select}
+                                    ContentScaling={this.ContentScale}
+                                    ScreenToLocalTransform={this.screenToLocalTransform}
+                                    focus={this.props.focus || emptyFunction}
+                                    ref={action((r: DocumentViewInternal | null) => r && (this.docView = r))} />
+                        </div>)}
+            </div>);
+      }
 }
 
 export function deiconifyViewFunc(documentView: DocumentView) {
-    documentView.iconify();
-    //StrCast(doc.layoutKey).split("_")[1] === "icon" && setNativeView(doc);
+      documentView.iconify();
+      //StrCast(doc.layoutKey).split("_")[1] === "icon" && setNativeView(doc);
 }
 ScriptingGlobals.add(function deiconifyView(documentView: DocumentView) {
-    documentView.iconify();
-    documentView.select(false);
+      documentView.iconify();
+      documentView.select(false);
 });
 
 ScriptingGlobals.add(function toggleDetail(dv: DocumentView, detailLayoutKeySuffix: string) {
-    if (dv.Document.layoutKey === "layout_" + detailLayoutKeySuffix) dv.switchViews(false, "layout");
-    else dv.switchViews(true, detailLayoutKeySuffix);
+      if (dv.Document.layoutKey === "layout_" + detailLayoutKeySuffix) dv.switchViews(false, "layout");
+      else dv.switchViews(true, detailLayoutKeySuffix);
 });
 
 ScriptingGlobals.add(function updateLinkCollection(linkCollection: Doc) {
-    const linkSource = Cast(linkCollection.linkSource, Doc, null);
-    const collectedLinks = DocListCast(Doc.GetProto(linkCollection).data);
-    let wid = linkSource[WidthSym]();
-    const links = DocListCast(linkSource.links);
-    links.forEach(link => {
-        const other = LinkManager.getOppositeAnchor(link, linkSource);
-        const otherdoc = !other ? undefined : other.annotationOn ? Cast(other.annotationOn, Doc, null) : other;
-        if (otherdoc && !collectedLinks?.some(d => Doc.AreProtosEqual(d, otherdoc))) {
-            const alias = Doc.MakeAlias(otherdoc);
-            alias.x = wid;
-            alias.y = 0;
-            alias._lockedPosition = false;
-            wid += otherdoc[WidthSym]();
-            Doc.AddDocToList(Doc.GetProto(linkCollection), "data", alias);
-        }
-    });
-    return links;
+      const linkSource = Cast(linkCollection.linkSource, Doc, null);
+      const collectedLinks = DocListCast(Doc.GetProto(linkCollection).data);
+      let wid = linkSource[WidthSym]();
+      const links = DocListCast(linkSource.links);
+      links.forEach(link => {
+            const other = LinkManager.getOppositeAnchor(link, linkSource);
+            const otherdoc = !other ? undefined : other.annotationOn ? Cast(other.annotationOn, Doc, null) : other;
+            if (otherdoc && !collectedLinks?.some(d => Doc.AreProtosEqual(d, otherdoc))) {
+                  const alias = Doc.MakeAlias(otherdoc);
+                  alias.x = wid;
+                  alias.y = 0;
+                  alias._lockedPosition = false;
+                  wid += otherdoc[WidthSym]();
+                  Doc.AddDocToList(Doc.GetProto(linkCollection), "data", alias);
+            }
+      });
+      return links;
 });
\ No newline at end of file
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 87716e9cc..5826abd65 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -9,6 +9,7 @@ import { Networking } from '../../../Network';
 import { Upload } from '../../../../server/SharedMediaTypes';
 
 import { RecordingApi } from '../../../util/RecordingApi';
+import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils';
 
 interface MediaSegment {
       videoChunks: any[],
@@ -193,12 +194,15 @@ export function RecordingView(props: IRecordingViewProps) {
             }
       }
 
-      const startOrResume = () => {
-            if (!videoRecorder.current || videoRecorder.current.state === "inactive") {
-                  record();
-            } else if (videoRecorder.current.state === "paused") {
-                  videoRecorder.current.resume();
-            }
+      const startOrResume = (e: React.PointerEvent) => {
+            // the code to start or resume does not get triggered if we start dragging the button
+            setupMoveUpEvents({}, e, returnFalse, returnFalse, () => {
+                  if (!videoRecorder.current || videoRecorder.current.state === "inactive") {
+                        record();
+                  } else if (videoRecorder.current.state === "paused") {
+                        videoRecorder.current.resume();
+                  }
+            })
       }
 
       const clearPrevious = () => {
@@ -240,8 +244,8 @@ export function RecordingView(props: IRecordingViewProps) {
                               <div className="controls-inner-container">
                                     <div className="record-button-wrapper">
                                           {recording ?
-                                                <button className="stop-button" onClick={pause} /> :
-                                                <button className="record-button" onClick={startOrResume} />
+                                                <button className="stop-button" onPointerDown={pause} /> :
+                                                <button className="record-button" onPointerDown={startOrResume} />
                                           }
                                     </div>
 
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index 99fc61cde..083ca5bea 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -51,11 +51,11 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
       componentWillUnmount() {
             this._heightDisposer?.();
       }
-    
-        @action
-        presExpandDocumentClick = () => {
+
+      @action
+      presExpandDocumentClick = () => {
             this.rootDoc.presExpandInlineButton = !this.rootDoc.presExpandInlineButton;
-        }
+      }
 
       /**
        * Returns a local transformed coordinate array for given coordinates.
@@ -324,7 +324,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
             } else {
                   // if we dont have any recording
-                  const recording = Docs.Create.WebCamDocument("", { _width: 400, _height: 200, title: "recording", cloneFieldFilter: new List<string>(["system"]) });
+                  const recording = Docs.Create.WebCamDocument("", { _width: 400, _height: 200, hideDocumentButtonBar: true, title: "recording", cloneFieldFilter: new List<string>(["system"]) });
 
                   // attach the recording to the slide, and attach the slide to the recording
                   recording.slides = activeItem
-- 
cgit v1.2.3-70-g09d2


From d3c89f90d376310cd583ae1c6ac4a7eb4c5a03ac Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 7 Jun 2022 13:39:17 -0400
Subject: fixed dragging items in overlayView to not invalidate DocumentView
 and cause a rerender.  fixed loss of ability to select or drag after dragging
 a recording.

---
 src/Utils.ts                                       |  10 +-
 src/client/util/DragManager.ts                     |   4 -
 src/client/views/OverlayView.tsx                   |  13 +-
 .../views/nodes/RecordingBox/RecordingBox.tsx      |  85 ++--
 .../views/nodes/RecordingBox/RecordingView.tsx     | 491 +++++++++++----------
 5 files changed, 305 insertions(+), 298 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/Utils.ts b/src/Utils.ts
index 6f3a31b49..07e95d438 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -698,6 +698,7 @@ export function setupMoveUpEvents(
     (target as any)._lastTap = Date.now();
     (target as any)._downX = (target as any)._lastX = e.clientX;
     (target as any)._downY = (target as any)._lastY = e.clientY;
+    (target as any)._noClick = false;
 
     const _moveEvent = (e: PointerEvent): void => {
         if (Math.abs(e.clientX - (target as any)._downX) > Utils.DRAG_THRESHOLD || Math.abs(e.clientY - (target as any)._downY) > Utils.DRAG_THRESHOLD) {
@@ -729,17 +730,20 @@ export function setupMoveUpEvents(
                 clearTimeout((target as any)._doubleTime);
                 (target as any)._doubleTime = undefined;
             }
-            clickEvent(e, (target as any)._doubleTap);
+            (target as any)._noClick = clickEvent(e, (target as any)._doubleTap);
         }
         document.removeEventListener("pointermove", _moveEvent);
         document.removeEventListener("pointerup", _upEvent);
     };
+    const _clickEvent = (e: MouseEvent): void => {
+        if ((target as any)._noClick) e.stopPropagation();
+        document.removeEventListener("click", _clickEvent, true);
+    }
     if (stopPropagation) {
         e.stopPropagation();
         e.preventDefault();
     }
-    document.removeEventListener("pointermove", _moveEvent);
-    document.removeEventListener("pointerup", _upEvent);
     document.addEventListener("pointermove", _moveEvent);
     document.addEventListener("pointerup", _upEvent);
+    document.addEventListener("click", _clickEvent, true);
 }
\ No newline at end of file
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index f438a8c11..9f8c49081 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -210,10 +210,6 @@ export namespace DragManager {
         options?: DragOptions,
         dropEvent?: () => any
     ) {
-        // stop an 'accidental' on-click drag that may have occured if the user is in presenting mode
-        // note: dragData.dropAction is only undefined when the element itself being dragged without being selected
-        if (Doc.UserDoc()?.presentationMode === 'recording' && dragData.dropAction === undefined) return false;
-
         const addAudioTag = (dropDoc: any) => {
             dropDoc && !dropDoc.creationDate && (dropDoc.creationDate = new DateField);
             dropDoc instanceof Doc && DocUtils.MakeLinkToActiveAudio(() => dropDoc);
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 9d970c06f..6796db51e 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -1,5 +1,7 @@
+import { docs } from "googleapis/build/src/apis/docs";
 import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
+import { computedFn } from "mobx-utils";
 import * as React from "react";
 import ReactLoading from 'react-loading';
 import { Doc, WidthSym, HeightSym } from "../../fields/Doc";
@@ -146,6 +148,12 @@ export class OverlayView extends React.Component {
         return remove;
     }
 
+    removeOverlayDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).map(doc => Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), "data", doc)).length ? true : false;
+
+
+    docScreenToLocalXf = computedFn(function docScreenToLocalXf(this: any, doc: Doc) {
+        return () => new Transform(-NumCast(doc.x), -NumCast(doc.y), 1);
+    }.bind(this));
 
     @computed get overlayDocs() {
         return CurrentUserUtils.OverlayDocs?.map(d => {
@@ -179,17 +187,16 @@ export class OverlayView extends React.Component {
                 offsetx = NumCast(d.x) - e.clientX;
                 offsety = NumCast(d.y) - e.clientY;
             };
-
             return <div className="overlayView-doc" ref={dref} key={d[Id]} onPointerDown={onPointerDown} style={{ top: d.type === 'presentation' ? 0 : undefined, width: NumCast(d._width), height: NumCast(d._height), transform: `translate(${d.x}px, ${d.y}px)` }}>
                 <DocumentView
                     Document={d}
                     rootSelected={returnTrue}
                     bringToFront={emptyFunction}
                     addDocument={undefined}
-                    removeDocument={doc => (doc instanceof Doc ? [doc] : doc).map(doc => Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), "data", doc)).length ? true : false}
+                    removeDocument={this.removeOverlayDoc}
                     PanelWidth={d[WidthSym]}
                     PanelHeight={d[HeightSym]}
-                    ScreenToLocalTransform={() => new Transform(-NumCast(d.x), -NumCast(d.y), 1)}
+                    ScreenToLocalTransform={this.docScreenToLocalXf(d)}
                     renderDepth={1}
                     isDocumentActive={returnTrue}
                     isContentActive={emptyFunction}
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 159271223..eac1c63f9 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -16,47 +16,46 @@ import { Id } from "../../../../fields/FieldSymbols";
 @observer
 export class RecordingBox extends ViewBoxBaseComponent() {
 
-      public static LayoutString(fieldKey: string) { return FieldView.LayoutString(RecordingBox, fieldKey); }
-
-      private _ref: React.RefObject<HTMLDivElement> = React.createRef();
-
-      constructor(props: any) {
-            super(props);
-      }
-
-      componentDidMount() {
-            console.log("set native width and height")
-            Doc.SetNativeWidth(this.dataDoc, 1280);
-            Doc.SetNativeHeight(this.dataDoc, 720);
-      }
-
-      @observable result: Upload.FileInformation | undefined = undefined
-      @observable videoDuration: number | undefined = undefined
-
-      @action
-      setVideoDuration = (duration: number) => {
-            this.videoDuration = duration
-      }
-
-      @action
-      setResult = (info: Upload.FileInformation, trackScreen: boolean) => {
-            this.result = info
-            this.dataDoc.type = DocumentType.VID;
-            this.dataDoc[this.fieldKey + "-duration"] = this.videoDuration;
-
-            this.dataDoc.layout = VideoBox.LayoutString(this.fieldKey);
-            this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.agnostic.client);
-            this.dataDoc[this.fieldKey + "-recorded"] = true;
-            // stringify the presenation and store it
-            if (trackScreen) {
-                  this.dataDoc[this.fieldKey + "-presentation"] = JSON.stringify(RecordingApi.Instance.clear());
-            }
-      }
-
-      render() {
-            // console.log("Proto[Is]: ", this.rootDoc.proto?.[Id])
-            return <div className="recordingBox" ref={this._ref}>
-                  {!this.result && <RecordingView setResult={this.setResult} setDuration={this.setVideoDuration} id={this.rootDoc.proto?.[Id]} />}
-            </div>;
-      }
+    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(RecordingBox, fieldKey); }
+
+    private _ref: React.RefObject<HTMLDivElement> = React.createRef();
+
+    constructor(props: any) {
+        super(props);
+    }
+
+    componentDidMount() {
+        console.log("set native width and height")
+        Doc.SetNativeWidth(this.dataDoc, 1280);
+        Doc.SetNativeHeight(this.dataDoc, 720);
+    }
+
+    @observable result: Upload.FileInformation | undefined = undefined
+    @observable videoDuration: number | undefined = undefined
+
+    @action
+    setVideoDuration = (duration: number) => {
+        this.videoDuration = duration
+    }
+
+    @action
+    setResult = (info: Upload.FileInformation, trackScreen: boolean) => {
+        this.result = info
+        this.dataDoc.type = DocumentType.VID;
+        this.dataDoc[this.fieldKey + "-duration"] = this.videoDuration;
+
+        this.dataDoc.layout = VideoBox.LayoutString(this.fieldKey);
+        this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.agnostic.client);
+        this.dataDoc[this.fieldKey + "-recorded"] = true;
+        // stringify the presenation and store it
+        if (trackScreen) {
+            this.dataDoc[this.fieldKey + "-presentation"] = JSON.stringify(RecordingApi.Instance.clear());
+        }
+    }
+
+    render() {
+        return <div className="recordingBox" ref={this._ref}>
+            {!this.result && <RecordingView setResult={this.setResult} setDuration={this.setVideoDuration} id={this.rootDoc.proto?.[Id]} />}
+        </div>;
+    }
 }
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 5826abd65..b95335792 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -9,273 +9,274 @@ import { Networking } from '../../../Network';
 import { Upload } from '../../../../server/SharedMediaTypes';
 
 import { RecordingApi } from '../../../util/RecordingApi';
-import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils';
+import { emptyFunction, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils';
 
 interface MediaSegment {
-      videoChunks: any[],
-      endTime: number
+    videoChunks: any[],
+    endTime: number
 }
 
 interface IRecordingViewProps {
-      setResult: (info: Upload.FileInformation, trackScreen: boolean) => void
-      setDuration: (seconds: number) => void
-      id: string
+    setResult: (info: Upload.FileInformation, trackScreen: boolean) => void
+    setDuration: (seconds: number) => void
+    id: string
 }
 
 const MAXTIME = 100000;
 
 export function RecordingView(props: IRecordingViewProps) {
 
-      const [recording, setRecording] = useState(false);
-      const recordingTimerRef = useRef<number>(0);
-      const [recordingTimer, setRecordingTimer] = useState(0); // unit is 0.01 second
-      const [playing, setPlaying] = useState(false);
-      const [progress, setProgress] = useState(0);
-
-      const [videos, setVideos] = useState<MediaSegment[]>([]);
-      const videoRecorder = useRef<MediaRecorder | null>(null);
-      const videoElementRef = useRef<HTMLVideoElement | null>(null);
-
-      const [finished, setFinished] = useState<boolean>(false)
-      const [trackScreen, setTrackScreen] = useState<boolean>(true)
-
-
-
-      const DEFAULT_MEDIA_CONSTRAINTS = {
-            video: {
-                  width: 1280,
-                  height: 720,
-            },
-            audio: {
-                  echoCancellation: true,
-                  noiseSuppression: true,
-                  sampleRate: 44100
-            }
-      }
-
-      useEffect(() => {
-
-            if (finished) {
-                  props.setDuration(recordingTimer * 100)
-                  let allVideoChunks: any = []
-                  videos.forEach((vid) => {
-                        console.log(vid.videoChunks)
-                        allVideoChunks = allVideoChunks.concat(vid.videoChunks)
-                  })
-
-                  const videoFile = new File(allVideoChunks, "video.mkv", { type: allVideoChunks[0].type, lastModified: Date.now() });
-
-                  Networking.UploadFilesToServer(videoFile)
-                        .then((data) => {
-                              const result = data[0].result
-                              if (!(result instanceof Error)) { // convert this screenshotBox into normal videoBox
-                                    props.setResult(result, trackScreen)
-                              } else {
-                                    alert("video conversion failed");
-                              }
-                        })
-
-            }
-
-
-      }, [finished])
-
-      useEffect(() => {
-            // check if the browser supports media devices on first load
-            if (!navigator.mediaDevices) {
-                  console.log('This browser does not support getUserMedia.')
-            }
-            console.log('This device has the correct media devices.')
-      }, [])
-
-      useEffect(() => {
-            // get access to the video element on every render
-            videoElementRef.current = document.getElementById(`video-${props.id}`) as HTMLVideoElement;
-      })
-
-      useEffect(() => {
-            let interval: any = null;
-            if (recording) {
-                  interval = setInterval(() => {
-                        setRecordingTimer(unit => unit + 1);
-                  }, 10);
-            } else if (!recording && recordingTimer !== 0) {
-                  clearInterval(interval);
-            }
-            return () => clearInterval(interval);
-      }, [recording])
-
-      useEffect(() => {
-            setVideoProgressHelper(recordingTimer)
-            recordingTimerRef.current = recordingTimer;
-      }, [recordingTimer])
-
-      const setVideoProgressHelper = (progress: number) => {
-            const newProgress = (progress / MAXTIME) * 100;
-            setProgress(newProgress)
-      }
-      const startShowingStream = async (mediaConstraints = DEFAULT_MEDIA_CONSTRAINTS) => {
-            const stream = await navigator.mediaDevices.getUserMedia(mediaConstraints)
-
-            videoElementRef.current!.src = ""
-            videoElementRef.current!.srcObject = stream
-            videoElementRef.current!.muted = true
-
-            return stream
-      }
-
-      const record = async () => {
-            const stream = await startShowingStream();
-            videoRecorder.current = new MediaRecorder(stream)
-
-            // temporary chunks of video
-            let videoChunks: any = []
-
-            videoRecorder.current.ondataavailable = (event: any) => {
-                  if (event.data.size > 0) {
-                        videoChunks.push(event.data)
-                  }
-            }
-
-            videoRecorder.current.onstart = (event: any) => {
-                  setRecording(true);
-                  trackScreen && RecordingApi.Instance.start();
-            }
-
-            videoRecorder.current.onstop = () => {
-                  // if we have a last portion
-                  if (videoChunks.length > 1) {
-                        // append the current portion to the video pieces
-                        setVideos(videos => [...videos, { videoChunks: videoChunks, endTime: recordingTimerRef.current }])
-                  }
-
-                  // reset the temporary chunks
-                  videoChunks = []
-                  setRecording(false);
-                  setFinished(true);
-                  trackScreen && RecordingApi.Instance.pause();
-            }
-
-            // recording paused
-            videoRecorder.current.onpause = (event: any) => {
-                  // append the current portion to the video pieces
-                  setVideos(videos => [...videos, { videoChunks: videoChunks, endTime: recordingTimerRef.current }])
+    const [recording, setRecording] = useState(false);
+    const recordingTimerRef = useRef<number>(0);
+    const [recordingTimer, setRecordingTimer] = useState(0); // unit is 0.01 second
+    const [playing, setPlaying] = useState(false);
+    const [progress, setProgress] = useState(0);
+
+    const [videos, setVideos] = useState<MediaSegment[]>([]);
+    const videoRecorder = useRef<MediaRecorder | null>(null);
+    const videoElementRef = useRef<HTMLVideoElement | null>(null);
+
+    const [finished, setFinished] = useState<boolean>(false)
+    const [trackScreen, setTrackScreen] = useState<boolean>(true)
+
+
+
+    const DEFAULT_MEDIA_CONSTRAINTS = {
+        video: {
+            width: 1280,
+            height: 720,
+        },
+        audio: {
+            echoCancellation: true,
+            noiseSuppression: true,
+            sampleRate: 44100
+        }
+    }
+
+    useEffect(() => {
+
+        if (finished) {
+            props.setDuration(recordingTimer * 100)
+            let allVideoChunks: any = []
+            videos.forEach((vid) => {
+                console.log(vid.videoChunks)
+                allVideoChunks = allVideoChunks.concat(vid.videoChunks)
+            })
 
-                  // reset the temporary chunks
-                  videoChunks = []
-                  setRecording(false);
-                  trackScreen && RecordingApi.Instance.pause();
+            const videoFile = new File(allVideoChunks, "video.mkv", { type: allVideoChunks[0].type, lastModified: Date.now() });
+
+            Networking.UploadFilesToServer(videoFile)
+                .then((data) => {
+                    const result = data[0].result
+                    if (!(result instanceof Error)) { // convert this screenshotBox into normal videoBox
+                        props.setResult(result, trackScreen)
+                    } else {
+                        alert("video conversion failed");
+                    }
+                })
+
+        }
+
+
+    }, [finished])
+
+    useEffect(() => {
+        // check if the browser supports media devices on first load
+        if (!navigator.mediaDevices) {
+            console.log('This browser does not support getUserMedia.')
+        }
+        console.log('This device has the correct media devices.')
+    }, [])
+
+    useEffect(() => {
+        // get access to the video element on every render
+        videoElementRef.current = document.getElementById(`video-${props.id}`) as HTMLVideoElement;
+    })
+
+    useEffect(() => {
+        let interval: any = null;
+        if (recording) {
+            interval = setInterval(() => {
+                setRecordingTimer(unit => unit + 1);
+            }, 10);
+        } else if (!recording && recordingTimer !== 0) {
+            clearInterval(interval);
+        }
+        return () => clearInterval(interval);
+    }, [recording])
+
+    useEffect(() => {
+        setVideoProgressHelper(recordingTimer)
+        recordingTimerRef.current = recordingTimer;
+    }, [recordingTimer])
+
+    const setVideoProgressHelper = (progress: number) => {
+        const newProgress = (progress / MAXTIME) * 100;
+        setProgress(newProgress)
+    }
+    const startShowingStream = async (mediaConstraints = DEFAULT_MEDIA_CONSTRAINTS) => {
+        const stream = await navigator.mediaDevices.getUserMedia(mediaConstraints)
+
+        videoElementRef.current!.src = ""
+        videoElementRef.current!.srcObject = stream
+        videoElementRef.current!.muted = true
+
+        return stream
+    }
+
+    const record = async () => {
+        const stream = await startShowingStream();
+        videoRecorder.current = new MediaRecorder(stream)
+
+        // temporary chunks of video
+        let videoChunks: any = []
+
+        videoRecorder.current.ondataavailable = (event: any) => {
+            if (event.data.size > 0) {
+                videoChunks.push(event.data)
             }
-
-            videoRecorder.current.onresume = async (event: any) => {
-                  await startShowingStream();
-                  setRecording(true);
-                  trackScreen && RecordingApi.Instance.resume();
+        }
+
+        videoRecorder.current.onstart = (event: any) => {
+            setRecording(true);
+            trackScreen && RecordingApi.Instance.start();
+        }
+
+        videoRecorder.current.onstop = () => {
+            // if we have a last portion
+            if (videoChunks.length > 1) {
+                // append the current portion to the video pieces
+                setVideos(videos => [...videos, { videoChunks: videoChunks, endTime: recordingTimerRef.current }])
             }
 
-            videoRecorder.current.start(200)
-      }
-
-
-      const stop = () => {
-            if (videoRecorder.current) {
-                  if (videoRecorder.current.state !== "inactive") {
-                        videoRecorder.current.stop();
-                        // recorder.current.stream.getTracks().forEach((track: any) => track.stop())
-                  }
+            // reset the temporary chunks
+            videoChunks = []
+            setRecording(false);
+            setFinished(true);
+            trackScreen && RecordingApi.Instance.pause();
+        }
+
+        // recording paused
+        videoRecorder.current.onpause = (event: any) => {
+            // append the current portion to the video pieces
+            setVideos(videos => [...videos, { videoChunks: videoChunks, endTime: recordingTimerRef.current }])
+
+            // reset the temporary chunks
+            videoChunks = []
+            setRecording(false);
+            trackScreen && RecordingApi.Instance.pause();
+        }
+
+        videoRecorder.current.onresume = async (event: any) => {
+            await startShowingStream();
+            setRecording(true);
+            trackScreen && RecordingApi.Instance.resume();
+        }
+
+        videoRecorder.current.start(200)
+    }
+
+
+    const stop = () => {
+        if (videoRecorder.current) {
+            if (videoRecorder.current.state !== "inactive") {
+                videoRecorder.current.stop();
+                // recorder.current.stream.getTracks().forEach((track: any) => track.stop())
             }
-      }
+        }
+    }
 
-      const pause = () => {
-            if (videoRecorder.current) {
-                  if (videoRecorder.current.state === "recording") {
-                        videoRecorder.current.pause();
-                  }
+    const pause = () => {
+        if (videoRecorder.current) {
+            if (videoRecorder.current.state === "recording") {
+                videoRecorder.current.pause();
             }
-      }
-
-      const startOrResume = (e: React.PointerEvent) => {
-            // the code to start or resume does not get triggered if we start dragging the button
-            setupMoveUpEvents({}, e, returnFalse, returnFalse, () => {
-                  if (!videoRecorder.current || videoRecorder.current.state === "inactive") {
-                        record();
-                  } else if (videoRecorder.current.state === "paused") {
-                        videoRecorder.current.resume();
-                  }
-            })
-      }
-
-      const clearPrevious = () => {
-            const numVideos = videos.length
-            setRecordingTimer(numVideos == 1 ? 0 : videos[numVideos - 2].endTime)
-            setVideoProgressHelper(numVideos == 1 ? 0 : videos[numVideos - 2].endTime)
-            setVideos(videos.filter((_, idx) => idx !== numVideos - 1));
-      }
-
-      const handleOnTimeUpdate = () => {
-            if (playing) {
-                  setVideoProgressHelper(videoElementRef.current!.currentTime)
+        }
+    }
+
+    const startOrResume = (e: React.PointerEvent) => {
+        // the code to start or resume does not get triggered if we start dragging the button
+        setupMoveUpEvents({}, e, returnTrue, returnFalse, e => {
+            if (!videoRecorder.current || videoRecorder.current.state === "inactive") {
+                record();
+            } else if (videoRecorder.current.state === "paused") {
+                videoRecorder.current.resume();
             }
-      };
-
-      const millisecondToMinuteSecond = (milliseconds: number) => {
-            const toTwoDigit = (digit: number) => {
-                  return String(digit).length == 1 ? "0" + digit : digit
-            }
-            const minutes = Math.floor((milliseconds % (1000 * 60 * 60)) / (1000 * 60));
-            const seconds = Math.floor((milliseconds % (1000 * 60)) / 1000);
-            return toTwoDigit(minutes) + " : " + toTwoDigit(seconds);
-      }
-
-      return (
-            <div className="recording-container">
-                  <div className="video-wrapper">
-                        <video id={`video-${props.id}`}
-                              autoPlay
-                              muted
-                              onTimeUpdate={handleOnTimeUpdate}
-                        />
-                        <div className="recording-sign">
-                              <span className="dot" />
-                              <p className="timer">{millisecondToMinuteSecond(recordingTimer * 10)}</p>
+            return true; // cancels propagation to documentView to avoid selecting it.
+        }, false, false);
+    }
+
+    const clearPrevious = () => {
+        const numVideos = videos.length
+        setRecordingTimer(numVideos == 1 ? 0 : videos[numVideos - 2].endTime)
+        setVideoProgressHelper(numVideos == 1 ? 0 : videos[numVideos - 2].endTime)
+        setVideos(videos.filter((_, idx) => idx !== numVideos - 1));
+    }
+
+    const handleOnTimeUpdate = () => {
+        if (playing) {
+            setVideoProgressHelper(videoElementRef.current!.currentTime)
+        }
+    };
+
+    const millisecondToMinuteSecond = (milliseconds: number) => {
+        const toTwoDigit = (digit: number) => {
+            return String(digit).length == 1 ? "0" + digit : digit
+        }
+        const minutes = Math.floor((milliseconds % (1000 * 60 * 60)) / (1000 * 60));
+        const seconds = Math.floor((milliseconds % (1000 * 60)) / 1000);
+        return toTwoDigit(minutes) + " : " + toTwoDigit(seconds);
+    }
+
+    return (
+        <div className="recording-container">
+            <div className="video-wrapper">
+                <video id={`video-${props.id}`}
+                    autoPlay
+                    muted
+                    onTimeUpdate={handleOnTimeUpdate}
+                />
+                <div className="recording-sign">
+                    <span className="dot" />
+                    <p className="timer">{millisecondToMinuteSecond(recordingTimer * 10)}</p>
+                </div>
+                <div className="controls">
+
+                    <div className="controls-inner-container">
+                        <div className="record-button-wrapper">
+                            {recording ?
+                                <button className="stop-button" onPointerDown={pause} /> :
+                                <button className="record-button" onPointerDown={startOrResume} />
+                            }
                         </div>
-                        <div className="controls">
-
-                              <div className="controls-inner-container">
-                                    <div className="record-button-wrapper">
-                                          {recording ?
-                                                <button className="stop-button" onPointerDown={pause} /> :
-                                                <button className="record-button" onPointerDown={startOrResume} />
-                                          }
-                                    </div>
 
-                                    {!recording && (videos.length > 0 ?
+                        {!recording && (videos.length > 0 ?
 
-                                          <div className="options-wrapper video-edit-wrapper">
-                                                {/* <IconContext.Provider value={{ color: "grey", className: "video-edit-buttons" }}>
+                            <div className="options-wrapper video-edit-wrapper">
+                                {/* <IconContext.Provider value={{ color: "grey", className: "video-edit-buttons" }}>
                                                       <MdBackspace onClick={clearPrevious} />
                                                 </IconContext.Provider> */}
-                                                <IconContext.Provider value={{ color: "#cc1c08", className: "video-edit-buttons" }}>
-                                                      <FaCheckCircle onClick={stop} />
-                                                </IconContext.Provider>
-                                          </div>
-
-                                          : <div className="options-wrapper track-screen-wrapper">
-                                                <label className="track-screen">
-                                                      <input type="checkbox" checked={trackScreen} onChange={(e) => { setTrackScreen(e.target.checked) }} />
-                                                      <span className="checkmark"></span>
-                                                      Track Screen
-                                                </label>
-                                          </div>)}
-
-                              </div>
-
-                              <ProgressBar
-                                    progress={progress}
-                                    marks={videos.map((elt) => elt.endTime / MAXTIME * 100)}
-                              // playSegment={playSegment}
-                              />
-                        </div>
-                  </div>
-            </div>)
+                                <IconContext.Provider value={{ color: "#cc1c08", className: "video-edit-buttons" }}>
+                                    <FaCheckCircle onClick={stop} />
+                                </IconContext.Provider>
+                            </div>
+
+                            : <div className="options-wrapper track-screen-wrapper">
+                                <label className="track-screen">
+                                    <input type="checkbox" checked={trackScreen} onChange={(e) => { setTrackScreen(e.target.checked) }} />
+                                    <span className="checkmark"></span>
+                                    Track Screen
+                                </label>
+                            </div>)}
+
+                    </div>
+
+                    <ProgressBar
+                        progress={progress}
+                        marks={videos.map((elt) => elt.endTime / MAXTIME * 100)}
+                    // playSegment={playSegment}
+                    />
+                </div>
+            </div>
+        </div>)
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2

