From 2f6cdc734d8a5855db3e0f4ee1d6b9535d20f325 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 13 Sep 2022 16:18:37 -0400
Subject: fixed rendering non-docs from freeform layout engine

---
 .../collectionFreeForm/CollectionFreeFormView.tsx       | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 039407e77..6927d429d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -116,8 +116,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     @observable ChildDrag: DocumentView | undefined; // child document view being dragged.  needed to update drop areas of groups when a group item is dragged.
 
     @computed get views() {
-        const viewsMask = this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z && ele.inkMask !== -1).map(ele => ele.ele);
-        const renderableEles = this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z && ele.inkMask === -1).map(ele => ele.ele);
+        const viewsMask = this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z && ele.inkMask !== -1 && ele.inkMask !== undefined).map(ele => ele.ele);
+        const renderableEles = this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z && (ele.inkMask === -1 || ele.inkMask === undefined)).map(ele => ele.ele);
         if (viewsMask.length) renderableEles.push(<div className={`collectionfreeformview-mask${this._layoutElements.some(ele => (ele.inkMask ?? 0) > 0) ? '' : '-empty'}`}>{viewsMask}</div>);
         return renderableEles;
     }
@@ -1425,15 +1425,12 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     @computed get doInternalLayoutComputation() {
         TraceMobx();
         const newPool = new Map<string, PoolData>();
+        // prettier-ignore
         switch (this.layoutEngine) {
-            case 'pass':
-                return { newPool, computedElementData: this.doEngineLayout(newPool, computerPassLayout) };
-            case 'timeline':
-                return { newPool, computedElementData: this.doEngineLayout(newPool, computeTimelineLayout) };
-            case 'pivot':
-                return { newPool, computedElementData: this.doEngineLayout(newPool, computePivotLayout) };
-            case 'starburst':
-                return { newPool, computedElementData: this.doEngineLayout(newPool, computerStarburstLayout) };
+            case 'pass':      return { newPool, computedElementData: this.doEngineLayout(newPool, computerPassLayout) };
+            case 'timeline':  return { newPool, computedElementData: this.doEngineLayout(newPool, computeTimelineLayout) };
+            case 'pivot':     return { newPool, computedElementData: this.doEngineLayout(newPool, computePivotLayout) };
+            case 'starburst': return { newPool, computedElementData: this.doEngineLayout(newPool, computerStarburstLayout) };
         }
         return { newPool, computedElementData: this.doFreeformLayout(newPool) };
     }
-- 
cgit v1.2.3-70-g09d2


From 6290c9147b4aead8b0253aa958f086752b397a4f Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 19 Sep 2022 12:47:17 -0400
Subject: if same youtube video is uploaded, reuse the existing file without
 downloading again.  removed failed uploads from parsed_files.  change
 pinWithView to highlight the pinned view region.  Give pinWithView
 collections an option to just pan or zoom to % of screen size.

---
 package-lock.json                                  | 1729 ++++++++++----------
 package.json                                       |    1 +
 src/client/views/DocComponent.tsx                  |    1 -
 src/client/views/collections/CollectionView.tsx    |    1 +
 src/client/views/collections/TabDocView.tsx        |    4 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   39 +-
 .../collections/collectionFreeForm/MarqueeView.tsx |    4 +-
 src/client/views/nodes/DocumentView.tsx            |    1 +
 src/client/views/nodes/PDFBox.tsx                  |    3 +
 src/client/views/nodes/trails/PresBox.tsx          |   73 +-
 src/client/views/pdf/PDFViewer.tsx                 |    8 +-
 src/server/DashUploadUtils.ts                      |  128 +-
 12 files changed, 1046 insertions(+), 946 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/package-lock.json b/package-lock.json
index 5c186f43f..6763aec2c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1138,7 +1138,7 @@
         "@types/bcrypt-nodejs": {
             "version": "0.0.30",
             "resolved": "https://registry.npmjs.org/@types/bcrypt-nodejs/-/bcrypt-nodejs-0.0.30.tgz",
-            "integrity": "sha512-gSWCu7EOXhcM0FYM8tanV0deaX1VM07sgBS8dSUmgnAQ5/3Xn6k+mWF+ZfE+c/OCW14IVnNdTOKcHgvL78oDFQ==",
+            "integrity": "sha1-TN2WtJKTs5MhIuS34pVD415rrlg=",
             "dev": true
         },
         "@types/bezier-js": {
@@ -2243,7 +2243,7 @@
         "@types/strip-bom": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
-            "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==",
+            "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=",
             "dev": true
         },
         "@types/strip-json-comments": {
@@ -2279,7 +2279,7 @@
         "@types/typescript": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/@types/typescript/-/typescript-2.0.0.tgz",
-            "integrity": "sha512-WMEWfMISiJ2QKyk5/dSdgL0ZwP//PZj0jmDU0hMh51FmLq4WIYzjlngsUQZXejQL+QtkXJUOGjb3G3UCvgZuSQ==",
+            "integrity": "sha1-xDNTnJi64oaCswfqp6D9IRW4PCg=",
             "dev": true,
             "requires": {
                 "typescript": "*"
@@ -2594,7 +2594,7 @@
                 "textarea-caret": {
                     "version": "3.0.2",
                     "resolved": "https://registry.npmjs.org/textarea-caret/-/textarea-caret-3.0.2.tgz",
-                    "integrity": "sha1-82DEhpmqGr9xhoCkOjGoUGZcLK8="
+                    "integrity": "sha512-gRzeti2YS4did7UJnPQ47wrjD+vp+CJIe9zbsu0bJ987d8QVLvLNG9757rqiQTIy4hGIeFauTTJt5Xkn51UkXg=="
                 }
             }
         },
@@ -2613,7 +2613,7 @@
         "Base64": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz",
-            "integrity": "sha512-reGEWshDmTDQDsCec/HduOO9Wyj6yMOupMfhIf3ugN1TDlK2NQW4DDJSqNNtp380SNcvRfXtO8HSCQot0d0SMw=="
+            "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg="
         },
         "D": {
             "version": "1.0.0",
@@ -2656,7 +2656,7 @@
         "acorn-globals": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz",
-            "integrity": "sha512-uWttZCk96+7itPxK8xCzY86PnxKTMrReKDqrHzv42VQY0K30PUO8WY13WMOuI+cOdX4EIdzdvQ8k6jkuGRFMYw==",
+            "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=",
             "requires": {
                 "acorn": "^4.0.4"
             },
@@ -2664,7 +2664,7 @@
                 "acorn": {
                     "version": "4.0.13",
                     "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
-                    "integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug=="
+                    "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c="
                 }
             }
         },
@@ -2693,7 +2693,7 @@
         "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.2",
@@ -2768,7 +2768,7 @@
         "align-text": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
-            "integrity": "sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==",
+            "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
             "requires": {
                 "kind-of": "^3.0.2",
                 "longest": "^1.0.1",
@@ -2783,7 +2783,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -2793,12 +2793,12 @@
         "amdefine": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
-            "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg=="
+            "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
         },
         "ansi-align": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz",
-            "integrity": "sha512-TdlOggdA/zURfMYa7ABC66j+oqfMew58KpJMbUlH3bcZP1b+cBHIHDDn5uH9INsxrHBPjsqM0tDB4jPTF/vgJA==",
+            "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=",
             "requires": {
                 "string-width": "^2.0.0"
             }
@@ -2862,7 +2862,7 @@
         "any-promise": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
-            "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
+            "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
         },
         "anymatch": {
             "version": "2.0.0",
@@ -2876,7 +2876,7 @@
                 "normalize-path": {
                     "version": "2.1.1",
                     "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
-                    "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==",
+                    "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
                     "requires": {
                         "remove-trailing-separator": "^1.0.1"
                     }
@@ -2971,7 +2971,7 @@
         "arr-diff": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
-            "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA=="
+            "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
         },
         "arr-flatten": {
             "version": "1.1.0",
@@ -2981,7 +2981,7 @@
         "arr-union": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
-            "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q=="
+            "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="
         },
         "array-back": {
             "version": "2.0.0",
@@ -3072,18 +3072,18 @@
         "array-equal": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
-            "integrity": "sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA==",
+            "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
             "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": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw=="
+            "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E="
         },
         "array-flatten": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
-            "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
+            "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
         },
         "array-includes": {
             "version": "3.1.5",
@@ -3101,7 +3101,7 @@
         "array-union": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
-            "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==",
+            "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
             "dev": true,
             "requires": {
                 "array-uniq": "^1.0.1"
@@ -3110,13 +3110,13 @@
         "array-uniq": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
-            "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==",
+            "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
             "dev": true
         },
         "array-unique": {
             "version": "0.3.2",
             "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
-            "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ=="
+            "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
         },
         "array.prototype.flat": {
             "version": "1.3.0",
@@ -3167,7 +3167,7 @@
         "asap": {
             "version": "2.0.6",
             "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
-            "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="
+            "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
         },
         "asn1": {
             "version": "0.2.6",
@@ -3180,7 +3180,7 @@
         "assert-plus": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
-            "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw=="
+            "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
         },
         "assertion-error": {
             "version": "1.1.0",
@@ -3190,7 +3190,7 @@
         "assign-symbols": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
-            "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw=="
+            "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
         },
         "ast-types-flow": {
             "version": "0.0.7",
@@ -3220,7 +3220,7 @@
         "async-foreach": {
             "version": "0.1.3",
             "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
-            "integrity": "sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA=="
+            "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI="
         },
         "async-limiter": {
             "version": "1.0.1",
@@ -3231,7 +3231,7 @@
         "asynckit": {
             "version": "0.4.0",
             "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-            "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+            "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
         },
         "atob": {
             "version": "2.1.2",
@@ -3281,7 +3281,7 @@
         "aws-sign2": {
             "version": "0.7.0",
             "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
-            "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA=="
+            "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
         },
         "aws4": {
             "version": "1.11.0",
@@ -3311,12 +3311,12 @@
         "babel": {
             "version": "6.23.0",
             "resolved": "https://registry.npmjs.org/babel/-/babel-6.23.0.tgz",
-            "integrity": "sha512-ZDcCaI8Vlct8PJ3DvmyqUz+5X2Ylz3ZuuItBe/74yXosk2dwyVo/aN7MCJ8HJzhnnJ+6yP4o+lDgG9MBe91DLA=="
+            "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": "sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==",
+            "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
             "dev": true,
             "requires": {
                 "chalk": "^1.1.3",
@@ -3327,19 +3327,19 @@
                 "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==",
+                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
                     "dev": true
                 },
                 "ansi-styles": {
                     "version": "2.2.1",
                     "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-                    "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==",
+                    "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
                     "dev": true
                 },
                 "chalk": {
                     "version": "1.1.3",
                     "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-                    "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
+                    "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
                     "dev": true,
                     "requires": {
                         "ansi-styles": "^2.2.1",
@@ -3352,7 +3352,7 @@
                 "js-tokens": {
                     "version": "3.0.2",
                     "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
-                    "integrity": "sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==",
+                    "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
                     "dev": true
                 },
                 "strip-ansi": {
@@ -3436,12 +3436,12 @@
         "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": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw=="
+            "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
         },
         "babel-runtime": {
             "version": "6.26.0",
             "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
-            "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
+            "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
             "requires": {
                 "core-js": "^2.4.0",
                 "regenerator-runtime": "^0.11.0"
@@ -3462,7 +3462,7 @@
         "babel-types": {
             "version": "6.26.0",
             "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
-            "integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==",
+            "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
             "requires": {
                 "babel-runtime": "^6.26.0",
                 "esutils": "^2.0.2",
@@ -3485,7 +3485,7 @@
         "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=="
         },
         "bail": {
             "version": "2.0.2",
@@ -3514,7 +3514,7 @@
                 "define-property": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-                    "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
+                    "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
                     "requires": {
                         "is-descriptor": "^1.0.0"
                     }
@@ -3550,12 +3550,12 @@
         "base16": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz",
-            "integrity": "sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ=="
+            "integrity": "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA="
         },
         "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.5.1",
@@ -3575,18 +3575,18 @@
         "batch": {
             "version": "0.6.1",
             "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
-            "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
+            "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
             "dev": true
         },
         "bcrypt-nodejs": {
             "version": "0.0.3",
             "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz",
-            "integrity": "sha512-NmTbLm867btBHCBZ222FQXkQKzecB0KG6pTXFa6NeTVZaSnLfCsx7EK2PL3J+kX8xJThUquEBbhimRCKKZX9zA=="
+            "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs="
         },
         "bcrypt-pbkdf": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
-            "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
+            "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
             "requires": {
                 "tweetnacl": "^0.14.3"
             }
@@ -3599,7 +3599,7 @@
         "bezier-curve": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/bezier-curve/-/bezier-curve-1.0.0.tgz",
-            "integrity": "sha512-h6uZJ6qdFfswS1rIRericgouhTeiVi/MnH10OKtCu2IZzXa+ZcjaxRLHY4u/evRsJcxYbbiNkgWQj2Z4UIcpEQ=="
+            "integrity": "sha1-o9+v6rEqlMRicw1QeYxSqEBdc3k="
         },
         "bezier-js": {
             "version": "4.1.1",
@@ -3648,7 +3648,7 @@
         "block-stream": {
             "version": "0.0.9",
             "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
-            "integrity": "sha512-OorbnJVPII4DuUKbjARAe8u8EfqOmkEEaSFIyoQ7OjTHn6kafxWl0wLgoZ2rXaYd7MyLcDaU4TmhfxtwgcccMQ==",
+            "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
             "requires": {
                 "inherits": "~2.0.0"
             }
@@ -3711,7 +3711,7 @@
         "bonjour": {
             "version": "3.5.0",
             "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
-            "integrity": "sha512-RaVTblr+OnEli0r/ud8InrU7D+G0y6aJhlxaLa6Pwty4+xoxboF1BsUI45tujvRpbj9dQVoglChqonGAsjEBYg==",
+            "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
             "dev": true,
             "requires": {
                 "array-flatten": "^2.1.0",
@@ -3733,7 +3733,7 @@
         "boolbase": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
-            "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
+            "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
         },
         "bootstrap": {
             "version": "4.6.1",
@@ -3762,7 +3762,7 @@
                 "camelcase": {
                     "version": "4.1.0",
                     "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-                    "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw=="
+                    "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
                 }
             }
         },
@@ -3795,7 +3795,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -3805,7 +3805,7 @@
         "browser-assert": {
             "version": "1.2.1",
             "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz",
-            "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ=="
+            "integrity": "sha1-mqpaKox0aFwq4Fv+Ru/WBvBowgA="
         },
         "browser-process-hrtime": {
             "version": "1.0.0",
@@ -3850,12 +3850,12 @@
         "buffer-crc32": {
             "version": "0.2.13",
             "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
-            "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="
+            "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
         },
         "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": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
+            "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
         },
         "buffer-from": {
             "version": "1.1.2",
@@ -3871,12 +3871,12 @@
         "buffer-shims": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
-            "integrity": "sha512-Zy8ZXMyxIT6RMTeY7OP/bDndfj6bwCan7SS98CEndS6deHwWPpseeHlwarNcBim+etXnF9HBc1non5JgDaJU1g=="
+            "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E="
         },
         "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": "sha512-5XD5cujru60ooKJ4sGZqoH5v2Xvgw7ezV54gJX/OnPkgDKoH3BnlMEi8xW6hl8xaEjxKHebgrsawroeZnGwIMA==",
+            "integrity": "sha1-JA3CHLOJQ5WIxhxGDrAHZJfvxBw=",
             "requires": {
                 "math-codegen": "^0.3.5"
             }
@@ -4007,7 +4007,7 @@
         "caller-callsite": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
-            "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==",
+            "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
             "requires": {
                 "callsites": "^2.0.0"
             },
@@ -4015,14 +4015,14 @@
                 "callsites": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
-                    "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ=="
+                    "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": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==",
+            "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
             "requires": {
                 "caller-callsite": "^2.0.0"
             }
@@ -4049,7 +4049,7 @@
         "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==",
+            "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
             "requires": {
                 "camelcase": "^2.0.0",
                 "map-obj": "^1.0.0"
@@ -4058,14 +4058,14 @@
                 "camelcase": {
                     "version": "2.1.1",
                     "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
-                    "integrity": "sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw=="
+                    "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
                 }
             }
         },
         "camelize": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
-            "integrity": "sha512-W2lPwkBkMZwFlPCXhIlYgxu+7gC/NUlCtdK652DAJ1JdgV0sTrvuPFshNPrFa1TY2JOkLhgdeEBplB4ezEa+xg=="
+            "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
         },
         "caniuse-lite": {
             "version": "1.0.30001351",
@@ -4090,7 +4090,7 @@
         "caseless": {
             "version": "0.12.0",
             "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
-            "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
+            "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
         },
         "ccount": {
             "version": "2.0.1",
@@ -4100,7 +4100,7 @@
         "center-align": {
             "version": "0.1.3",
             "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
-            "integrity": "sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==",
+            "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
             "requires": {
                 "align-text": "^0.1.3",
                 "lazy-cache": "^1.0.3"
@@ -4138,7 +4138,7 @@
         "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=="
+            "integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU="
         },
         "character-entities": {
             "version": "2.0.2",
@@ -4148,7 +4148,7 @@
         "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==",
+            "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=",
             "requires": {
                 "is-regex": "^1.0.3"
             }
@@ -4162,12 +4162,12 @@
         "check-error": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
-            "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA=="
+            "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
         },
         "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=="
+            "integrity": "sha1-sffn/HPSXn/R1FWtyU4UODAYK1o="
         },
         "chokidar": {
             "version": "2.1.8",
@@ -4196,7 +4196,7 @@
         "chrome": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/chrome/-/chrome-0.1.0.tgz",
-            "integrity": "sha512-6KYl20U4Taj6YipylsWr2etUvp9AElJKfGNSBmyGTymYmancnOb041ZNadolEZi2nboLXH7jMSqUmm4kpuTzfg==",
+            "integrity": "sha1-9h2beS/v6MGUxwVt3BAscmqGQyk=",
             "requires": {
                 "exeq": "^2.2.0",
                 "plist": "^1.1.0"
@@ -4216,7 +4216,7 @@
         "clamp": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz",
-            "integrity": "sha512-kgMuFyE78OC6Dyu3Dy7vcx4uy97EIbVxJB/B0eJ3bUNAkwdNcxYzgKltnyADiYwsR7SEqkkUPsEUT//OVS6XMA=="
+            "integrity": "sha1-ZqDmQBGBbjcZaCj9yMjBRzEshjQ="
         },
         "class-transformer": {
             "version": "0.2.3",
@@ -4237,7 +4237,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
+                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -4267,7 +4267,7 @@
         "cli-boxes": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
-            "integrity": "sha512-3Fo5wu8Ytle8q9iCzS4D2MWVL2X7JVWRiS1BnXbTFDhS9c/REkM9vd1AmabsoZoY5/dGi5TT9iKL8Kb6DeBRQg=="
+            "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM="
         },
         "cli-cursor": {
             "version": "3.1.0",
@@ -4287,7 +4287,7 @@
         "clipboard": {
             "version": "1.7.1",
             "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-1.7.1.tgz",
-            "integrity": "sha512-smkaRaIQsrnKN1F3wd1/vY9Q+DeR4L8ZCXKeHCFC2j8RZuSBbuImcLdnIO4GTxmzJxQuDGNKkyfpGoPW7Ua5bQ==",
+            "integrity": "sha1-Ng1taUbpmnof7zleQrqStem1oWs=",
             "requires": {
                 "good-listener": "^1.2.2",
                 "select": "^1.1.2",
@@ -4312,7 +4312,7 @@
                 "camelcase": {
                     "version": "4.1.0",
                     "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-                    "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw=="
+                    "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
                 },
                 "yargs-parser": {
                     "version": "7.0.0",
@@ -4362,7 +4362,7 @@
         "clj-fuzzy": {
             "version": "0.3.3",
             "resolved": "https://registry.npmjs.org/clj-fuzzy/-/clj-fuzzy-0.3.3.tgz",
-            "integrity": "sha512-9cyh9A8+OphDZeKIG21MgyDHWDkWxTvagwvFLVjtdi6eToFENF7iDLlKwhHrnBQRSQwprKNhazG053nE/UgwfQ=="
+            "integrity": "sha1-seU0MJHFIC28UlMoY+HEp4RX8D0="
         },
         "clone-deep": {
             "version": "4.0.1",
@@ -4377,7 +4377,7 @@
         "clone-response": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
-            "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==",
+            "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
             "requires": {
                 "mimic-response": "^1.0.0"
             },
@@ -4397,12 +4397,12 @@
         "code-point-at": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
-            "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA=="
+            "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
         },
         "collection-visit": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
-            "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==",
+            "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
             "requires": {
                 "map-visit": "^1.0.0",
                 "object-visit": "^1.0.0"
@@ -4428,7 +4428,7 @@
         "color-name": {
             "version": "1.1.3",
             "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-            "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+            "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
         },
         "color-string": {
             "version": "1.9.1",
@@ -4491,13 +4491,13 @@
         "commondir": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
-            "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
+            "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
             "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",
@@ -4507,7 +4507,7 @@
         "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",
@@ -4572,7 +4572,7 @@
                 "bytes": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
-                    "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==",
+                    "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
                     "dev": true
                 },
                 "debug": {
@@ -4587,7 +4587,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
                     "dev": true
                 }
             }
@@ -4595,7 +4595,7 @@
         "concat-map": {
             "version": "0.0.1",
             "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-            "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+            "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
         },
         "concat-stream": {
             "version": "1.6.2",
@@ -4661,7 +4661,7 @@
         "connect-flash": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz",
-            "integrity": "sha512-2rcfELQt/ZMP+SM/pG8PyhJRaLKp+6Hk2IUBNkEit09X+vwn3QsAL3ZbYtxUn7NVPzbMTSLRDhqe0B/eh30RYA=="
+            "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA="
         },
         "connect-history-api-fallback": {
             "version": "1.6.0",
@@ -4690,12 +4690,12 @@
                 "process-nextick-args": {
                     "version": "1.0.7",
                     "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
-                    "integrity": "sha512-yN0WQmuCX63LP/TMvAg31nvT6m4vDqJEiiv2CAZqWOGNWutc9DfDk1NPYYmKUFmaVM2UwDowH4u5AHWYP/jxKw=="
+                    "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
                 },
                 "readable-stream": {
                     "version": "2.2.7",
                     "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz",
-                    "integrity": "sha512-a6ibcfWFhgihuTw/chl+u3fB5ykBZFmnvpyZHebY0MCQE4vvYcsCLpCeaQ1BkH7HdJYavNSqF0WDLeo4IPHQaQ==",
+                    "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=",
                     "requires": {
                         "buffer-shims": "~1.0.0",
                         "core-util-is": "~1.0.0",
@@ -4719,7 +4719,7 @@
         "console-control-strings": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
-            "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
+            "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
         },
         "constantinople": {
             "version": "3.1.2",
@@ -4803,7 +4803,7 @@
         "cookie-signature": {
             "version": "1.0.6",
             "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
-            "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
+            "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
         },
         "cookies": {
             "version": "0.8.0",
@@ -4848,7 +4848,7 @@
         "copy-descriptor": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
-            "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw=="
+            "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
         },
         "copy-webpack-plugin": {
             "version": "4.6.0",
@@ -4878,7 +4878,7 @@
                 "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==",
+                    "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
                     "dev": true
                 },
                 "serialize-javascript": {
@@ -4892,7 +4892,7 @@
         "core-js": {
             "version": "1.2.7",
             "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
-            "integrity": "sha512-ZiPp9pZlgxpWRu0M+YWbm6+aQ84XEfH1JRXvfOc/fILWI0VKhLC2LX13X1NYq4fULzLMq7Hfh43CSo2/aIaUPA=="
+            "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
         },
         "core-js-pure": {
             "version": "3.22.8",
@@ -4956,7 +4956,7 @@
         "create-error-class": {
             "version": "3.0.2",
             "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
-            "integrity": "sha512-gYTKKexFO3kh200H1Nit76sRwRtOY32vQd3jpAQKpLtZqyNsSQNfI4N7o3eP2wUjV35pTWKRYqFUDBvUha/Pkw==",
+            "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=",
             "requires": {
                 "capture-stack-trace": "^1.0.0"
             }
@@ -5021,7 +5021,7 @@
         "cross-spawn": {
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
-            "integrity": "sha512-eZ+m1WNhSZutOa/uRblAc9Ut5MQfukFrFMtPSm3bZCA888NmMd5AWXWdgRZ80zd+pTk1P2JrGjg9pUPTvl2PWQ==",
+            "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
             "requires": {
                 "lru-cache": "^4.0.1",
                 "which": "^1.2.9"
@@ -5051,7 +5051,7 @@
         "crypto-random-string": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
-            "integrity": "sha512-GsVpkFPlycH7/fRR7Dhcmnoii54gV1nz7y4CWyeFS14N+JVBBhY+r8amRHE4BwSYal7BPTDp8isvAlCxyFt3Hg=="
+            "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4="
         },
         "css-box-model": {
             "version": "1.2.1",
@@ -5064,7 +5064,7 @@
         "css-color-keywords": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
-            "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg=="
+            "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU="
         },
         "css-in-js-utils": {
             "version": "2.0.1",
@@ -5207,7 +5207,7 @@
         "currently-unhandled": {
             "version": "0.4.1",
             "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
-            "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==",
+            "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
             "requires": {
                 "array-find-index": "^1.0.1"
             }
@@ -5215,12 +5215,12 @@
         "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": "sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A==",
+            "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
             "dev": true
         },
         "d": {
@@ -5367,7 +5367,7 @@
         "dashdash": {
             "version": "1.14.1",
             "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
-            "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
+            "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
             "requires": {
                 "assert-plus": "^1.0.0"
             }
@@ -5419,7 +5419,7 @@
         "de-indent": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
-            "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg=="
+            "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0="
         },
         "debounce": {
             "version": "1.2.1",
@@ -5437,7 +5437,7 @@
         "decamelize": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
-            "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="
+            "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
         },
         "decode-named-character-reference": {
             "version": "1.0.2",
@@ -5450,7 +5450,7 @@
         "decode-uri-component": {
             "version": "0.2.0",
             "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
-            "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og=="
+            "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
         },
         "decompress-response": {
             "version": "4.2.1",
@@ -5615,7 +5615,7 @@
                 "globby": {
                     "version": "6.1.0",
                     "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
-                    "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==",
+                    "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
                     "dev": true,
                     "requires": {
                         "array-union": "^1.0.1",
@@ -5628,7 +5628,7 @@
                         "pify": {
                             "version": "2.3.0",
                             "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-                            "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+                            "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
                             "dev": true
                         }
                     }
@@ -5653,7 +5653,7 @@
         "delayed-stream": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-            "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
+            "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
         },
         "delegate": {
             "version": "3.2.0",
@@ -5663,7 +5663,7 @@
         "delegates": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
-            "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
+            "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
         },
         "denque": {
             "version": "1.5.1",
@@ -5766,7 +5766,7 @@
                 "import-fresh": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
-                    "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==",
+                    "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
                     "requires": {
                         "caller-path": "^2.0.0",
                         "resolve-from": "^3.0.0"
@@ -5801,7 +5801,7 @@
                 "parse-json": {
                     "version": "4.0.0",
                     "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
-                    "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+                    "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
                     "requires": {
                         "error-ex": "^1.3.1",
                         "json-parse-better-errors": "^1.0.1"
@@ -5815,7 +5815,7 @@
                 "resolve-from": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
-                    "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw=="
+                    "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
                 },
                 "string-width": {
                     "version": "4.2.3",
@@ -5887,7 +5887,7 @@
         "deps-regex": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/deps-regex/-/deps-regex-0.1.4.tgz",
-            "integrity": "sha512-3tzwGYogSJi8HoG93R5x9NrdefZQOXgHgGih/7eivloOq6yC6O+yoFxZnkgP661twvfILONfoKRdF9GQOGx2RA=="
+            "integrity": "sha1-UYZnt2kUYKXn4KNBvnbrfOgJAYQ="
         },
         "dequal": {
             "version": "2.0.3",
@@ -5941,7 +5941,7 @@
                 "pify": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-                    "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+                    "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
                     "dev": true
                 }
             }
@@ -5949,7 +5949,7 @@
         "dns-equal": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
-            "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==",
+            "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
             "dev": true
         },
         "dns-packet": {
@@ -5965,7 +5965,7 @@
         "dns-txt": {
             "version": "2.0.2",
             "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
-            "integrity": "sha512-Ix5PrWjphuSoUXV/Zv5gaFHjnaJtb02F2+Si3Ht9dyJ87+Z/lMmy+dpNHtTGraNK958ndXq2i+GLkWsWHcKaBQ==",
+            "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
             "dev": true,
             "requires": {
                 "buffer-indexof": "^1.0.0"
@@ -5983,7 +5983,7 @@
         "doctypes": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz",
-            "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ=="
+            "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk="
         },
         "dom-converter": {
             "version": "0.2.0",
@@ -6092,12 +6092,12 @@
         "double-bits": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/double-bits/-/double-bits-1.1.1.tgz",
-            "integrity": "sha512-BCLEIBq0O/DWoA7BsCu/R+RP0ZXiowP8BhtJT3qeuuQEBpnS8LK/Wo6UTJQv6v8mK1fj8n90YziHLwGdM5whSg=="
+            "integrity": "sha1-WKu6RUlNpND6Nrc60RoobJGEscY="
         },
         "duplexer3": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
-            "integrity": "sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA=="
+            "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
         },
         "duplexify": {
             "version": "3.7.1",
@@ -6131,7 +6131,7 @@
         "dynamic-dedupe": {
             "version": "0.3.0",
             "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
-            "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==",
+            "integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=",
             "dev": true,
             "requires": {
                 "xtend": "^4.0.0"
@@ -6140,7 +6140,7 @@
         "ecc-jsbn": {
             "version": "0.1.2",
             "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
-            "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
+            "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
             "requires": {
                 "jsbn": "~0.1.0",
                 "safer-buffer": "^2.1.0"
@@ -6157,7 +6157,7 @@
         "ee-first": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
-            "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
+            "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
         },
         "electron-to-chromium": {
             "version": "1.4.149",
@@ -6186,7 +6186,7 @@
         "encodeurl": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
-            "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
+            "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
         },
         "encoding": {
             "version": "0.1.13",
@@ -6261,7 +6261,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",
@@ -6425,7 +6425,7 @@
         "es6-promise": {
             "version": "3.2.1",
             "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz",
-            "integrity": "sha512-oj4jOSXvWglTsc3wrw86iom3LDPOx1nbipQk+jaG3dy+sMRM6ReSgVr/VlmBuF6lXUrflN9DCcQHeSbAwGUl4g=="
+            "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q="
         },
         "es6-symbol": {
             "version": "3.1.3",
@@ -6445,12 +6445,12 @@
         "escape-html": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-            "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+            "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
         },
         "escape-string-regexp": {
             "version": "1.0.5",
             "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-            "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
+            "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
         },
         "escodegen": {
             "version": "1.14.3",
@@ -7676,7 +7676,7 @@
         "etag": {
             "version": "1.8.1",
             "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
-            "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
+            "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
         },
         "event-target-shim": {
             "version": "5.0.1",
@@ -7704,7 +7704,7 @@
         "execa": {
             "version": "0.7.0",
             "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
-            "integrity": "sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==",
+            "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
             "requires": {
                 "cross-spawn": "^5.0.1",
                 "get-stream": "^3.0.0",
@@ -7718,7 +7718,7 @@
                 "cross-spawn": {
                     "version": "5.1.0",
                     "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
-                    "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==",
+                    "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
                     "requires": {
                         "lru-cache": "^4.0.1",
                         "shebang-command": "^1.2.0",
@@ -7749,7 +7749,7 @@
         "exeq": {
             "version": "2.4.0",
             "resolved": "https://registry.npmjs.org/exeq/-/exeq-2.4.0.tgz",
-            "integrity": "sha512-B648qbDS00nQZv9UQGLT5RbZm/5dNBX10F8oWeXcgpFHSLm1249u95t/3sn2wXdQjLhlF+edAECdshFtSr1K0Q==",
+            "integrity": "sha1-Td8qaEZIxCeteZNJzzO9dTWPiEo=",
             "requires": {
                 "bluebird": "^3.0.3",
                 "native-or-bluebird": "^1.2.0"
@@ -7758,7 +7758,7 @@
         "exif": {
             "version": "0.6.0",
             "resolved": "https://registry.npmjs.org/exif/-/exif-0.6.0.tgz",
-            "integrity": "sha512-gEwM4uanNMfLnDNKclZ7jPEA99E3rpy4ntoS6QW8u6murZjl1o8qRaPdMoC46Syg3d9/QaET0bYKhWlTwJCPgg==",
+            "integrity": "sha1-YKYmaAdlQst+T1cZnUrG830sX0o=",
             "requires": {
                 "debug": "^2.2"
             },
@@ -7774,7 +7774,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
                 }
             }
         },
@@ -7786,7 +7786,7 @@
         "expand-brackets": {
             "version": "2.1.4",
             "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
-            "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==",
+            "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
             "requires": {
                 "debug": "^2.3.3",
                 "define-property": "^0.2.5",
@@ -7808,7 +7808,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
+                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -7816,7 +7816,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -7824,7 +7824,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
                 }
             }
         },
@@ -7907,7 +7907,7 @@
         "express-flash": {
             "version": "0.0.2",
             "resolved": "https://registry.npmjs.org/express-flash/-/express-flash-0.0.2.tgz",
-            "integrity": "sha512-QVUR0ZZRCaa8+iPHoUQaQJrQWcQuK/Q+19M7IUIdIEtvwhrA/ifHT7y1CVJI41YfGiOQnbGtn3uvd2vOdgu58A==",
+            "integrity": "sha1-I9GovPP5DXB5KOSJ+Whp7K0KzaI=",
             "requires": {
                 "connect-flash": "0.1.x"
             }
@@ -7964,7 +7964,7 @@
         "expressjs": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/expressjs/-/expressjs-1.0.1.tgz",
-            "integrity": "sha512-eFnQ5bMJxTZ29XwRJPV8ee/OURBBMS6Fm+b5rvMMEyz6u2IxPEh2SRzMZt9WvgnV+SMLmnzkALE1DnGG1HxJCw=="
+            "integrity": "sha1-IgMoRpoY31rWFeK3oM6ZXxf7ru8="
         },
         "ext": {
             "version": "1.6.0",
@@ -7991,7 +7991,7 @@
         "extend-shallow": {
             "version": "3.0.2",
             "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
-            "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==",
+            "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
             "requires": {
                 "assign-symbols": "^1.0.0",
                 "is-extendable": "^1.0.1"
@@ -8047,7 +8047,7 @@
                 "define-property": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-                    "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
+                    "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
                     "requires": {
                         "is-descriptor": "^1.0.0"
                     }
@@ -8055,7 +8055,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -8125,7 +8125,7 @@
         "extsprintf": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
-            "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g=="
+            "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
         },
         "fast-deep-equal": {
             "version": "3.1.3",
@@ -8146,7 +8146,7 @@
         "fast-levenshtein": {
             "version": "2.0.6",
             "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-            "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+            "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
             "dev": true
         },
         "fast-text-encoding": {
@@ -8185,7 +8185,7 @@
         "fd-slicer": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
-            "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
+            "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
             "requires": {
                 "pend": "~1.2.0"
             }
@@ -8193,7 +8193,7 @@
         "ffmpeg": {
             "version": "0.0.4",
             "resolved": "https://registry.npmjs.org/ffmpeg/-/ffmpeg-0.0.4.tgz",
-            "integrity": "sha512-3TgWUJJlZGQn+crJFyhsO/oNeRRnGTy6GhgS98oUCIfZrOW5haPPV7DUfOm3xJcHr5q3TJpjk2GudPutrNisRA==",
+            "integrity": "sha1-HEYN+OfaUSf2LO70v6BsWciWMMs=",
             "requires": {
                 "when": ">= 0.0.1"
             }
@@ -8240,7 +8240,7 @@
         "fill-range": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
-            "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==",
+            "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
             "requires": {
                 "extend-shallow": "^2.0.1",
                 "is-number": "^3.0.0",
@@ -8251,7 +8251,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -8261,7 +8261,7 @@
         "filter-obj": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
-            "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ=="
+            "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs="
         },
         "finalhandler": {
             "version": "1.2.0",
@@ -8295,7 +8295,7 @@
         "find": {
             "version": "0.1.7",
             "resolved": "https://registry.npmjs.org/find/-/find-0.1.7.tgz",
-            "integrity": "sha512-jPrupTOe/pO//3a9Ty2o4NqQCp0L46UG+swUnfFtdmtQVN8pEltKpAqR7Nuf6vWn0GBXx5w+R1MyZzqwjEIqdA==",
+            "integrity": "sha1-yGyHrxqxjyIrvjjeyGy8dg0Wpvs=",
             "requires": {
                 "traverse-chain": "~0.1.0"
             }
@@ -8303,7 +8303,7 @@
         "find-cache-dir": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
-            "integrity": "sha512-46TFiBOzX7xq/PcSWfFwkyjpemdRnMe31UQF+os0y+1W3k95f6R4SEt02Hj4p3X0Mir9gfrkmOtshFidS0VPUg==",
+            "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
             "dev": true,
             "requires": {
                 "commondir": "^1.0.1",
@@ -8444,7 +8444,7 @@
         "fluent-ffmpeg": {
             "version": "2.1.2",
             "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz",
-            "integrity": "sha512-IZTB4kq5GK0DPp7sGQ0q/BWurGHffRtQQwVkiqDgeO6wYJLLV5ZhgNOQ65loZxxuPMKZKZcICCUnaGtlxBiR0Q==",
+            "integrity": "sha1-yVLeIkD4EuvaCqgAbXd27irPfXQ=",
             "requires": {
                 "async": ">=0.2.9",
                 "which": "^1.1.1"
@@ -8511,7 +8511,7 @@
         "for-each-property": {
             "version": "0.0.4",
             "resolved": "https://registry.npmjs.org/for-each-property/-/for-each-property-0.0.4.tgz",
-            "integrity": "sha512-xYs28PM0CKXETFzuGC6ZooH0voZlsSDZwidJcy92flQJi3PK7i3gZx23xHXCPOaD4zmet3bDo+wS7E7SujrlCw==",
+            "integrity": "sha1-z6hXrsFCLh0Sb/CHhPz2Jim8g/Y=",
             "requires": {
                 "get-prototype-chain": "^1.0.1"
             }
@@ -8519,7 +8519,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": "sha512-qzP8QkODWVVRPpWiBZacSbBl67cTTWoBfxMG0wE46AsS1yl7qv05sGN+dHvD4s4tnvl/goe6Sp4qBI+rlVBgNg==",
+            "integrity": "sha1-MTCaSvw4qcygbxsiP1PWSm0IP60=",
             "requires": {
                 "for-each-property": "0.0.4"
             }
@@ -8527,12 +8527,12 @@
         "for-in": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
-            "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ=="
+            "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
         },
         "forever-agent": {
             "version": "0.6.1",
             "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
-            "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw=="
+            "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
         },
         "fork-ts-checker-webpack-plugin": {
             "version": "1.6.0",
@@ -8586,7 +8586,7 @@
         "fragment-cache": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
-            "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==",
+            "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
             "requires": {
                 "map-cache": "^0.2.2"
             }
@@ -8594,12 +8594,12 @@
         "fresh": {
             "version": "0.5.2",
             "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
-            "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
+            "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
         },
         "from2": {
             "version": "2.3.0",
             "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
-            "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==",
+            "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
             "dev": true,
             "requires": {
                 "inherits": "^2.0.1",
@@ -8631,7 +8631,7 @@
         "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==",
+            "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=",
             "requires": {
                 "graceful-fs": "^4.1.2",
                 "jsonfile": "^2.1.0",
@@ -8666,7 +8666,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": "sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==",
+            "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
             "dev": true,
             "requires": {
                 "graceful-fs": "^4.1.2",
@@ -8695,7 +8695,7 @@
         "fs.realpath": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-            "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+            "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
         },
         "fsevents": {
             "version": "1.2.13",
@@ -8876,7 +8876,7 @@
         "get-func-name": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
-            "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig=="
+            "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE="
         },
         "get-intrinsic": {
             "version": "1.1.2",
@@ -8896,12 +8896,12 @@
         "get-prototype-chain": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/get-prototype-chain/-/get-prototype-chain-1.0.1.tgz",
-            "integrity": "sha512-2m7WZ0jveIg/dAbCbpUxEToaJ8Dmti5EkgDP8YM3UpHUT6SAORjE2odP8XQGNVGXMHi8q8cCCoy3HTByTaTVTw=="
+            "integrity": "sha1-oXGhFeoeSQbG7ThDofABwYUQQW8="
         },
         "get-stdin": {
             "version": "5.0.1",
             "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz",
-            "integrity": "sha512-jZV7n6jGE3Gt7fgSTJoz91Ak5MuTLwMwkoYdjxuJ/AmjIsE1UC03y/IWkZCQGEvVNS9qoRNwy5BCqxImv0FVeA=="
+            "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="
         },
         "get-stream": {
             "version": "6.0.1",
@@ -8920,12 +8920,12 @@
         "get-value": {
             "version": "2.0.6",
             "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
-            "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA=="
+            "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
         },
         "getpass": {
             "version": "0.1.7",
             "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
-            "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
+            "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
             "requires": {
                 "assert-plus": "^1.0.0"
             }
@@ -8933,7 +8933,7 @@
         "github-from-package": {
             "version": "0.0.0",
             "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
-            "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
+            "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4="
         },
         "glob": {
             "version": "7.2.3",
@@ -8951,7 +8951,7 @@
         "glob-parent": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
-            "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==",
+            "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
             "requires": {
                 "is-glob": "^3.1.0",
                 "path-dirname": "^1.0.0"
@@ -8960,7 +8960,7 @@
                 "is-glob": {
                     "version": "3.1.0",
                     "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
-                    "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==",
+                    "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
                     "requires": {
                         "is-extglob": "^2.1.0"
                     }
@@ -8976,7 +8976,7 @@
         "global-dirs": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
-            "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==",
+            "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=",
             "requires": {
                 "ini": "^1.3.4"
             }
@@ -8989,7 +8989,7 @@
         "globby": {
             "version": "7.1.1",
             "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
-            "integrity": "sha512-yANWAN2DUcBtuus5Cpd+SKROzXHs2iVXFZt/Ykrfz6SAXqacLX25NZpltE+39ceMexYF4TtEadjuSTw8+3wX4g==",
+            "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
             "dev": true,
             "requires": {
                 "array-union": "^1.0.1",
@@ -9003,7 +9003,7 @@
                 "pify": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-                    "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+                    "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
                     "dev": true
                 }
             }
@@ -9044,7 +9044,7 @@
         "golden-layout": {
             "version": "1.5.9",
             "resolved": "https://registry.npmjs.org/golden-layout/-/golden-layout-1.5.9.tgz",
-            "integrity": "sha512-iBXDQCXOTgUEQJo96zPbjDoy5bRIk9XW5l+q+pDgLnIyReqaa1aiQctNud4epsskyLt952BG521dew5Z1liSxA==",
+            "integrity": "sha1-o5vB9qZ+b4hreXwBbdkk6UJrp38=",
             "requires": {
                 "jquery": "*"
             }
@@ -9052,7 +9052,7 @@
         "good-listener": {
             "version": "1.2.2",
             "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
-            "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
+            "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
             "requires": {
                 "delegate": "^3.1.2"
             }
@@ -9219,7 +9219,7 @@
         "har-schema": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
-            "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q=="
+            "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
         },
         "har-validator": {
             "version": "5.1.5",
@@ -9241,7 +9241,7 @@
         "has-ansi": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
-            "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==",
+            "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
             "requires": {
                 "ansi-regex": "^2.0.0"
             },
@@ -9249,7 +9249,7 @@
                 "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=="
+                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
                 }
             }
         },
@@ -9269,19 +9269,19 @@
                 "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": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="
+            "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
         },
         "has-property-descriptors": {
             "version": "1.0.0",
@@ -9307,12 +9307,12 @@
         "has-unicode": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
-            "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
+            "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
         },
         "has-value": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
-            "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==",
+            "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
             "requires": {
                 "get-value": "^2.0.6",
                 "has-values": "^1.0.0",
@@ -9322,7 +9322,7 @@
         "has-values": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
-            "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==",
+            "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
             "requires": {
                 "is-number": "^3.0.0",
                 "kind-of": "^4.0.0"
@@ -9336,7 +9336,7 @@
                 "kind-of": {
                     "version": "4.0.0",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
-                    "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==",
+                    "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -9461,7 +9461,7 @@
         "hpack.js": {
             "version": "2.1.6",
             "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
-            "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==",
+            "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
             "dev": true,
             "requires": {
                 "inherits": "^2.0.1",
@@ -9490,7 +9490,7 @@
         "html": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/html/-/html-1.0.0.tgz",
-            "integrity": "sha512-lw/7YsdKiP3kk5PnR1INY17iJuzdAtJewxr14ozKJWbbR97znovZ0mh+WEMZ8rjc3lgTK+ID/htTjuyGKB52Kw==",
+            "integrity": "sha1-pUT6nqVJK/s6LMqCEKEL57WvH2E=",
             "requires": {
                 "concat-stream": "^1.4.7"
             }
@@ -9573,7 +9573,7 @@
         "http-browserify": {
             "version": "1.7.0",
             "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz",
-            "integrity": "sha512-Irf/LJXmE3cBzU1eaR4+NEX6bmVLqt1wkmDiA7kBwH7zmb0D8kBAXsDmQ88hhj/qv9iEZKlyGx/hrMcFi8sOHw==",
+            "integrity": "sha1-M3la3nLfiKz7/TZ3PO/tp2RzWyA=",
             "requires": {
                 "Base64": "~0.2.0",
                 "inherits": "~2.0.1"
@@ -9587,7 +9587,7 @@
         "http-deceiver": {
             "version": "1.2.7",
             "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
-            "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==",
+            "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
             "dev": true
         },
         "http-errors": {
@@ -9634,7 +9634,7 @@
         "http-signature": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
-            "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
+            "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
             "requires": {
                 "assert-plus": "^1.0.0",
                 "jsprim": "^1.2.2",
@@ -9653,12 +9653,12 @@
         "https": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/https/-/https-1.0.0.tgz",
-            "integrity": "sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg=="
+            "integrity": "sha1-PDfHrhqO65ZpBKKtHpdaGUt+06Q="
         },
         "https-browserify": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
-            "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg=="
+            "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
         },
         "https-proxy-agent": {
             "version": "5.0.1",
@@ -9710,7 +9710,7 @@
         "icss-replace-symbols": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz",
-            "integrity": "sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==",
+            "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=",
             "dev": true
         },
         "icss-utils": {
@@ -9730,7 +9730,7 @@
         "iferr": {
             "version": "0.1.5",
             "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
-            "integrity": "sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==",
+            "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
             "dev": true
         },
         "ignore": {
@@ -9742,7 +9742,7 @@
         "ignore-by-default": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
-            "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA=="
+            "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk="
         },
         "iink-js": {
             "version": "1.5.4",
@@ -9786,7 +9786,7 @@
         "image-size-stream": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/image-size-stream/-/image-size-stream-1.1.0.tgz",
-            "integrity": "sha512-N505B5FSy2Xf5l/Haef+99TwfJqTu40hnU560+rC0Cm6cxtwVz2yRFh9WpOk1YEjfv3dI0PgVYAH0hmXQmjDcw==",
+            "integrity": "sha1-Ivou2mbG31AQh0bacUkmSy0l+Gs=",
             "requires": {
                 "image-size": "github:netroy/image-size#da2c863807a3e9602617bdd357b0de3ab4a064c1",
                 "readable-stream": "^1.0.33",
@@ -9800,12 +9800,12 @@
                 "isarray": {
                     "version": "0.0.1",
                     "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
-                    "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
+                    "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
                 },
                 "readable-stream": {
                     "version": "1.1.14",
                     "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
-                    "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==",
+                    "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
                     "requires": {
                         "core-util-is": "~1.0.0",
                         "inherits": "~2.0.1",
@@ -9823,7 +9823,7 @@
         "immediate": {
             "version": "3.0.6",
             "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
-            "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
+            "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
         },
         "import-fresh": {
             "version": "3.3.0",
@@ -9837,7 +9837,7 @@
         "import-lazy": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
-            "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A=="
+            "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM="
         },
         "import-local": {
             "version": "3.1.0",
@@ -9851,7 +9851,7 @@
         "imurmurhash": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-            "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="
+            "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
         },
         "in-publish": {
             "version": "2.0.1",
@@ -9861,7 +9861,7 @@
         "indent-string": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
-            "integrity": "sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==",
+            "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
             "requires": {
                 "repeating": "^2.0.0"
             }
@@ -9869,12 +9869,12 @@
         "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": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+            "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
             "requires": {
                 "once": "^1.3.0",
                 "wrappy": "1"
@@ -9891,7 +9891,7 @@
                 "camelcase": {
                     "version": "4.1.0",
                     "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-                    "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw=="
+                    "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
                 }
             }
         },
@@ -9913,7 +9913,7 @@
         "inline-style-prefixer": {
             "version": "3.0.8",
             "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-3.0.8.tgz",
-            "integrity": "sha512-ne8XIyyqkRaNJ1JfL1NYzNdCNxq+MCBQhC8NgOQlzNm2vv3XxlP0VSLQUbSRCF6KPEoveCVEpayHoHzcMyZsMQ==",
+            "integrity": "sha1-hVG45bTVcyROZqNLBPfTIHaitTQ=",
             "requires": {
                 "bowser": "^1.7.3",
                 "css-in-js-utils": "^2.0.0"
@@ -10032,7 +10032,7 @@
         "inspect-function": {
             "version": "0.2.2",
             "resolved": "https://registry.npmjs.org/inspect-function/-/inspect-function-0.2.2.tgz",
-            "integrity": "sha512-becs5gzcHwPrlHawscYkyQ/ShiOiosrXPhA5RVZ3qyWH4aWdD52RnMfXq/dwQXciHwiieD8aIPwdIWYv6eL+sQ==",
+            "integrity": "sha1-hdoMUli8TDMK4yg7Z0fgdZ2QpjU=",
             "requires": {
                 "split-skip": "0.0.1",
                 "unpack-string": "0.0.2"
@@ -10041,7 +10041,7 @@
                 "split-skip": {
                     "version": "0.0.1",
                     "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.1.tgz",
-                    "integrity": "sha512-7dkvq+gofI4M8zx4iZnEZ3O1s7FP4Y/iaIDHJh5RyWrs8idcPauFi2OZe3TBi36fLvR2j5z3kSzVtz6IhPdncQ=="
+                    "integrity": "sha1-gK2ONumOV2RUzDtmfB3SXYZejwA="
                 }
             }
         },
@@ -10064,7 +10064,7 @@
                 "magicli": {
                     "version": "0.0.5",
                     "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
-                    "integrity": "sha512-wZbMtnl2v1b+Jp3xlqA9FU/O4I6YhGXR8xSY/eU2+gDAvut/F+W3gl4qs61iL4LELC7jqSAE6aAD5668EbmQHA==",
+                    "integrity": "sha1-zufQ+7THBRiqyxHsPrfiX/SaSSE=",
                     "requires": {
                         "commander": "^2.9.0",
                         "get-stdin": "^5.0.1",
@@ -10115,7 +10115,7 @@
                         "inspect-function": {
                             "version": "0.2.2",
                             "resolved": "https://registry.npmjs.org/inspect-function/-/inspect-function-0.2.2.tgz",
-                            "integrity": "sha512-becs5gzcHwPrlHawscYkyQ/ShiOiosrXPhA5RVZ3qyWH4aWdD52RnMfXq/dwQXciHwiieD8aIPwdIWYv6eL+sQ==",
+                            "integrity": "sha1-hdoMUli8TDMK4yg7Z0fgdZ2QpjU=",
                             "requires": {
                                 "split-skip": "0.0.1",
                                 "unpack-string": "0.0.2"
@@ -10124,14 +10124,14 @@
                                 "split-skip": {
                                     "version": "0.0.1",
                                     "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.1.tgz",
-                                    "integrity": "sha512-7dkvq+gofI4M8zx4iZnEZ3O1s7FP4Y/iaIDHJh5RyWrs8idcPauFi2OZe3TBi36fLvR2j5z3kSzVtz6IhPdncQ=="
+                                    "integrity": "sha1-gK2ONumOV2RUzDtmfB3SXYZejwA="
                                 }
                             }
                         },
                         "magicli": {
                             "version": "0.0.5",
                             "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
-                            "integrity": "sha512-wZbMtnl2v1b+Jp3xlqA9FU/O4I6YhGXR8xSY/eU2+gDAvut/F+W3gl4qs61iL4LELC7jqSAE6aAD5668EbmQHA==",
+                            "integrity": "sha1-zufQ+7THBRiqyxHsPrfiX/SaSSE=",
                             "requires": {
                                 "commander": "^2.9.0",
                                 "get-stdin": "^5.0.1",
@@ -10142,14 +10142,14 @@
                         "split-skip": {
                             "version": "0.0.2",
                             "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.2.tgz",
-                            "integrity": "sha512-weHOi8BolsDnGIwhhWHbA+wKSuSpvWwjRrdj8SdbIIis2vSwOE37CQP8x3EleuzxanUr3AK8BdUy4MkiOULPZg=="
+                            "integrity": "sha1-2J2Iu9L3Pka1FYqjcKVhIk6A1GE="
                         }
                     }
                 },
                 "split-skip": {
                     "version": "0.0.1",
                     "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.1.tgz",
-                    "integrity": "sha512-7dkvq+gofI4M8zx4iZnEZ3O1s7FP4Y/iaIDHJh5RyWrs8idcPauFi2OZe3TBi36fLvR2j5z3kSzVtz6IhPdncQ=="
+                    "integrity": "sha1-gK2ONumOV2RUzDtmfB3SXYZejwA="
                 }
             }
         },
@@ -10220,7 +10220,7 @@
         "ip-regex": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
-            "integrity": "sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==",
+            "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=",
             "dev": true
         },
         "ipaddr.js": {
@@ -10237,7 +10237,7 @@
         "is-accessor-descriptor": {
             "version": "0.1.6",
             "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-            "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==",
+            "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
             "requires": {
                 "kind-of": "^3.0.2"
             },
@@ -10250,7 +10250,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -10269,7 +10269,7 @@
         "is-arrayish": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
-            "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
+            "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
         },
         "is-bigint": {
             "version": "1.0.4",
@@ -10282,7 +10282,7 @@
         "is-binary-path": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
-            "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==",
+            "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
             "requires": {
                 "binary-extensions": "^1.0.0"
             }
@@ -10325,7 +10325,7 @@
         "is-data-descriptor": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-            "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==",
+            "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
             "requires": {
                 "kind-of": "^3.0.2"
             },
@@ -10338,7 +10338,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -10373,12 +10373,12 @@
         "is-directory": {
             "version": "0.3.1",
             "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
-            "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw=="
+            "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
         },
         "is-expression": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz",
-            "integrity": "sha512-vyMeQMq+AiH5uUnoBfMTwf18tO3bM6k1QXBE9D6ueAAquEfCZe3AJPtud9g6qS0+4X8xA7ndpZiDyeb2l2qOBw==",
+            "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=",
             "requires": {
                 "acorn": "~4.0.2",
                 "object-assign": "^4.0.1"
@@ -10387,7 +10387,7 @@
                 "acorn": {
                     "version": "4.0.13",
                     "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
-                    "integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug=="
+                    "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c="
                 }
             }
         },
@@ -10399,7 +10399,7 @@
         "is-extglob": {
             "version": "2.1.1",
             "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-            "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
+            "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
         },
         "is-finite": {
             "version": "1.1.0",
@@ -10409,7 +10409,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": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w=="
+            "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
         },
         "is-generator-function": {
             "version": "1.0.10",
@@ -10430,12 +10430,12 @@
         "is-in-browser": {
             "version": "1.1.3",
             "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz",
-            "integrity": "sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g=="
+            "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU="
         },
         "is-installed-globally": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz",
-            "integrity": "sha512-ERNhMg+i/XgDwPIPF3u24qpajVreaiSuvpb1Uu0jugw7KKcxGyCX8cgp8P5fwTmAuXku6beDHHECdKArjlg7tw==",
+            "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=",
             "requires": {
                 "global-dirs": "^0.1.0",
                 "is-path-inside": "^1.0.0"
@@ -10449,12 +10449,12 @@
         "is-npm": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
-            "integrity": "sha512-9r39FIr3d+KD9SbX0sfMsHzb5PP3uimOiwr3YupUaUFG4W0l1U57Rx3utpttV7qz5U3jmrO5auUa04LU9pyHsg=="
+            "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ="
         },
         "is-number": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
-            "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==",
+            "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
             "requires": {
                 "kind-of": "^3.0.2"
             },
@@ -10467,7 +10467,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -10485,7 +10485,7 @@
         "is-obj": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
-            "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg=="
+            "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
         },
         "is-path-cwd": {
             "version": "2.2.0",
@@ -10516,7 +10516,7 @@
         "is-path-inside": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
-            "integrity": "sha512-qhsCR/Esx4U4hg/9I19OVUAJkGWtjRYHMRgUMZE2TDdj+Ag+kttZanLupfddNyglzz50cUlmWzUaI37GDfNx/g==",
+            "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
             "requires": {
                 "path-is-inside": "^1.0.1"
             }
@@ -10542,7 +10542,7 @@
         "is-redirect": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
-            "integrity": "sha512-cr/SlUEe5zOGmzvj9bUyC4LVvkNVAXu4GytXLNMr1pny+a65MpQ9IJzFHD5vi7FyJgb4qt27+eS3TuQnqB+RQw=="
+            "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ="
         },
         "is-regex": {
             "version": "1.1.4",
@@ -10577,7 +10577,7 @@
         "is-stream": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
-            "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="
+            "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
         },
         "is-string": {
             "version": "1.0.7",
@@ -10610,7 +10610,7 @@
         "is-typedarray": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
-            "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
+            "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
         },
         "is-url": {
             "version": "1.2.4",
@@ -10620,7 +10620,7 @@
         "is-utf8": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
-            "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q=="
+            "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI="
         },
         "is-weakref": {
             "version": "1.0.2",
@@ -10643,28 +10643,28 @@
         "is-wsl": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
-            "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==",
+            "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
             "dev": true
         },
         "isarray": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-            "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
+            "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
         },
         "isexe": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-            "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+            "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
         },
         "isobject": {
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
-            "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="
+            "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
         },
         "isomorphic-fetch": {
             "version": "2.2.1",
             "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
-            "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==",
+            "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
             "requires": {
                 "node-fetch": "^1.0.1",
                 "whatwg-fetch": ">=0.10.0"
@@ -10673,7 +10673,7 @@
         "isstream": {
             "version": "0.1.2",
             "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
-            "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
+            "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
         },
         "its-set": {
             "version": "1.2.3",
@@ -10730,7 +10730,7 @@
         "js-stringify": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz",
-            "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g=="
+            "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds="
         },
         "js-tokens": {
             "version": "4.0.0",
@@ -10749,7 +10749,7 @@
         "jsbn": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
-            "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="
+            "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
         },
         "jsdom": {
             "version": "15.2.1",
@@ -10869,7 +10869,7 @@
         "json-css": {
             "version": "1.5.6",
             "resolved": "https://registry.npmjs.org/json-css/-/json-css-1.5.6.tgz",
-            "integrity": "sha512-B/0T0OxZH9tSb93tXV6VOYtXqrPz/Vgz2QrCT/4NXen8HGElYkYr9V+8IrSVTMj/ftxa8cG1kcu7f3iAMlaFlQ=="
+            "integrity": "sha1-65ZPg0ouTqobwvaY/12wB6JsfAA="
         },
         "json-parse-better-errors": {
             "version": "1.0.2",
@@ -10900,7 +10900,7 @@
         "json-stringify-safe": {
             "version": "5.0.1",
             "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
-            "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
+            "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
         },
         "json5": {
             "version": "1.0.1",
@@ -10922,7 +10922,7 @@
         "jsonfile": {
             "version": "2.4.0",
             "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
-            "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==",
+            "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
             "requires": {
                 "graceful-fs": "^4.1.6"
             }
@@ -11031,7 +11031,7 @@
         "jstransformer": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz",
-            "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==",
+            "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=",
             "requires": {
                 "is-promise": "^2.0.0",
                 "promise": "^7.0.1"
@@ -11153,7 +11153,7 @@
         "klaw": {
             "version": "1.3.1",
             "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
-            "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==",
+            "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=",
             "requires": {
                 "graceful-fs": "^4.1.9"
             }
@@ -11181,7 +11181,7 @@
         "latest-version": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz",
-            "integrity": "sha512-Be1YRHWWlZaSsrz2U+VInk+tO0EwLIyV+23RhWLINJYwg/UIikxjlj3MhH37/6/EDCAusjajvMkMMUXRaMWl/w==",
+            "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=",
             "requires": {
                 "package-json": "^4.0.0"
             }
@@ -11189,7 +11189,7 @@
         "lazy-cache": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
-            "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ=="
+            "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4="
         },
         "lazystream": {
             "version": "1.0.1",
@@ -11218,7 +11218,7 @@
         "levn": {
             "version": "0.3.0",
             "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
-            "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
+            "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
             "dev": true,
             "requires": {
                 "prelude-ls": "~1.1.2",
@@ -11241,7 +11241,7 @@
         "load-json-file": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
-            "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==",
+            "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
             "requires": {
                 "graceful-fs": "^4.1.2",
                 "parse-json": "^2.2.0",
@@ -11253,7 +11253,7 @@
                 "parse-json": {
                     "version": "2.2.0",
                     "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
-                    "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==",
+                    "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
                     "requires": {
                         "error-ex": "^1.2.0"
                     }
@@ -11298,22 +11298,22 @@
         "lodash._getnative": {
             "version": "3.9.1",
             "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
-            "integrity": "sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA=="
+            "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U="
         },
         "lodash.chunk": {
             "version": "4.2.0",
             "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz",
-            "integrity": "sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w=="
+            "integrity": "sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw="
         },
         "lodash.curry": {
             "version": "4.1.1",
             "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz",
-            "integrity": "sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA=="
+            "integrity": "sha1-JI42By7ekGUB11lmIAqG2riyMXA="
         },
         "lodash.debounce": {
             "version": "3.1.1",
             "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-3.1.1.tgz",
-            "integrity": "sha512-lcmJwMpdPAtChA4hfiwxTtgFeNAaow701wWUgVUqeD0XJF7vMXIN+bu/2FJSGxT0NUbZy9g9VFrlOFfPjl+0Ew==",
+            "integrity": "sha1-gSIRw3ipTMKdWqTjNGzwv846ffU=",
             "requires": {
                 "lodash._getnative": "^3.0.0"
             }
@@ -11321,42 +11321,42 @@
         "lodash.defaults": {
             "version": "4.2.0",
             "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
-            "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
+            "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw="
         },
         "lodash.difference": {
             "version": "4.5.0",
             "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
-            "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA=="
+            "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw="
         },
         "lodash.flatten": {
             "version": "4.4.0",
             "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
-            "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g=="
+            "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8="
         },
         "lodash.flow": {
             "version": "3.5.0",
             "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz",
-            "integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw=="
+            "integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o="
         },
         "lodash.get": {
             "version": "4.4.2",
             "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
-            "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ=="
+            "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
         },
         "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": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
+            "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
         },
         "lodash.memoize": {
             "version": "4.1.2",
             "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
-            "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag=="
+            "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
         },
         "lodash.merge": {
             "version": "4.6.2",
@@ -11366,23 +11366,23 @@
         "lodash.padend": {
             "version": "4.6.1",
             "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz",
-            "integrity": "sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw=="
+            "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4="
         },
         "lodash.sortby": {
             "version": "4.7.0",
             "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
-            "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==",
+            "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
             "dev": true
         },
         "lodash.throttle": {
             "version": "4.1.1",
             "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
-            "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="
+            "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
         },
         "lodash.union": {
             "version": "4.6.0",
             "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
-            "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw=="
+            "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg="
         },
         "log-symbols": {
             "version": "2.2.0",
@@ -11410,7 +11410,7 @@
         "longest": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
-            "integrity": "sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg=="
+            "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
         },
         "longest-streak": {
             "version": "3.0.1",
@@ -11428,7 +11428,7 @@
         "loud-rejection": {
             "version": "1.6.0",
             "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
-            "integrity": "sha512-RPNliZOFkqFumDhvYqOaNY4Uz9oJM2K9tC6JWsJJsNdhuONW4LQHRBpb0qf4pJApVffI5N39SwzWZJuEhfd7eQ==",
+            "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
             "requires": {
                 "currently-unhandled": "^0.4.1",
                 "signal-exit": "^3.0.0"
@@ -11477,7 +11477,7 @@
                 "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==",
+                    "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
                     "requires": {
                         "locate-path": "^2.0.0"
                     }
@@ -11485,7 +11485,7 @@
                 "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==",
+                    "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
                     "requires": {
                         "p-locate": "^2.0.0",
                         "path-exists": "^3.0.0"
@@ -11502,7 +11502,7 @@
                 "p-locate": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
-                    "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
+                    "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
                     "requires": {
                         "p-limit": "^1.1.0"
                     }
@@ -11510,7 +11510,7 @@
                 "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=="
+                    "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
                 }
             }
         },
@@ -11538,17 +11538,17 @@
         "map-cache": {
             "version": "0.2.2",
             "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
-            "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg=="
+            "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8="
         },
         "map-obj": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
-            "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg=="
+            "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0="
         },
         "map-visit": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
-            "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==",
+            "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
             "requires": {
                 "object-visit": "^1.0.0"
             }
@@ -11598,7 +11598,7 @@
         "math-codegen": {
             "version": "0.3.5",
             "resolved": "https://registry.npmjs.org/math-codegen/-/math-codegen-0.3.5.tgz",
-            "integrity": "sha512-SsFYMv33FxMKYxI1PBiaZT+8AeDITK+k/PKhbHNlOPHIz5FIPF4wy78yWqanN6luXdsXENUZgCIC6xH6bfUq1g==",
+            "integrity": "sha1-R5nuRnfe0Ud2bQA8ykt4ee3UDMo=",
             "requires": {
                 "extend": "^3.0.0",
                 "mr-parser": "^0.2.1"
@@ -11607,7 +11607,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"
             },
@@ -11615,14 +11615,19 @@
                 "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": "sha512-CHZ/Nopqh46UtA0YvLclxj9F95qExLmTnMS5fnYlXvX4zj1RUOC3cPaGEOMhdPE8SSudSQ6wkQUJLA5E/WeL4A=="
+            "integrity": "sha1-84BgvixWPYwC5tSK85Ei/YO29BA="
+        },
+        "md5-file": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-5.0.0.tgz",
+            "integrity": "sha512-xbEFXCYVWrSx/gEKS1VPlg84h/4L20znVIulKw6kMfmBUAZNAnF00eczz9ICMl+/hjQGo5KSXRxbL/47X3rmMw=="
         },
         "mdast-util-definitions": {
             "version": "5.1.1",
@@ -11778,7 +11783,7 @@
         "media-typer": {
             "version": "0.3.0",
             "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
-            "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
+            "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
         },
         "memfs": {
             "version": "3.4.4",
@@ -11829,12 +11834,12 @@
         "memorystream": {
             "version": "0.3.1",
             "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
-            "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw=="
+            "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI="
         },
         "meow": {
             "version": "3.7.0",
             "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
-            "integrity": "sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==",
+            "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
             "requires": {
                 "camelcase-keys": "^2.0.0",
                 "decamelize": "^1.1.2",
@@ -11859,7 +11864,7 @@
         "merge-descriptors": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
-            "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
+            "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
         },
         "merge-stream": {
             "version": "2.0.0",
@@ -11870,7 +11875,7 @@
         "methods": {
             "version": "1.1.2",
             "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
-            "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
+            "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
         },
         "microevent.ts": {
             "version": "0.1.1",
@@ -12419,7 +12424,7 @@
                 "he": {
                     "version": "1.1.1",
                     "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
-                    "integrity": "sha512-z/GDPjlRMNOa2XJiB4em8wJpuuBfrFOlYKTZxtpkdr1uPdibHI8rYA3MY0KDObpVyaes0e/aunid/t88ZI2EKA==",
+                    "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
                     "dev": true
                 },
                 "minimatch": {
@@ -12434,13 +12439,13 @@
                 "minimist": {
                     "version": "0.0.8",
                     "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
-                    "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==",
+                    "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
                     "dev": true
                 },
                 "mkdirp": {
                     "version": "0.5.1",
                     "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
-                    "integrity": "sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==",
+                    "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
                     "dev": true,
                     "requires": {
                         "minimist": "0.0.8"
@@ -12449,7 +12454,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
                     "dev": true
                 },
                 "supports-color": {
@@ -12573,7 +12578,7 @@
         "move-concurrently": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
-            "integrity": "sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==",
+            "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
             "dev": true,
             "requires": {
                 "aproba": "^1.1.1",
@@ -12634,14 +12639,14 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
                 }
             }
         },
         "mr-parser": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/mr-parser/-/mr-parser-0.2.1.tgz",
-            "integrity": "sha512-hug+mpbSSKnH13rFqy3zm+XiG+QTStiDAgMTHK355TIstQE0qBkBtSJsa5YHP94AuarVX9b/4dcebdTRZ9YiEw=="
+            "integrity": "sha1-hhi5ukF+KOn0OaQcaVtVTq/u2Sc="
         },
         "mri": {
             "version": "1.2.0",
@@ -12666,7 +12671,7 @@
         "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": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==",
+            "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
             "dev": true
         },
         "mute-stream": {
@@ -12711,7 +12716,7 @@
         "native-or-bluebird": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.2.0.tgz",
-            "integrity": "sha512-0SH8UubxDfe382eYiwmd12qxAbiWGzlGZv6CkMA+DPojWa/Y0oH4hE0lRtFfFgJmPQFyKXeB8XxPbZz6TvvKaQ=="
+            "integrity": "sha1-OcR7/Xgl0fuf+tMiEK4l2q3xAck="
         },
         "natural-compare": {
             "version": "1.4.0",
@@ -12738,7 +12743,7 @@
         "nextafter": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/nextafter/-/nextafter-1.0.0.tgz",
-            "integrity": "sha512-7PO+A89Tll2rSEfyrjtqO0MaI37+nnxBdnQcPypfbEYYuGaJxWGCqaOwQX4a3GHNTS08l1kazuiLEWZniZjMUQ==",
+            "integrity": "sha1-t9d7U1MQ4+CX5gJauwqQNHfsGjo=",
             "requires": {
                 "double-bits": "^1.1.0"
             }
@@ -12769,7 +12774,7 @@
         "node-ensure": {
             "version": "0.0.0",
             "resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz",
-            "integrity": "sha512-DRI60hzo2oKN1ma0ckc6nQWlHU69RH6xN0sjQTjMpChPfTYvKZdcQFfdYK2RWbJcKyUizSIy/l8OTGxMAM1QDw=="
+            "integrity": "sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc="
         },
         "node-environment-flags": {
             "version": "1.0.5",
@@ -12858,7 +12863,7 @@
                 "nopt": {
                     "version": "3.0.6",
                     "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
-                    "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==",
+                    "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
                     "requires": {
                         "abbrev": "1"
                     }
@@ -12899,7 +12904,7 @@
                 "semver": {
                     "version": "5.3.0",
                     "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
-                    "integrity": "sha512-mfmm3/H9+67MCVix1h+IXTpDwL6710LyHuk7+cWC9T1mE0qz4iHhh6r4hU2wrIT9iTsAAC2XQRvfblL028cpLw=="
+                    "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
                 },
                 "string-width": {
                     "version": "1.0.2",
@@ -12963,12 +12968,12 @@
                 "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=="
+                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
                 },
                 "ansi-styles": {
                     "version": "2.2.1",
                     "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-                    "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA=="
+                    "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
                 },
                 "aproba": {
                     "version": "1.2.0",
@@ -12987,7 +12992,7 @@
                 "chalk": {
                     "version": "1.1.3",
                     "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-                    "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
+                    "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
                     "requires": {
                         "ansi-styles": "^2.2.1",
                         "escape-string-regexp": "^1.0.2",
@@ -13014,7 +13019,7 @@
                 "get-stdin": {
                     "version": "4.0.1",
                     "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
-                    "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw=="
+                    "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4="
                 },
                 "is-fullwidth-code-point": {
                     "version": "1.0.0",
@@ -13112,7 +13117,7 @@
         "noop-logger": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
-            "integrity": "sha512-6kM8CLXvuW5crTxsAtva2YLrRrDaiTIkIePWs9moLHqbFWT94WpNFjwS/5dfLfECg5i/lkmw3aoqVidxt23TEQ=="
+            "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI="
         },
         "nopt": {
             "version": "5.0.0",
@@ -13288,12 +13293,12 @@
                 },
                 "abbrev": {
                     "version": "1.1.1",
-                    "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
                 },
                 "agent-base": {
                     "version": "4.3.0",
-                    "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
                     "requires": {
                         "es6-promisify": "^5.0.0"
@@ -13301,7 +13306,7 @@
                 },
                 "agentkeepalive": {
                     "version": "3.5.2",
-                    "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==",
                     "requires": {
                         "humanize-ms": "^1.2.1"
@@ -13309,7 +13314,7 @@
                 },
                 "ansi-align": {
                     "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=",
                     "requires": {
                         "string-width": "^2.0.0"
@@ -13317,12 +13322,12 @@
                 },
                 "ansi-regex": {
                     "version": "2.1.1",
-                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
                 },
                 "ansi-styles": {
                     "version": "3.2.1",
-                    "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
                     "requires": {
                         "color-convert": "^1.9.0"
@@ -13330,27 +13335,27 @@
                 },
                 "ansicolors": {
                     "version": "0.3.2",
-                    "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk="
                 },
                 "ansistyles": {
                     "version": "0.1.3",
-                    "resolved": "https://registry.npmjs.org/ansistyles/-/ansistyles-0.1.3.tgz",
+                    "resolved": false,
                     "integrity": "sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk="
                 },
                 "aproba": {
                     "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ=="
                 },
                 "archy": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA="
                 },
                 "are-we-there-yet": {
                     "version": "1.1.4",
-                    "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz",
+                    "resolved": false,
                     "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
                     "requires": {
                         "delegates": "^1.0.0",
@@ -13359,7 +13364,7 @@
                     "dependencies": {
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+                            "resolved": false,
                             "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
                             "requires": {
                                 "core-util-is": "~1.0.0",
@@ -13373,7 +13378,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
                             "requires": {
                                 "safe-buffer": "~5.1.0"
@@ -13383,12 +13388,12 @@
                 },
                 "asap": {
                     "version": "2.0.6",
-                    "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+                    "resolved": false,
                     "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
                 },
                 "asn1": {
                     "version": "0.2.4",
-                    "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
                     "requires": {
                         "safer-buffer": "~2.1.0"
@@ -13396,32 +13401,32 @@
                 },
                 "assert-plus": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
                 },
                 "asynckit": {
                     "version": "0.4.0",
-                    "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
                 },
                 "aws-sign2": {
                     "version": "0.7.0",
-                    "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
                 },
                 "aws4": {
                     "version": "1.8.0",
-                    "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
                 },
                 "balanced-match": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
                 },
                 "bcrypt-pbkdf": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
                     "optional": true,
                     "requires": {
@@ -13430,7 +13435,7 @@
                 },
                 "bin-links": {
                     "version": "1.1.8",
-                    "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-1.1.8.tgz",
+                    "resolved": false,
                     "integrity": "sha512-KgmVfx+QqggqP9dA3iIc5pA4T1qEEEL+hOhOhNPaUm77OTrJoOXE/C05SJLNJe6m/2wUK7F1tDSou7n5TfCDzQ==",
                     "requires": {
                         "bluebird": "^3.5.3",
@@ -13443,12 +13448,12 @@
                 },
                 "bluebird": {
                     "version": "3.5.5",
-                    "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
+                    "resolved": false,
                     "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w=="
                 },
                 "boxen": {
                     "version": "1.3.0",
-                    "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==",
                     "requires": {
                         "ansi-align": "^2.0.0",
@@ -13462,7 +13467,7 @@
                 },
                 "brace-expansion": {
                     "version": "1.1.11",
-                    "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+                    "resolved": false,
                     "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
                     "requires": {
                         "balanced-match": "^1.0.0",
@@ -13471,27 +13476,27 @@
                 },
                 "buffer-from": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA=="
                 },
                 "builtins": {
                     "version": "1.0.3",
-                    "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og="
                 },
                 "byline": {
                     "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE="
                 },
                 "byte-size": {
                     "version": "5.0.1",
-                    "resolved": "https://registry.npmjs.org/byte-size/-/byte-size-5.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw=="
                 },
                 "cacache": {
                     "version": "12.0.3",
-                    "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==",
                     "requires": {
                         "bluebird": "^3.5.5",
@@ -13513,27 +13518,27 @@
                 },
                 "call-limit": {
                     "version": "1.1.1",
-                    "resolved": "https://registry.npmjs.org/call-limit/-/call-limit-1.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-5twvci5b9eRBw2wCfPtN0GmlR2/gadZqyFpPhOK6CvMFoFgA+USnZ6Jpu1lhG9h85pQ3Ouil3PfXWRD4EUaRiQ=="
                 },
                 "camelcase": {
                     "version": "4.1.0",
-                    "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
                 },
                 "capture-stack-trace": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0="
                 },
                 "caseless": {
                     "version": "0.12.0",
-                    "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
                 },
                 "chalk": {
                     "version": "2.4.1",
-                    "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
                     "requires": {
                         "ansi-styles": "^3.2.1",
@@ -13543,17 +13548,17 @@
                 },
                 "chownr": {
                     "version": "1.1.4",
-                    "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
                 },
                 "ci-info": {
                     "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="
                 },
                 "cidr-regex": {
                     "version": "2.0.10",
-                    "resolved": "https://registry.npmjs.org/cidr-regex/-/cidr-regex-2.0.10.tgz",
+                    "resolved": false,
                     "integrity": "sha512-sB3ogMQXWvreNPbJUZMRApxuRYd+KoIo4RGQ81VatjmMW6WJPo+IJZ2846FGItr9VzKo5w7DXzijPLGtSd0N3Q==",
                     "requires": {
                         "ip-regex": "^2.1.0"
@@ -13561,12 +13566,12 @@
                 },
                 "cli-boxes": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM="
                 },
                 "cli-columns": {
                     "version": "3.1.2",
-                    "resolved": "https://registry.npmjs.org/cli-columns/-/cli-columns-3.1.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-ZzLZcpee/CrkRKHwjgj6E5yWoY4=",
                     "requires": {
                         "string-width": "^2.0.0",
@@ -13575,7 +13580,7 @@
                 },
                 "cli-table3": {
                     "version": "0.5.1",
-                    "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==",
                     "requires": {
                         "colors": "^1.1.2",
@@ -13585,7 +13590,7 @@
                 },
                 "cliui": {
                     "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
                     "requires": {
                         "string-width": "^3.1.0",
@@ -13595,17 +13600,17 @@
                     "dependencies": {
                         "ansi-regex": {
                             "version": "4.1.1",
-                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="
                         },
                         "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",
+                            "resolved": false,
                             "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
                         },
                         "string-width": {
                             "version": "3.1.0",
-                            "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
                             "requires": {
                                 "emoji-regex": "^7.0.1",
@@ -13615,7 +13620,7 @@
                         },
                         "strip-ansi": {
                             "version": "5.2.0",
-                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
                             "requires": {
                                 "ansi-regex": "^4.1.0"
@@ -13625,12 +13630,12 @@
                 },
                 "clone": {
                     "version": "1.0.4",
-                    "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+                    "resolved": false,
                     "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4="
                 },
                 "cmd-shim": {
                     "version": "3.0.3",
-                    "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-3.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-DtGg+0xiFhQIntSBRzL2fRQBnmtAVwXIDo4Qq46HPpObYquxMaZS4sb82U9nH91qJrlosC1wa9gwr0QyL/HypA==",
                     "requires": {
                         "graceful-fs": "^4.1.2",
@@ -13639,12 +13644,12 @@
                 },
                 "code-point-at": {
                     "version": "1.1.0",
-                    "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
                 },
                 "color-convert": {
                     "version": "1.9.1",
-                    "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==",
                     "requires": {
                         "color-name": "^1.1.1"
@@ -13652,18 +13657,18 @@
                 },
                 "color-name": {
                     "version": "1.1.3",
-                    "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+                    "resolved": false,
                     "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
                 },
                 "colors": {
                     "version": "1.3.3",
-                    "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==",
                     "optional": true
                 },
                 "columnify": {
                     "version": "1.5.4",
-                    "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz",
+                    "resolved": false,
                     "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=",
                     "requires": {
                         "strip-ansi": "^3.0.0",
@@ -13672,7 +13677,7 @@
                 },
                 "combined-stream": {
                     "version": "1.0.6",
-                    "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
+                    "resolved": false,
                     "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
                     "requires": {
                         "delayed-stream": "~1.0.0"
@@ -13680,12 +13685,12 @@
                 },
                 "concat-map": {
                     "version": "0.0.1",
-                    "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
                 },
                 "concat-stream": {
                     "version": "1.6.2",
-                    "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
                     "requires": {
                         "buffer-from": "^1.0.0",
@@ -13696,7 +13701,7 @@
                     "dependencies": {
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+                            "resolved": false,
                             "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
                             "requires": {
                                 "core-util-is": "~1.0.0",
@@ -13710,7 +13715,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
                             "requires": {
                                 "safe-buffer": "~5.1.0"
@@ -13720,7 +13725,7 @@
                 },
                 "config-chain": {
                     "version": "1.1.12",
-                    "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz",
+                    "resolved": false,
                     "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==",
                     "requires": {
                         "ini": "^1.3.4",
@@ -13729,7 +13734,7 @@
                 },
                 "configstore": {
                     "version": "3.1.5",
-                    "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.5.tgz",
+                    "resolved": false,
                     "integrity": "sha512-nlOhI4+fdzoK5xmJ+NY+1gZK56bwEaWZr8fYuXohZ9Vkc1o3a4T/R3M+yE/w7x/ZVJ1zF8c+oaOvF0dztdUgmA==",
                     "requires": {
                         "dot-prop": "^4.2.1",
@@ -13742,12 +13747,12 @@
                 },
                 "console-control-strings": {
                     "version": "1.1.0",
-                    "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
                 },
                 "copy-concurrently": {
                     "version": "1.0.5",
-                    "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
+                    "resolved": false,
                     "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
                     "requires": {
                         "aproba": "^1.1.1",
@@ -13760,24 +13765,24 @@
                     "dependencies": {
                         "aproba": {
                             "version": "1.2.0",
-                            "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
                         },
                         "iferr": {
                             "version": "0.1.5",
-                            "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
+                            "resolved": false,
                             "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE="
                         }
                     }
                 },
                 "core-util-is": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
                 },
                 "create-error-class": {
                     "version": "3.0.2",
-                    "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=",
                     "requires": {
                         "capture-stack-trace": "^1.0.0"
@@ -13785,7 +13790,7 @@
                 },
                 "cross-spawn": {
                     "version": "5.1.0",
-                    "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
                     "requires": {
                         "lru-cache": "^4.0.1",
@@ -13795,7 +13800,7 @@
                     "dependencies": {
                         "lru-cache": {
                             "version": "4.1.5",
-                            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+                            "resolved": false,
                             "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
                             "requires": {
                                 "pseudomap": "^1.0.2",
@@ -13804,24 +13809,24 @@
                         },
                         "yallist": {
                             "version": "2.1.2",
-                            "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+                            "resolved": false,
                             "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
                         }
                     }
                 },
                 "crypto-random-string": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4="
                 },
                 "cyclist": {
                     "version": "0.2.2",
-                    "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA="
                 },
                 "dashdash": {
                     "version": "1.14.1",
-                    "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
                     "requires": {
                         "assert-plus": "^1.0.0"
@@ -13829,7 +13834,7 @@
                 },
                 "debug": {
                     "version": "3.1.0",
-                    "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
                     "requires": {
                         "ms": "2.0.0"
@@ -13837,34 +13842,34 @@
                     "dependencies": {
                         "ms": {
                             "version": "2.0.0",
-                            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+                            "resolved": false,
                             "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
                         }
                     }
                 },
                 "debuglog": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI="
                 },
                 "decamelize": {
                     "version": "1.2.0",
-                    "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
                 },
                 "decode-uri-component": {
                     "version": "0.2.0",
-                    "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
                 },
                 "deep-extend": {
                     "version": "0.6.0",
-                    "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
                 },
                 "defaults": {
                     "version": "1.0.3",
-                    "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
                     "requires": {
                         "clone": "^1.0.2"
@@ -13872,7 +13877,7 @@
                 },
                 "define-properties": {
                     "version": "1.1.3",
-                    "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
                     "requires": {
                         "object-keys": "^1.0.12"
@@ -13880,27 +13885,27 @@
                 },
                 "delayed-stream": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
                 },
                 "delegates": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
                 },
                 "detect-indent": {
                     "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50="
                 },
                 "detect-newline": {
                     "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I="
                 },
                 "dezalgo": {
                     "version": "1.0.3",
-                    "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=",
                     "requires": {
                         "asap": "^2.0.0",
@@ -13909,7 +13914,7 @@
                 },
                 "dot-prop": {
                     "version": "4.2.1",
-                    "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==",
                     "requires": {
                         "is-obj": "^1.0.0"
@@ -13917,17 +13922,17 @@
                 },
                 "dotenv": {
                     "version": "5.0.1",
-                    "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-5.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow=="
                 },
                 "duplexer3": {
                     "version": "0.1.4",
-                    "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
+                    "resolved": false,
                     "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
                 },
                 "duplexify": {
                     "version": "3.6.0",
-                    "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==",
                     "requires": {
                         "end-of-stream": "^1.0.0",
@@ -13938,7 +13943,7 @@
                     "dependencies": {
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+                            "resolved": false,
                             "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
                             "requires": {
                                 "core-util-is": "~1.0.0",
@@ -13952,7 +13957,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
                             "requires": {
                                 "safe-buffer": "~5.1.0"
@@ -13962,7 +13967,7 @@
                 },
                 "ecc-jsbn": {
                     "version": "0.1.2",
-                    "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
                     "optional": true,
                     "requires": {
@@ -13972,17 +13977,17 @@
                 },
                 "editor": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/editor/-/editor-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-YMf4e9YrzGqJT6jM1q+3gjok90I="
                 },
                 "emoji-regex": {
                     "version": "7.0.3",
-                    "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
                 },
                 "encoding": {
                     "version": "0.1.12",
-                    "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
+                    "resolved": false,
                     "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
                     "requires": {
                         "iconv-lite": "~0.4.13"
@@ -13990,7 +13995,7 @@
                 },
                 "end-of-stream": {
                     "version": "1.4.1",
-                    "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
                     "requires": {
                         "once": "^1.4.0"
@@ -13998,17 +14003,17 @@
                 },
                 "env-paths": {
                     "version": "2.2.0",
-                    "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA=="
                 },
                 "err-code": {
                     "version": "1.1.2",
-                    "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA="
                 },
                 "errno": {
                     "version": "0.1.7",
-                    "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+                    "resolved": false,
                     "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
                     "requires": {
                         "prr": "~1.0.1"
@@ -14016,7 +14021,7 @@
                 },
                 "es-abstract": {
                     "version": "1.12.0",
-                    "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
                     "requires": {
                         "es-to-primitive": "^1.1.1",
@@ -14028,7 +14033,7 @@
                 },
                 "es-to-primitive": {
                     "version": "1.2.0",
-                    "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
                     "requires": {
                         "is-callable": "^1.1.4",
@@ -14038,12 +14043,12 @@
                 },
                 "es6-promise": {
                     "version": "4.2.8",
-                    "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
+                    "resolved": false,
                     "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
                 },
                 "es6-promisify": {
                     "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
                     "requires": {
                         "es6-promise": "^4.0.3"
@@ -14051,12 +14056,12 @@
                 },
                 "escape-string-regexp": {
                     "version": "1.0.5",
-                    "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+                    "resolved": false,
                     "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
                 },
                 "execa": {
                     "version": "0.7.0",
-                    "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
                     "requires": {
                         "cross-spawn": "^5.0.1",
@@ -14070,39 +14075,39 @@
                     "dependencies": {
                         "get-stream": {
                             "version": "3.0.0",
-                            "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+                            "resolved": false,
                             "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
                         }
                     }
                 },
                 "extend": {
                     "version": "3.0.2",
-                    "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
                 },
                 "extsprintf": {
                     "version": "1.3.0",
-                    "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
                 },
                 "fast-json-stable-stringify": {
                     "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
                 },
                 "figgy-pudding": {
                     "version": "3.5.1",
-                    "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w=="
                 },
                 "find-npm-prefix": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/find-npm-prefix/-/find-npm-prefix-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-KEftzJ+H90x6pcKtdXZEPsQse8/y/UnvzRKrOSQFprnrGaFuJ62fVkP34Iu2IYuMvyauCyoLTNkJZgrrGA2wkA=="
                 },
                 "flush-write-stream": {
                     "version": "1.0.3",
-                    "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==",
                     "requires": {
                         "inherits": "^2.0.1",
@@ -14111,7 +14116,7 @@
                     "dependencies": {
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+                            "resolved": false,
                             "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
                             "requires": {
                                 "core-util-is": "~1.0.0",
@@ -14125,7 +14130,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
                             "requires": {
                                 "safe-buffer": "~5.1.0"
@@ -14135,12 +14140,12 @@
                 },
                 "forever-agent": {
                     "version": "0.6.1",
-                    "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
                 },
                 "form-data": {
                     "version": "2.3.2",
-                    "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
                     "requires": {
                         "asynckit": "^0.4.0",
@@ -14150,7 +14155,7 @@
                 },
                 "from2": {
                     "version": "2.3.0",
-                    "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
                     "requires": {
                         "inherits": "^2.0.1",
@@ -14159,7 +14164,7 @@
                     "dependencies": {
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+                            "resolved": false,
                             "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
                             "requires": {
                                 "core-util-is": "~1.0.0",
@@ -14173,7 +14178,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
                             "requires": {
                                 "safe-buffer": "~5.1.0"
@@ -14183,7 +14188,7 @@
                 },
                 "fs-minipass": {
                     "version": "1.2.7",
-                    "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
+                    "resolved": false,
                     "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
                     "requires": {
                         "minipass": "^2.6.0"
@@ -14191,7 +14196,7 @@
                     "dependencies": {
                         "minipass": {
                             "version": "2.9.0",
-                            "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
                             "requires": {
                                 "safe-buffer": "^5.1.2",
@@ -14202,7 +14207,7 @@
                 },
                 "fs-vacuum": {
                     "version": "1.2.10",
-                    "resolved": "https://registry.npmjs.org/fs-vacuum/-/fs-vacuum-1.2.10.tgz",
+                    "resolved": false,
                     "integrity": "sha1-t2Kb7AekAxolSP35n17PHMizHjY=",
                     "requires": {
                         "graceful-fs": "^4.1.2",
@@ -14212,7 +14217,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",
+                    "resolved": false,
                     "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
                     "requires": {
                         "graceful-fs": "^4.1.2",
@@ -14223,12 +14228,12 @@
                     "dependencies": {
                         "iferr": {
                             "version": "0.1.5",
-                            "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
+                            "resolved": false,
                             "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE="
                         },
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+                            "resolved": false,
                             "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
                             "requires": {
                                 "core-util-is": "~1.0.0",
@@ -14242,7 +14247,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
                             "requires": {
                                 "safe-buffer": "~5.1.0"
@@ -14252,17 +14257,17 @@
                 },
                 "fs.realpath": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
                 },
                 "function-bind": {
                     "version": "1.1.1",
-                    "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
                 },
                 "gauge": {
                     "version": "2.7.4",
-                    "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+                    "resolved": false,
                     "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
                     "requires": {
                         "aproba": "^1.0.3",
@@ -14277,12 +14282,12 @@
                     "dependencies": {
                         "aproba": {
                             "version": "1.2.0",
-                            "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
                         },
                         "string-width": {
                             "version": "1.0.2",
-                            "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+                            "resolved": false,
                             "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
                             "requires": {
                                 "code-point-at": "^1.0.0",
@@ -14294,12 +14299,12 @@
                 },
                 "genfun": {
                     "version": "5.0.0",
-                    "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA=="
                 },
                 "gentle-fs": {
                     "version": "2.3.1",
-                    "resolved": "https://registry.npmjs.org/gentle-fs/-/gentle-fs-2.3.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-OlwBBwqCFPcjm33rF2BjW+Pr6/ll2741l+xooiwTCeaX2CA1ZuclavyMBe0/KlR21/XGsgY6hzEQZ15BdNa13Q==",
                     "requires": {
                         "aproba": "^1.1.2",
@@ -14317,24 +14322,24 @@
                     "dependencies": {
                         "aproba": {
                             "version": "1.2.0",
-                            "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
                         },
                         "iferr": {
                             "version": "0.1.5",
-                            "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
+                            "resolved": false,
                             "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE="
                         }
                     }
                 },
                 "get-caller-file": {
                     "version": "2.0.5",
-                    "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+                    "resolved": false,
                     "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
                 },
                 "get-stream": {
                     "version": "4.1.0",
-                    "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
                     "requires": {
                         "pump": "^3.0.0"
@@ -14342,7 +14347,7 @@
                 },
                 "getpass": {
                     "version": "0.1.7",
-                    "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+                    "resolved": false,
                     "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
                     "requires": {
                         "assert-plus": "^1.0.0"
@@ -14350,7 +14355,7 @@
                 },
                 "glob": {
                     "version": "7.1.6",
-                    "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+                    "resolved": false,
                     "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
                     "requires": {
                         "fs.realpath": "^1.0.0",
@@ -14363,7 +14368,7 @@
                 },
                 "global-dirs": {
                     "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=",
                     "requires": {
                         "ini": "^1.3.4"
@@ -14371,7 +14376,7 @@
                 },
                 "got": {
                     "version": "6.7.1",
-                    "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
                     "requires": {
                         "create-error-class": "^3.0.0",
@@ -14389,24 +14394,24 @@
                     "dependencies": {
                         "get-stream": {
                             "version": "3.0.0",
-                            "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+                            "resolved": false,
                             "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
                         }
                     }
                 },
                 "graceful-fs": {
                     "version": "4.2.4",
-                    "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
                 },
                 "har-schema": {
                     "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
                 },
                 "har-validator": {
                     "version": "5.1.5",
-                    "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
+                    "resolved": false,
                     "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
                     "requires": {
                         "ajv": "^6.12.3",
@@ -14415,7 +14420,7 @@
                     "dependencies": {
                         "ajv": {
                             "version": "6.12.6",
-                            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+                            "resolved": false,
                             "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
                             "requires": {
                                 "fast-deep-equal": "^3.1.1",
@@ -14426,19 +14431,19 @@
                         },
                         "fast-deep-equal": {
                             "version": "3.1.3",
-                            "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+                            "resolved": false,
                             "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
                         },
                         "json-schema-traverse": {
                             "version": "0.4.1",
-                            "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
                         }
                     }
                 },
                 "has": {
                     "version": "1.0.3",
-                    "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
                     "requires": {
                         "function-bind": "^1.1.1"
@@ -14446,32 +14451,32 @@
                 },
                 "has-flag": {
                     "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
                 },
                 "has-symbols": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q="
                 },
                 "has-unicode": {
                     "version": "2.0.1",
-                    "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
                 },
                 "hosted-git-info": {
                     "version": "2.8.9",
-                    "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+                    "resolved": false,
                     "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="
                 },
                 "http-cache-semantics": {
                     "version": "3.8.1",
-                    "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w=="
                 },
                 "http-proxy-agent": {
                     "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==",
                     "requires": {
                         "agent-base": "4",
@@ -14480,7 +14485,7 @@
                 },
                 "http-signature": {
                     "version": "1.2.0",
-                    "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
                     "requires": {
                         "assert-plus": "^1.0.0",
@@ -14490,7 +14495,7 @@
                 },
                 "https-proxy-agent": {
                     "version": "2.2.4",
-                    "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
                     "requires": {
                         "agent-base": "^4.3.0",
@@ -14499,7 +14504,7 @@
                 },
                 "humanize-ms": {
                     "version": "1.2.1",
-                    "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=",
                     "requires": {
                         "ms": "^2.0.0"
@@ -14507,7 +14512,7 @@
                 },
                 "iconv-lite": {
                     "version": "0.4.23",
-                    "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
+                    "resolved": false,
                     "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
                     "requires": {
                         "safer-buffer": ">= 2.1.2 < 3"
@@ -14515,12 +14520,12 @@
                 },
                 "iferr": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/iferr/-/iferr-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-9AfeLfji44r5TKInjhz3W9DyZI1zR1JAf2hVBMGhddAKPqBsupb89jGfbCTHIGZd6fGZl9WlHdn4AObygyMKwg=="
                 },
                 "ignore-walk": {
                     "version": "3.0.3",
-                    "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
                     "requires": {
                         "minimatch": "^3.0.4"
@@ -14528,22 +14533,22 @@
                 },
                 "import-lazy": {
                     "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM="
                 },
                 "imurmurhash": {
                     "version": "0.1.4",
-                    "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+                    "resolved": false,
                     "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
                 },
                 "infer-owner": {
                     "version": "1.0.4",
-                    "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A=="
                 },
                 "inflight": {
                     "version": "1.0.6",
-                    "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+                    "resolved": false,
                     "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
                     "requires": {
                         "once": "^1.3.0",
@@ -14552,17 +14557,17 @@
                 },
                 "inherits": {
                     "version": "2.0.4",
-                    "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
                 },
                 "ini": {
                     "version": "1.3.8",
-                    "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+                    "resolved": false,
                     "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
                 },
                 "init-package-json": {
                     "version": "1.10.3",
-                    "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-1.10.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw==",
                     "requires": {
                         "glob": "^7.1.1",
@@ -14577,22 +14582,22 @@
                 },
                 "ip": {
                     "version": "1.1.5",
-                    "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
+                    "resolved": false,
                     "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo="
                 },
                 "ip-regex": {
                     "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk="
                 },
                 "is-callable": {
                     "version": "1.1.4",
-                    "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA=="
                 },
                 "is-ci": {
                     "version": "1.2.1",
-                    "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
                     "requires": {
                         "ci-info": "^1.5.0"
@@ -14600,14 +14605,14 @@
                     "dependencies": {
                         "ci-info": {
                             "version": "1.6.0",
-                            "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A=="
                         }
                     }
                 },
                 "is-cidr": {
                     "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/is-cidr/-/is-cidr-3.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-8Xnnbjsb0x462VoYiGlhEi+drY8SFwrHiSYuzc/CEwco55vkehTaxAyIjEdpi3EMvLPPJAJi9FlzP+h+03gp0Q==",
                     "requires": {
                         "cidr-regex": "^2.0.10"
@@ -14615,12 +14620,12 @@
                 },
                 "is-date-object": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
                 },
                 "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",
+                    "resolved": false,
                     "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
                     "requires": {
                         "number-is-nan": "^1.0.0"
@@ -14628,7 +14633,7 @@
                 },
                 "is-installed-globally": {
                     "version": "0.1.0",
-                    "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=",
                     "requires": {
                         "global-dirs": "^0.1.0",
@@ -14637,17 +14642,17 @@
                 },
                 "is-npm": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ="
                 },
                 "is-obj": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
                 },
                 "is-path-inside": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
                     "requires": {
                         "path-is-inside": "^1.0.1"
@@ -14655,12 +14660,12 @@
                 },
                 "is-redirect": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ="
                 },
                 "is-regex": {
                     "version": "1.0.4",
-                    "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
+                    "resolved": false,
                     "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
                     "requires": {
                         "has": "^1.0.1"
@@ -14668,17 +14673,17 @@
                 },
                 "is-retry-allowed": {
                     "version": "1.2.0",
-                    "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg=="
                 },
                 "is-stream": {
                     "version": "1.1.0",
-                    "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
                 },
                 "is-symbol": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
                     "requires": {
                         "has-symbols": "^1.0.0"
@@ -14686,43 +14691,43 @@
                 },
                 "is-typedarray": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
                 },
                 "isarray": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
                 },
                 "isexe": {
                     "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
                 },
                 "isstream": {
                     "version": "0.1.2",
-                    "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
                 },
                 "jsbn": {
                     "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
                     "optional": true
                 },
                 "json-parse-better-errors": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
                 },
                 "json-schema": {
                     "version": "0.4.0",
-                    "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
                 },
                 "json-stringify-safe": {
                     "version": "5.0.1",
-                    "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
                 },
                 "jsonparse": {
@@ -14732,7 +14737,7 @@
                 },
                 "jsprim": {
                     "version": "1.4.2",
-                    "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
                     "requires": {
                         "assert-plus": "1.0.0",
@@ -14743,7 +14748,7 @@
                 },
                 "latest-version": {
                     "version": "3.1.0",
-                    "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=",
                     "requires": {
                         "package-json": "^4.0.0"
@@ -14751,12 +14756,12 @@
                 },
                 "lazy-property": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/lazy-property/-/lazy-property-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-hN3Es3Bnm6i9TNz6TAa0PVcREUc="
                 },
                 "libcipm": {
                     "version": "4.0.8",
-                    "resolved": "https://registry.npmjs.org/libcipm/-/libcipm-4.0.8.tgz",
+                    "resolved": false,
                     "integrity": "sha512-IN3hh2yDJQtZZ5paSV4fbvJg4aHxCCg5tcZID/dSVlTuUiWktsgaldVljJv6Z5OUlYspx6xQkbR0efNodnIrOA==",
                     "requires": {
                         "bin-links": "^1.1.2",
@@ -14778,7 +14783,7 @@
                 },
                 "libnpm": {
                     "version": "3.0.1",
-                    "resolved": "https://registry.npmjs.org/libnpm/-/libnpm-3.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-d7jU5ZcMiTfBqTUJVZ3xid44fE5ERBm9vBnmhp2ECD2Ls+FNXWxHSkO7gtvrnbLO78gwPdNPz1HpsF3W4rjkBQ==",
                     "requires": {
                         "bin-links": "^1.1.2",
@@ -14805,7 +14810,7 @@
                 },
                 "libnpmaccess": {
                     "version": "3.0.2",
-                    "resolved": "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-3.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-01512AK7MqByrI2mfC7h5j8N9V4I7MHJuk9buo8Gv+5QgThpOgpjB7sQBDDkeZqRteFb1QM/6YNdHfG7cDvfAQ==",
                     "requires": {
                         "aproba": "^2.0.0",
@@ -14816,7 +14821,7 @@
                 },
                 "libnpmconfig": {
                     "version": "1.2.1",
-                    "resolved": "https://registry.npmjs.org/libnpmconfig/-/libnpmconfig-1.2.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-9esX8rTQAHqarx6qeZqmGQKBNZR5OIbl/Ayr0qQDy3oXja2iFVQQI81R6GZ2a02bSNZ9p3YOGX1O6HHCb1X7kA==",
                     "requires": {
                         "figgy-pudding": "^3.5.1",
@@ -14826,7 +14831,7 @@
                     "dependencies": {
                         "find-up": {
                             "version": "3.0.0",
-                            "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
                             "requires": {
                                 "locate-path": "^3.0.0"
@@ -14834,7 +14839,7 @@
                         },
                         "locate-path": {
                             "version": "3.0.0",
-                            "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
                             "requires": {
                                 "p-locate": "^3.0.0",
@@ -14843,7 +14848,7 @@
                         },
                         "p-limit": {
                             "version": "2.2.0",
-                            "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
                             "requires": {
                                 "p-try": "^2.0.0"
@@ -14851,7 +14856,7 @@
                         },
                         "p-locate": {
                             "version": "3.0.0",
-                            "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
                             "requires": {
                                 "p-limit": "^2.0.0"
@@ -14859,14 +14864,14 @@
                         },
                         "p-try": {
                             "version": "2.2.0",
-                            "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
                         }
                     }
                 },
                 "libnpmhook": {
                     "version": "5.0.3",
-                    "resolved": "https://registry.npmjs.org/libnpmhook/-/libnpmhook-5.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-UdNLMuefVZra/wbnBXECZPefHMGsVDTq5zaM/LgKNE9Keyl5YXQTnGAzEo+nFOpdRqTWI9LYi4ApqF9uVCCtuA==",
                     "requires": {
                         "aproba": "^2.0.0",
@@ -14877,7 +14882,7 @@
                 },
                 "libnpmorg": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/libnpmorg/-/libnpmorg-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-0sRUXLh+PLBgZmARvthhYXQAWn0fOsa6T5l3JSe2n9vKG/lCVK4nuG7pDsa7uMq+uTt2epdPK+a2g6btcY11Ww==",
                     "requires": {
                         "aproba": "^2.0.0",
@@ -14888,7 +14893,7 @@
                 },
                 "libnpmpublish": {
                     "version": "1.1.2",
-                    "resolved": "https://registry.npmjs.org/libnpmpublish/-/libnpmpublish-1.1.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-2yIwaXrhTTcF7bkJKIKmaCV9wZOALf/gsTDxVSu/Gu/6wiG3fA8ce8YKstiWKTxSFNC0R7isPUb6tXTVFZHt2g==",
                     "requires": {
                         "aproba": "^2.0.0",
@@ -14904,7 +14909,7 @@
                 },
                 "libnpmsearch": {
                     "version": "2.0.2",
-                    "resolved": "https://registry.npmjs.org/libnpmsearch/-/libnpmsearch-2.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-VTBbV55Q6fRzTdzziYCr64+f8AopQ1YZ+BdPOv16UegIEaE8C0Kch01wo4s3kRTFV64P121WZJwgmBwrq68zYg==",
                     "requires": {
                         "figgy-pudding": "^3.5.1",
@@ -14914,7 +14919,7 @@
                 },
                 "libnpmteam": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/libnpmteam/-/libnpmteam-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-p420vM28Us04NAcg1rzgGW63LMM6rwe+6rtZpfDxCcXxM0zUTLl7nPFEnRF3JfFBF5skF/yuZDUthTsHgde8QA==",
                     "requires": {
                         "aproba": "^2.0.0",
@@ -14925,7 +14930,7 @@
                 },
                 "libnpx": {
                     "version": "10.2.4",
-                    "resolved": "https://registry.npmjs.org/libnpx/-/libnpx-10.2.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-BPc0D1cOjBeS8VIBKUu5F80s6njm0wbVt7CsGMrIcJ+SI7pi7V0uVPGpEMH9H5L8csOcclTxAXFE2VAsJXUhfA==",
                     "requires": {
                         "dotenv": "^5.0.1",
@@ -14940,7 +14945,7 @@
                 },
                 "lock-verify": {
                     "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/lock-verify/-/lock-verify-2.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-vcLpxnGvrqisKvLQ2C2v0/u7LVly17ak2YSgoK4PrdsYBXQIax19vhKiLfvKNFx7FRrpTnitrpzF/uuCMuorIg==",
                     "requires": {
                         "npm-package-arg": "^6.1.0",
@@ -14949,7 +14954,7 @@
                 },
                 "lockfile": {
                     "version": "1.0.4",
-                    "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==",
                     "requires": {
                         "signal-exit": "^3.0.2"
@@ -14957,12 +14962,12 @@
                 },
                 "lodash._baseindexof": {
                     "version": "3.1.0",
-                    "resolved": "https://registry.npmjs.org/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw="
                 },
                 "lodash._baseuniq": {
                     "version": "4.6.0",
-                    "resolved": "https://registry.npmjs.org/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-DrtE5FaBSveQXGIS+iybLVG4Qeg=",
                     "requires": {
                         "lodash._createset": "~4.0.0",
@@ -14971,17 +14976,17 @@
                 },
                 "lodash._bindcallback": {
                     "version": "3.0.1",
-                    "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4="
                 },
                 "lodash._cacheindexof": {
                     "version": "3.0.2",
-                    "resolved": "https://registry.npmjs.org/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI="
                 },
                 "lodash._createcache": {
                     "version": "3.1.2",
-                    "resolved": "https://registry.npmjs.org/lodash._createcache/-/lodash._createcache-3.1.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=",
                     "requires": {
                         "lodash._getnative": "^3.0.0"
@@ -14989,52 +14994,52 @@
                 },
                 "lodash._createset": {
                     "version": "4.0.3",
-                    "resolved": "https://registry.npmjs.org/lodash._createset/-/lodash._createset-4.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY="
                 },
                 "lodash._getnative": {
                     "version": "3.9.1",
-                    "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U="
                 },
                 "lodash._root": {
                     "version": "3.0.1",
-                    "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI="
                 },
                 "lodash.clonedeep": {
                     "version": "4.5.0",
-                    "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8="
                 },
                 "lodash.restparam": {
                     "version": "3.6.1",
-                    "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU="
                 },
                 "lodash.union": {
                     "version": "4.6.0",
-                    "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg="
                 },
                 "lodash.uniq": {
                     "version": "4.5.0",
-                    "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M="
                 },
                 "lodash.without": {
                     "version": "4.4.0",
-                    "resolved": "https://registry.npmjs.org/lodash.without/-/lodash.without-4.4.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-PNRXSgC2e643OpS3SHcmQFB7eqw="
                 },
                 "lowercase-keys": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA=="
                 },
                 "lru-cache": {
                     "version": "5.1.1",
-                    "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
                     "requires": {
                         "yallist": "^3.0.2"
@@ -15042,7 +15047,7 @@
                 },
                 "make-dir": {
                     "version": "1.3.0",
-                    "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
                     "requires": {
                         "pify": "^3.0.0"
@@ -15050,7 +15055,7 @@
                 },
                 "make-fetch-happen": {
                     "version": "5.0.2",
-                    "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==",
                     "requires": {
                         "agentkeepalive": "^3.4.1",
@@ -15068,17 +15073,17 @@
                 },
                 "meant": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/meant/-/meant-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-KN+1uowN/NK+sT/Lzx7WSGIj2u+3xe5n2LbwObfjOhPZiA+cCfCm6idVl0RkEfjThkw5XJ96CyRcanq6GmKtUg=="
                 },
                 "mime-db": {
                     "version": "1.35.0",
-                    "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg=="
                 },
                 "mime-types": {
                     "version": "2.1.19",
-                    "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz",
+                    "resolved": false,
                     "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==",
                     "requires": {
                         "mime-db": "~1.35.0"
@@ -15086,7 +15091,7 @@
                 },
                 "minimatch": {
                     "version": "3.0.4",
-                    "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
                     "requires": {
                         "brace-expansion": "^1.1.7"
@@ -15094,12 +15099,12 @@
                 },
                 "minimist": {
                     "version": "1.2.6",
-                    "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+                    "resolved": false,
                     "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
                 },
                 "minizlib": {
                     "version": "1.3.3",
-                    "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
                     "requires": {
                         "minipass": "^2.9.0"
@@ -15107,7 +15112,7 @@
                     "dependencies": {
                         "minipass": {
                             "version": "2.9.0",
-                            "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
                             "requires": {
                                 "safe-buffer": "^5.1.2",
@@ -15118,7 +15123,7 @@
                 },
                 "mississippi": {
                     "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
                     "requires": {
                         "concat-stream": "^1.5.0",
@@ -15135,7 +15140,7 @@
                 },
                 "mkdirp": {
                     "version": "0.5.5",
-                    "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+                    "resolved": false,
                     "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
                     "requires": {
                         "minimist": "^1.2.5"
@@ -15143,14 +15148,14 @@
                     "dependencies": {
                         "minimist": {
                             "version": "1.2.6",
-                            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+                            "resolved": false,
                             "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
                         }
                     }
                 },
                 "move-concurrently": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
                     "requires": {
                         "aproba": "^1.1.1",
@@ -15163,24 +15168,24 @@
                     "dependencies": {
                         "aproba": {
                             "version": "1.2.0",
-                            "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
                         }
                     }
                 },
                 "ms": {
                     "version": "2.1.1",
-                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
                 },
                 "mute-stream": {
                     "version": "0.0.7",
-                    "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+                    "resolved": false,
                     "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s="
                 },
                 "node-fetch-npm": {
                     "version": "2.0.2",
-                    "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==",
                     "requires": {
                         "encoding": "^0.1.11",
@@ -15190,7 +15195,7 @@
                 },
                 "node-gyp": {
                     "version": "5.1.0",
-                    "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-5.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-OUTryc5bt/P8zVgNUmC6xdXiDJxLMAW8cF5tLQOT9E5sOQj+UeQxnnPy74K3CLCa/SOjjBlbuzDLR8ANwA+wmw==",
                     "requires": {
                         "env-paths": "^2.2.0",
@@ -15208,7 +15213,7 @@
                 },
                 "nopt": {
                     "version": "4.0.3",
-                    "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
                     "requires": {
                         "abbrev": "1",
@@ -15217,7 +15222,7 @@
                 },
                 "normalize-package-data": {
                     "version": "2.5.0",
-                    "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
                     "requires": {
                         "hosted-git-info": "^2.1.4",
@@ -15228,7 +15233,7 @@
                     "dependencies": {
                         "resolve": {
                             "version": "1.10.0",
-                            "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==",
                             "requires": {
                                 "path-parse": "^1.0.6"
@@ -15238,7 +15243,7 @@
                 },
                 "npm-audit-report": {
                     "version": "1.3.3",
-                    "resolved": "https://registry.npmjs.org/npm-audit-report/-/npm-audit-report-1.3.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-8nH/JjsFfAWMvn474HB9mpmMjrnKb1Hx/oTAdjv4PT9iZBvBxiZ+wtDUapHCJwLqYGQVPaAfs+vL5+5k9QndXw==",
                     "requires": {
                         "cli-table3": "^0.5.0",
@@ -15247,7 +15252,7 @@
                 },
                 "npm-bundled": {
                     "version": "1.1.1",
-                    "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
                     "requires": {
                         "npm-normalize-package-bin": "^1.0.1"
@@ -15255,12 +15260,12 @@
                 },
                 "npm-cache-filename": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/npm-cache-filename/-/npm-cache-filename-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-3tMGxbC/yHCp6fr4I7xfKD4FrhE="
                 },
                 "npm-install-checks": {
                     "version": "3.0.2",
-                    "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-3.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-E4kzkyZDIWoin6uT5howP8VDvkM+E8IQDcHAycaAxMbwkqhIg5eEYALnXOl3Hq9MrkdQB/2/g1xwBINXdKSRkg==",
                     "requires": {
                         "semver": "^2.3.0 || 3.x || 4 || 5"
@@ -15268,7 +15273,7 @@
                 },
                 "npm-lifecycle": {
                     "version": "3.1.5",
-                    "resolved": "https://registry.npmjs.org/npm-lifecycle/-/npm-lifecycle-3.1.5.tgz",
+                    "resolved": false,
                     "integrity": "sha512-lDLVkjfZmvmfvpvBzA4vzee9cn+Me4orq0QF8glbswJVEbIcSNWib7qGOffolysc3teCqbbPZZkzbr3GQZTL1g==",
                     "requires": {
                         "byline": "^5.0.0",
@@ -15283,17 +15288,17 @@
                 },
                 "npm-logical-tree": {
                     "version": "1.2.1",
-                    "resolved": "https://registry.npmjs.org/npm-logical-tree/-/npm-logical-tree-1.2.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-AJI/qxDB2PWI4LG1CYN579AY1vCiNyWfkiquCsJWqntRu/WwimVrC8yXeILBFHDwxfOejxewlmnvW9XXjMlYIg=="
                 },
                 "npm-normalize-package-bin": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA=="
                 },
                 "npm-package-arg": {
                     "version": "6.1.1",
-                    "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==",
                     "requires": {
                         "hosted-git-info": "^2.7.1",
@@ -15304,7 +15309,7 @@
                 },
                 "npm-packlist": {
                     "version": "1.4.8",
-                    "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
+                    "resolved": false,
                     "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
                     "requires": {
                         "ignore-walk": "^3.0.1",
@@ -15314,7 +15319,7 @@
                 },
                 "npm-pick-manifest": {
                     "version": "3.0.2",
-                    "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==",
                     "requires": {
                         "figgy-pudding": "^3.5.1",
@@ -15324,7 +15329,7 @@
                 },
                 "npm-profile": {
                     "version": "4.0.4",
-                    "resolved": "https://registry.npmjs.org/npm-profile/-/npm-profile-4.0.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-Ta8xq8TLMpqssF0H60BXS1A90iMoM6GeKwsmravJ6wYjWwSzcYBTdyWa3DZCYqPutacBMEm7cxiOkiIeCUAHDQ==",
                     "requires": {
                         "aproba": "^1.1.2 || 2",
@@ -15334,7 +15339,7 @@
                 },
                 "npm-registry-fetch": {
                     "version": "4.0.7",
-                    "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.7.tgz",
+                    "resolved": false,
                     "integrity": "sha512-cny9v0+Mq6Tjz+e0erFAB+RYJ/AVGzkjnISiobqP8OWj9c9FLoZZu8/SPSKJWE17F1tk4018wfjV+ZbIbqC7fQ==",
                     "requires": {
                         "JSONStream": "^1.3.4",
@@ -15348,14 +15353,14 @@
                     "dependencies": {
                         "safe-buffer": {
                             "version": "5.2.1",
-                            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
                         }
                     }
                 },
                 "npm-run-path": {
                     "version": "2.0.2",
-                    "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
                     "requires": {
                         "path-key": "^2.0.0"
@@ -15363,12 +15368,12 @@
                 },
                 "npm-user-validate": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/npm-user-validate/-/npm-user-validate-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-uQwcd/tY+h1jnEaze6cdX/LrhWhoBxfSknxentoqmIuStxUExxjWd3ULMLFPiFUrZKbOVMowH6Jq2FRWfmhcEw=="
                 },
                 "npmlog": {
                     "version": "4.1.2",
-                    "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
                     "requires": {
                         "are-we-there-yet": "~1.1.2",
@@ -15379,27 +15384,27 @@
                 },
                 "number-is-nan": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
                 },
                 "oauth-sign": {
                     "version": "0.9.0",
-                    "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
                 },
                 "object-assign": {
                     "version": "4.1.1",
-                    "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
                 },
                 "object-keys": {
                     "version": "1.0.12",
-                    "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
+                    "resolved": false,
                     "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag=="
                 },
                 "object.getownpropertydescriptors": {
                     "version": "2.0.3",
-                    "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
                     "requires": {
                         "define-properties": "^1.1.2",
@@ -15408,7 +15413,7 @@
                 },
                 "once": {
                     "version": "1.4.0",
-                    "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
                     "requires": {
                         "wrappy": "1"
@@ -15416,22 +15421,22 @@
                 },
                 "opener": {
                     "version": "1.5.2",
-                    "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A=="
                 },
                 "os-homedir": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
                 },
                 "os-tmpdir": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
                 },
                 "osenv": {
                     "version": "0.1.5",
-                    "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+                    "resolved": false,
                     "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
                     "requires": {
                         "os-homedir": "^1.0.0",
@@ -15440,12 +15445,12 @@
                 },
                 "p-finally": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
                 },
                 "package-json": {
                     "version": "4.0.1",
-                    "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=",
                     "requires": {
                         "got": "^6.7.1",
@@ -15456,7 +15461,7 @@
                 },
                 "pacote": {
                     "version": "9.5.12",
-                    "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.12.tgz",
+                    "resolved": false,
                     "integrity": "sha512-BUIj/4kKbwWg4RtnBncXPJd15piFSVNpTzY0rysSr3VnMowTYgkGKcaHrbReepAkjTr8lH2CVWRi58Spg2CicQ==",
                     "requires": {
                         "bluebird": "^3.5.3",
@@ -15493,7 +15498,7 @@
                     "dependencies": {
                         "minipass": {
                             "version": "2.9.0",
-                            "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
                             "requires": {
                                 "safe-buffer": "^5.1.2",
@@ -15504,7 +15509,7 @@
                 },
                 "parallel-transform": {
                     "version": "1.1.0",
-                    "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=",
                     "requires": {
                         "cyclist": "~0.2.2",
@@ -15514,7 +15519,7 @@
                     "dependencies": {
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+                            "resolved": false,
                             "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
                             "requires": {
                                 "core-util-is": "~1.0.0",
@@ -15528,7 +15533,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
                             "requires": {
                                 "safe-buffer": "~5.1.0"
@@ -15538,57 +15543,57 @@
                 },
                 "path-exists": {
                     "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
                 },
                 "path-is-absolute": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
                 },
                 "path-is-inside": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM="
                 },
                 "path-key": {
                     "version": "2.0.1",
-                    "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
                 },
                 "path-parse": {
                     "version": "1.0.7",
-                    "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+                    "resolved": false,
                     "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
                 },
                 "performance-now": {
                     "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
                 },
                 "pify": {
                     "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
                 },
                 "prepend-http": {
                     "version": "1.0.4",
-                    "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
+                    "resolved": false,
                     "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
                 },
                 "process-nextick-args": {
                     "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
                 },
                 "promise-inflight": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM="
                 },
                 "promise-retry": {
                     "version": "1.1.1",
-                    "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=",
                     "requires": {
                         "err-code": "^1.0.0",
@@ -15597,14 +15602,14 @@
                     "dependencies": {
                         "retry": {
                             "version": "0.10.1",
-                            "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz",
+                            "resolved": false,
                             "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q="
                         }
                     }
                 },
                 "promzard": {
                     "version": "0.3.0",
-                    "resolved": "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=",
                     "requires": {
                         "read": "1"
@@ -15612,12 +15617,12 @@
                 },
                 "proto-list": {
                     "version": "1.2.4",
-                    "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
+                    "resolved": false,
                     "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk="
                 },
                 "protoduck": {
                     "version": "5.0.1",
-                    "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==",
                     "requires": {
                         "genfun": "^5.0.0"
@@ -15625,22 +15630,22 @@
                 },
                 "prr": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY="
                 },
                 "pseudomap": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
                 },
                 "psl": {
                     "version": "1.1.29",
-                    "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz",
+                    "resolved": false,
                     "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ=="
                 },
                 "pump": {
                     "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
                     "requires": {
                         "end-of-stream": "^1.1.0",
@@ -15649,7 +15654,7 @@
                 },
                 "pumpify": {
                     "version": "1.5.1",
-                    "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
                     "requires": {
                         "duplexify": "^3.6.0",
@@ -15659,7 +15664,7 @@
                     "dependencies": {
                         "pump": {
                             "version": "2.0.1",
-                            "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
                             "requires": {
                                 "end-of-stream": "^1.1.0",
@@ -15670,22 +15675,22 @@
                 },
                 "punycode": {
                     "version": "1.4.1",
-                    "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
                 },
                 "qrcode-terminal": {
                     "version": "0.12.0",
-                    "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ=="
                 },
                 "qs": {
                     "version": "6.5.2",
-                    "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
                 },
                 "query-string": {
                     "version": "6.8.2",
-                    "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.8.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-J3Qi8XZJXh93t2FiKyd/7Ec6GNifsjKXUsVFkSBj/kjLsDylWhnCz4NT1bkPcKotttPW+QbKGqqPH8OoI2pdqw==",
                     "requires": {
                         "decode-uri-component": "^0.2.0",
@@ -15695,12 +15700,12 @@
                 },
                 "qw": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/qw/-/qw-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-77/cdA+a0FQwRCassYNBLMi5ltQ="
                 },
                 "rc": {
                     "version": "1.2.8",
-                    "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+                    "resolved": false,
                     "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
                     "requires": {
                         "deep-extend": "^0.6.0",
@@ -15711,7 +15716,7 @@
                 },
                 "read": {
                     "version": "1.0.7",
-                    "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
+                    "resolved": false,
                     "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=",
                     "requires": {
                         "mute-stream": "~0.0.4"
@@ -15719,7 +15724,7 @@
                 },
                 "read-cmd-shim": {
                     "version": "1.0.5",
-                    "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz",
+                    "resolved": false,
                     "integrity": "sha512-v5yCqQ/7okKoZZkBQUAfTsQ3sVJtXdNfbPnI5cceppoxEVLYA3k+VtV2omkeo8MS94JCy4fSiUwlRBAwCVRPUA==",
                     "requires": {
                         "graceful-fs": "^4.1.2"
@@ -15727,7 +15732,7 @@
                 },
                 "read-installed": {
                     "version": "4.0.3",
-                    "resolved": "https://registry.npmjs.org/read-installed/-/read-installed-4.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha1-/5uLZ/GH0eTCm5/rMfayI6zRkGc=",
                     "requires": {
                         "debuglog": "^1.0.1",
@@ -15741,7 +15746,7 @@
                 },
                 "read-package-json": {
                     "version": "2.1.1",
-                    "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-dAiqGtVc/q5doFz6096CcnXhpYk0ZN8dEKVkGLU0CsASt8SrgF6SF7OTKAYubfvFhWaqofl+Y8HK19GR8jwW+A==",
                     "requires": {
                         "glob": "^7.1.1",
@@ -15753,7 +15758,7 @@
                 },
                 "read-package-tree": {
                     "version": "5.3.1",
-                    "resolved": "https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.3.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==",
                     "requires": {
                         "read-package-json": "^2.0.0",
@@ -15763,7 +15768,7 @@
                 },
                 "readable-stream": {
                     "version": "3.6.0",
-                    "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
                     "requires": {
                         "inherits": "^2.0.3",
@@ -15773,7 +15778,7 @@
                 },
                 "readdir-scoped-modules": {
                     "version": "1.1.0",
-                    "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==",
                     "requires": {
                         "debuglog": "^1.0.1",
@@ -15784,7 +15789,7 @@
                 },
                 "registry-auth-token": {
                     "version": "3.4.0",
-                    "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==",
                     "requires": {
                         "rc": "^1.1.6",
@@ -15793,7 +15798,7 @@
                 },
                 "registry-url": {
                     "version": "3.1.0",
-                    "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=",
                     "requires": {
                         "rc": "^1.0.1"
@@ -15801,7 +15806,7 @@
                 },
                 "request": {
                     "version": "2.88.0",
-                    "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
                     "requires": {
                         "aws-sign2": "~0.7.0",
@@ -15828,27 +15833,27 @@
                 },
                 "require-directory": {
                     "version": "2.1.1",
-                    "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
                 },
                 "require-main-filename": {
                     "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
                 },
                 "resolve-from": {
                     "version": "4.0.0",
-                    "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="
                 },
                 "retry": {
                     "version": "0.12.0",
-                    "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs="
                 },
                 "rimraf": {
                     "version": "2.7.1",
-                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
                     "requires": {
                         "glob": "^7.1.3"
@@ -15856,7 +15861,7 @@
                 },
                 "run-queue": {
                     "version": "1.0.3",
-                    "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
                     "requires": {
                         "aproba": "^1.1.1"
@@ -15864,29 +15869,29 @@
                     "dependencies": {
                         "aproba": {
                             "version": "1.2.0",
-                            "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
                         }
                     }
                 },
                 "safe-buffer": {
                     "version": "5.1.2",
-                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                 },
                 "safer-buffer": {
                     "version": "2.1.2",
-                    "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
                 },
                 "semver": {
                     "version": "5.7.1",
-                    "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
                 },
                 "semver-diff": {
                     "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=",
                     "requires": {
                         "semver": "^5.0.3"
@@ -15894,12 +15899,12 @@
                 },
                 "set-blocking": {
                     "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
                 },
                 "sha": {
                     "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/sha/-/sha-3.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-DOYnM37cNsLNSGIG/zZWch5CKIRNoLdYUQTQlcgkRkoYIUwDYjqDyye16YcDZg/OPdcbUgTKMjc4SY6TB7ZAPw==",
                     "requires": {
                         "graceful-fs": "^4.1.2"
@@ -15907,7 +15912,7 @@
                 },
                 "shebang-command": {
                     "version": "1.2.0",
-                    "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
                     "requires": {
                         "shebang-regex": "^1.0.0"
@@ -15915,27 +15920,27 @@
                 },
                 "shebang-regex": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
                 },
                 "signal-exit": {
                     "version": "3.0.2",
-                    "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
                 },
                 "slide": {
                     "version": "1.1.6",
-                    "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
+                    "resolved": false,
                     "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc="
                 },
                 "smart-buffer": {
                     "version": "4.1.0",
-                    "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw=="
                 },
                 "socks": {
                     "version": "2.3.3",
-                    "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==",
                     "requires": {
                         "ip": "1.1.5",
@@ -15944,7 +15949,7 @@
                 },
                 "socks-proxy-agent": {
                     "version": "4.0.2",
-                    "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==",
                     "requires": {
                         "agent-base": "~4.2.1",
@@ -15953,7 +15958,7 @@
                     "dependencies": {
                         "agent-base": {
                             "version": "4.2.1",
-                            "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
                             "requires": {
                                 "es6-promisify": "^5.0.0"
@@ -15963,12 +15968,12 @@
                 },
                 "sorted-object": {
                     "version": "2.0.1",
-                    "resolved": "https://registry.npmjs.org/sorted-object/-/sorted-object-2.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-fWMfS9OnmKJK8d/8+/6DM3pd9fw="
                 },
                 "sorted-union-stream": {
                     "version": "2.1.3",
-                    "resolved": "https://registry.npmjs.org/sorted-union-stream/-/sorted-union-stream-2.1.3.tgz",
+                    "resolved": false,
                     "integrity": "sha1-x3lMfgd4gAUv9xqNSi27Sppjisc=",
                     "requires": {
                         "from2": "^1.3.0",
@@ -15977,7 +15982,7 @@
                     "dependencies": {
                         "from2": {
                             "version": "1.3.0",
-                            "resolved": "https://registry.npmjs.org/from2/-/from2-1.3.0.tgz",
+                            "resolved": false,
                             "integrity": "sha1-iEE7qqX5pZfP3pIh2GmGzTwGHf0=",
                             "requires": {
                                 "inherits": "~2.0.1",
@@ -15986,12 +15991,12 @@
                         },
                         "isarray": {
                             "version": "0.0.1",
-                            "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+                            "resolved": false,
                             "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
                         },
                         "readable-stream": {
                             "version": "1.1.14",
-                            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+                            "resolved": false,
                             "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
                             "requires": {
                                 "core-util-is": "~1.0.0",
@@ -16002,14 +16007,14 @@
                         },
                         "string_decoder": {
                             "version": "0.10.31",
-                            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+                            "resolved": false,
                             "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
                         }
                     }
                 },
                 "spdx-correct": {
                     "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==",
                     "requires": {
                         "spdx-expression-parse": "^3.0.0",
@@ -16018,12 +16023,12 @@
                 },
                 "spdx-exceptions": {
                     "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg=="
                 },
                 "spdx-expression-parse": {
                     "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
                     "requires": {
                         "spdx-exceptions": "^2.1.0",
@@ -16032,17 +16037,17 @@
                 },
                 "spdx-license-ids": {
                     "version": "3.0.5",
-                    "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
+                    "resolved": false,
                     "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q=="
                 },
                 "split-on-first": {
                     "version": "1.1.0",
-                    "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw=="
                 },
                 "sshpk": {
                     "version": "1.14.2",
-                    "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
                     "requires": {
                         "asn1": "~0.2.3",
@@ -16058,7 +16063,7 @@
                 },
                 "ssri": {
                     "version": "6.0.2",
-                    "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==",
                     "requires": {
                         "figgy-pudding": "^3.5.1"
@@ -16066,7 +16071,7 @@
                 },
                 "stream-each": {
                     "version": "1.2.2",
-                    "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==",
                     "requires": {
                         "end-of-stream": "^1.1.0",
@@ -16075,7 +16080,7 @@
                 },
                 "stream-iterate": {
                     "version": "1.2.0",
-                    "resolved": "https://registry.npmjs.org/stream-iterate/-/stream-iterate-1.2.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-K9fHcpbBcCpGSIuK1B95hl7s1OE=",
                     "requires": {
                         "readable-stream": "^2.1.5",
@@ -16084,7 +16089,7 @@
                     "dependencies": {
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+                            "resolved": false,
                             "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
                             "requires": {
                                 "core-util-is": "~1.0.0",
@@ -16098,7 +16103,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
                             "requires": {
                                 "safe-buffer": "~5.1.0"
@@ -16108,7 +16113,7 @@
                 },
                 "stream-shift": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI="
                 },
                 "strict-uri-encode": {
@@ -16118,7 +16123,7 @@
                 },
                 "string-width": {
                     "version": "2.1.1",
-                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
                     "requires": {
                         "is-fullwidth-code-point": "^2.0.0",
@@ -16127,17 +16132,17 @@
                     "dependencies": {
                         "ansi-regex": {
                             "version": "3.0.0",
-                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+                            "resolved": false,
                             "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
                         },
                         "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",
+                            "resolved": false,
                             "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
                         },
                         "strip-ansi": {
                             "version": "4.0.0",
-                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+                            "resolved": false,
                             "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
                             "requires": {
                                 "ansi-regex": "^3.0.0"
@@ -16160,12 +16165,12 @@
                 },
                 "stringify-package": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg=="
                 },
                 "strip-ansi": {
                     "version": "3.0.1",
-                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
                     "requires": {
                         "ansi-regex": "^2.0.0"
@@ -16173,17 +16178,17 @@
                 },
                 "strip-eof": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
                 },
                 "strip-json-comments": {
                     "version": "2.0.1",
-                    "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
                 },
                 "supports-color": {
                     "version": "5.4.0",
-                    "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
                     "requires": {
                         "has-flag": "^3.0.0"
@@ -16191,7 +16196,7 @@
                 },
                 "tar": {
                     "version": "4.4.19",
-                    "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz",
+                    "resolved": false,
                     "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==",
                     "requires": {
                         "chownr": "^1.1.4",
@@ -16205,7 +16210,7 @@
                     "dependencies": {
                         "minipass": {
                             "version": "2.9.0",
-                            "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
                             "requires": {
                                 "safe-buffer": "^5.1.2",
@@ -16214,19 +16219,19 @@
                         },
                         "safe-buffer": {
                             "version": "5.2.1",
-                            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
                         },
                         "yallist": {
                             "version": "3.1.1",
-                            "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
                         }
                     }
                 },
                 "term-size": {
                     "version": "1.2.0",
-                    "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=",
                     "requires": {
                         "execa": "^0.7.0"
@@ -16234,17 +16239,17 @@
                 },
                 "text-table": {
                     "version": "0.2.0",
-                    "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ="
                 },
                 "through": {
                     "version": "2.3.8",
-                    "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+                    "resolved": false,
                     "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
                 },
                 "through2": {
                     "version": "2.0.3",
-                    "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
                     "requires": {
                         "readable-stream": "^2.1.5",
@@ -16253,7 +16258,7 @@
                     "dependencies": {
                         "readable-stream": {
                             "version": "2.3.6",
-                            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+                            "resolved": false,
                             "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
                             "requires": {
                                 "core-util-is": "~1.0.0",
@@ -16267,7 +16272,7 @@
                         },
                         "string_decoder": {
                             "version": "1.1.1",
-                            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
                             "requires": {
                                 "safe-buffer": "~5.1.0"
@@ -16277,17 +16282,17 @@
                 },
                 "timed-out": {
                     "version": "4.0.1",
-                    "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8="
                 },
                 "tiny-relative-date": {
                     "version": "1.3.0",
-                    "resolved": "https://registry.npmjs.org/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A=="
                 },
                 "tough-cookie": {
                     "version": "2.4.3",
-                    "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
                     "requires": {
                         "psl": "^1.1.24",
@@ -16296,7 +16301,7 @@
                 },
                 "tunnel-agent": {
                     "version": "0.6.0",
-                    "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
                     "requires": {
                         "safe-buffer": "^5.0.1"
@@ -16304,28 +16309,28 @@
                 },
                 "tweetnacl": {
                     "version": "0.14.5",
-                    "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+                    "resolved": false,
                     "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
                     "optional": true
                 },
                 "typedarray": {
                     "version": "0.0.6",
-                    "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+                    "resolved": false,
                     "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
                 },
                 "uid-number": {
                     "version": "0.0.6",
-                    "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz",
+                    "resolved": false,
                     "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE="
                 },
                 "umask": {
                     "version": "1.1.0",
-                    "resolved": "https://registry.npmjs.org/umask/-/umask-1.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0="
                 },
                 "unique-filename": {
                     "version": "1.1.1",
-                    "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
                     "requires": {
                         "unique-slug": "^2.0.0"
@@ -16333,7 +16338,7 @@
                 },
                 "unique-slug": {
                     "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=",
                     "requires": {
                         "imurmurhash": "^0.1.4"
@@ -16341,7 +16346,7 @@
                 },
                 "unique-string": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=",
                     "requires": {
                         "crypto-random-string": "^1.0.0"
@@ -16349,17 +16354,17 @@
                 },
                 "unpipe": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
                 },
                 "unzip-response": {
                     "version": "2.0.1",
-                    "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c="
                 },
                 "update-notifier": {
                     "version": "2.5.0",
-                    "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==",
                     "requires": {
                         "boxen": "^1.2.1",
@@ -16376,7 +16381,7 @@
                 },
                 "uri-js": {
                     "version": "4.4.0",
-                    "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==",
                     "requires": {
                         "punycode": "^2.1.0"
@@ -16384,14 +16389,14 @@
                     "dependencies": {
                         "punycode": {
                             "version": "2.1.1",
-                            "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
                         }
                     }
                 },
                 "url-parse-lax": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=",
                     "requires": {
                         "prepend-http": "^1.0.1"
@@ -16399,17 +16404,17 @@
                 },
                 "util-deprecate": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
                 },
                 "util-extend": {
                     "version": "1.0.3",
-                    "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8="
                 },
                 "util-promisify": {
                     "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/util-promisify/-/util-promisify-2.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=",
                     "requires": {
                         "object.getownpropertydescriptors": "^2.0.3"
@@ -16417,12 +16422,12 @@
                 },
                 "uuid": {
                     "version": "3.3.3",
-                    "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
                 },
                 "validate-npm-package-license": {
                     "version": "3.0.4",
-                    "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
                     "requires": {
                         "spdx-correct": "^3.0.0",
@@ -16431,7 +16436,7 @@
                 },
                 "validate-npm-package-name": {
                     "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=",
                     "requires": {
                         "builtins": "^1.0.3"
@@ -16439,7 +16444,7 @@
                 },
                 "verror": {
                     "version": "1.10.0",
-                    "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
                     "requires": {
                         "assert-plus": "^1.0.0",
@@ -16449,7 +16454,7 @@
                 },
                 "wcwidth": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
                     "requires": {
                         "defaults": "^1.0.3"
@@ -16457,7 +16462,7 @@
                 },
                 "which": {
                     "version": "1.3.1",
-                    "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
                     "requires": {
                         "isexe": "^2.0.0"
@@ -16465,12 +16470,12 @@
                 },
                 "which-module": {
                     "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
                 },
                 "wide-align": {
                     "version": "1.1.2",
-                    "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
                     "requires": {
                         "string-width": "^1.0.2"
@@ -16478,7 +16483,7 @@
                     "dependencies": {
                         "string-width": {
                             "version": "1.0.2",
-                            "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+                            "resolved": false,
                             "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
                             "requires": {
                                 "code-point-at": "^1.0.0",
@@ -16490,7 +16495,7 @@
                 },
                 "widest-line": {
                     "version": "2.0.1",
-                    "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==",
                     "requires": {
                         "string-width": "^2.1.1"
@@ -16498,7 +16503,7 @@
                 },
                 "worker-farm": {
                     "version": "1.7.0",
-                    "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
                     "requires": {
                         "errno": "~0.1.7"
@@ -16506,7 +16511,7 @@
                 },
                 "wrap-ansi": {
                     "version": "5.1.0",
-                    "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
                     "requires": {
                         "ansi-styles": "^3.2.0",
@@ -16516,17 +16521,17 @@
                     "dependencies": {
                         "ansi-regex": {
                             "version": "4.1.1",
-                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="
                         },
                         "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",
+                            "resolved": false,
                             "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
                         },
                         "string-width": {
                             "version": "3.1.0",
-                            "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
                             "requires": {
                                 "emoji-regex": "^7.0.1",
@@ -16536,7 +16541,7 @@
                         },
                         "strip-ansi": {
                             "version": "5.2.0",
-                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
                             "requires": {
                                 "ansi-regex": "^4.1.0"
@@ -16546,12 +16551,12 @@
                 },
                 "wrappy": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
                 },
                 "write-file-atomic": {
                     "version": "2.4.3",
-                    "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
                     "requires": {
                         "graceful-fs": "^4.1.11",
@@ -16561,27 +16566,27 @@
                 },
                 "xdg-basedir": {
                     "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ="
                 },
                 "xtend": {
                     "version": "4.0.1",
-                    "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
                 },
                 "y18n": {
                     "version": "4.0.1",
-                    "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ=="
                 },
                 "yallist": {
                     "version": "3.0.3",
-                    "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A=="
                 },
                 "yargs": {
                     "version": "14.2.3",
-                    "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==",
                     "requires": {
                         "cliui": "^5.0.0",
@@ -16599,12 +16604,12 @@
                     "dependencies": {
                         "ansi-regex": {
                             "version": "4.1.0",
-                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
                         },
                         "find-up": {
                             "version": "3.0.0",
-                            "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
                             "requires": {
                                 "locate-path": "^3.0.0"
@@ -16612,12 +16617,12 @@
                         },
                         "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",
+                            "resolved": false,
                             "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
                         },
                         "locate-path": {
                             "version": "3.0.0",
-                            "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
                             "requires": {
                                 "p-locate": "^3.0.0",
@@ -16626,7 +16631,7 @@
                         },
                         "p-limit": {
                             "version": "2.3.0",
-                            "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
                             "requires": {
                                 "p-try": "^2.0.0"
@@ -16634,7 +16639,7 @@
                         },
                         "p-locate": {
                             "version": "3.0.0",
-                            "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
                             "requires": {
                                 "p-limit": "^2.0.0"
@@ -16642,12 +16647,12 @@
                         },
                         "p-try": {
                             "version": "2.2.0",
-                            "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
                         },
                         "string-width": {
                             "version": "3.1.0",
-                            "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
                             "requires": {
                                 "emoji-regex": "^7.0.1",
@@ -16657,7 +16662,7 @@
                         },
                         "strip-ansi": {
                             "version": "5.2.0",
-                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
                             "requires": {
                                 "ansi-regex": "^4.1.0"
@@ -16667,7 +16672,7 @@
                 },
                 "yargs-parser": {
                     "version": "15.0.1",
-                    "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==",
                     "requires": {
                         "camelcase": "^5.0.0",
@@ -16676,7 +16681,7 @@
                     "dependencies": {
                         "camelcase": {
                             "version": "5.3.1",
-                            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
                         }
                     }
@@ -16686,7 +16691,7 @@
         "npm-run-path": {
             "version": "2.0.2",
             "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
-            "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==",
+            "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
             "requires": {
                 "path-key": "^2.0.0"
             }
@@ -16713,7 +16718,7 @@
         "number-is-nan": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
-            "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ=="
+            "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
         },
         "nwsapi": {
             "version": "2.2.0",
@@ -16724,7 +16729,7 @@
         "oauth": {
             "version": "0.9.15",
             "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz",
-            "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA=="
+            "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE="
         },
         "oauth-sign": {
             "version": "0.9.0",
@@ -16734,12 +16739,12 @@
         "object-assign": {
             "version": "4.1.1",
             "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-            "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
+            "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
         },
         "object-copy": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
-            "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==",
+            "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
             "requires": {
                 "copy-descriptor": "^0.1.0",
                 "define-property": "^0.2.5",
@@ -16749,7 +16754,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
+                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -16762,7 +16767,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -16819,7 +16824,7 @@
                 "magicli": {
                     "version": "0.0.5",
                     "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
-                    "integrity": "sha512-wZbMtnl2v1b+Jp3xlqA9FU/O4I6YhGXR8xSY/eU2+gDAvut/F+W3gl4qs61iL4LELC7jqSAE6aAD5668EbmQHA==",
+                    "integrity": "sha1-zufQ+7THBRiqyxHsPrfiX/SaSSE=",
                     "requires": {
                         "commander": "^2.9.0",
                         "get-stdin": "^5.0.1",
@@ -16832,7 +16837,7 @@
         "object-visit": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
-            "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==",
+            "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
             "requires": {
                 "isobject": "^3.0.0"
             }
@@ -16894,7 +16899,7 @@
         "object.pick": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
-            "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==",
+            "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
             "requires": {
                 "isobject": "^3.0.1"
             }
@@ -16932,7 +16937,7 @@
         "once": {
             "version": "1.4.0",
             "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-            "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+            "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
             "requires": {
                 "wrappy": "1"
             }
@@ -16994,12 +16999,12 @@
         "os-homedir": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
-            "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ=="
+            "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
         },
         "os-tmpdir": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
-            "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="
+            "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
         },
         "osenv": {
             "version": "0.1.5",
@@ -17018,12 +17023,12 @@
         "p-debounce": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/p-debounce/-/p-debounce-1.0.0.tgz",
-            "integrity": "sha512-ttOxn4Yt0hzIsLLqKi/Ry9QRxW+UQKdoWHz7g99Ci57zPkqUU3kbWKAeHuv+HfRLe109acYLUY6kuVCOOqnt4g=="
+            "integrity": "sha1-y38svu/YegnrqGHhErZ1J+Yh4v0="
         },
         "p-finally": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
-            "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow=="
+            "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
         },
         "p-limit": {
             "version": "2.3.0",
@@ -17064,7 +17069,7 @@
         "package-json": {
             "version": "4.0.1",
             "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz",
-            "integrity": "sha512-q/R5GrMek0vzgoomq6rm9OX+3PQve8sLwTirmK30YB3Cu0Bbt9OX9M/SIUnroN5BGJkzwGsFwDaRGD9EwBOlCA==",
+            "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=",
             "requires": {
                 "got": "^6.7.1",
                 "registry-auth-token": "^3.0.1",
@@ -17080,7 +17085,7 @@
                 "got": {
                     "version": "6.7.1",
                     "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
-                    "integrity": "sha512-Y/K3EDuiQN9rTZhBvPRWMLXIKdeD1Rj0nzunfoi0Yyn5WBEbzxXKU9Ub2X41oZBagVWOBU3MuDonFMgPWQFnwg==",
+                    "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
                     "requires": {
                         "create-error-class": "^3.0.0",
                         "duplexer3": "^0.1.4",
@@ -17196,7 +17201,7 @@
         "pascalcase": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
-            "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw=="
+            "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="
         },
         "passport": {
             "version": "0.4.1",
@@ -17218,7 +17223,7 @@
         "passport-local": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
-            "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==",
+            "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=",
             "requires": {
                 "passport-strategy": "1.x.x"
             }
@@ -17238,7 +17243,7 @@
         "passport-strategy": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
-            "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA=="
+            "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ="
         },
         "path-browserify": {
             "version": "1.0.1",
@@ -17248,27 +17253,27 @@
         "path-dirname": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
-            "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q=="
+            "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA="
         },
         "path-exists": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
-            "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="
+            "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
         },
         "path-is-absolute": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-            "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
+            "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
         },
         "path-is-inside": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
-            "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w=="
+            "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM="
         },
         "path-key": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
-            "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="
+            "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
         },
         "path-parse": {
             "version": "1.0.7",
@@ -17278,7 +17283,7 @@
         "path-to-regexp": {
             "version": "0.1.7",
             "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
-            "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
+            "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
         },
         "path-type": {
             "version": "4.0.0",
@@ -17293,7 +17298,7 @@
         "pause": {
             "version": "0.0.1",
             "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
-            "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg=="
+            "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10="
         },
         "pdf-parse": {
             "version": "1.1.1",
@@ -17341,7 +17346,7 @@
         "pend": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
-            "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="
+            "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
         },
         "perfect-scrollbar": {
             "version": "1.5.5",
@@ -17351,7 +17356,7 @@
         "performance-now": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
-            "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
+            "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
         },
         "picocolors": {
             "version": "1.0.0",
@@ -17371,12 +17376,12 @@
         "pinkie": {
             "version": "2.0.4",
             "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
-            "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg=="
+            "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
         },
         "pinkie-promise": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
-            "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==",
+            "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
             "requires": {
                 "pinkie": "^2.0.0"
             }
@@ -17437,7 +17442,7 @@
         "plist": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/plist/-/plist-1.2.0.tgz",
-            "integrity": "sha512-dL9Xc2Aj3YyBnwvCNuHmFl2LWvQacm/HEAsoVwLiuu0POboMChETt5wexpU1P6F6MnibIucXlVsMFFgNUT2IyA==",
+            "integrity": "sha1-CEtQk93JJQbiWfh0uNmxr7jHlZM=",
             "requires": {
                 "base64-js": "0.0.8",
                 "util-deprecate": "1.0.2",
@@ -17448,7 +17453,7 @@
                 "base64-js": {
                     "version": "0.0.8",
                     "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
-                    "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw=="
+                    "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg="
                 }
             }
         },
@@ -17488,7 +17493,7 @@
         "posix-character-classes": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
-            "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg=="
+            "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
         },
         "postcss": {
             "version": "7.0.39",
@@ -17686,13 +17691,13 @@
         "prelude-ls": {
             "version": "1.1.2",
             "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
-            "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
+            "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
             "dev": true
         },
         "prepend-http": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
-            "integrity": "sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg=="
+            "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
         },
         "prettier": {
             "version": "2.7.1",
@@ -17741,7 +17746,7 @@
         "process": {
             "version": "0.11.10",
             "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
-            "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="
+            "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
         },
         "process-nextick-args": {
             "version": "2.0.1",
@@ -17764,7 +17769,7 @@
         "promise-inflight": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
-            "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
+            "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
             "dev": true
         },
         "prop-types": {
@@ -17815,7 +17820,7 @@
         "prosemirror-find-replace": {
             "version": "0.9.0",
             "resolved": "https://registry.npmjs.org/prosemirror-find-replace/-/prosemirror-find-replace-0.9.0.tgz",
-            "integrity": "sha512-LfhQ/Zr0PkkJpCsr9vTJ5ZPYh49mSVVG+hHJ6djT+chlCW+t2ilSxBpBG+2IeE/I5nlbcvuLLAbxeI1g3pTCpA=="
+            "integrity": "sha1-QgsENNF5xdBJD44hSNhVGpVJY4I="
         },
         "prosemirror-history": {
             "version": "1.3.0",
@@ -17907,13 +17912,13 @@
         "prr": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
-            "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==",
+            "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
             "dev": true
         },
         "pseudomap": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
-            "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ=="
+            "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
         },
         "psl": {
             "version": "1.8.0",
@@ -18145,12 +18150,12 @@
         "pure-color": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz",
-            "integrity": "sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA=="
+            "integrity": "sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4="
         },
         "q": {
             "version": "1.5.1",
             "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
-            "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw=="
+            "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc="
         },
         "qs": {
             "version": "6.5.3",
@@ -18171,7 +18176,7 @@
         "querystring": {
             "version": "0.2.0",
             "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
-            "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==",
+            "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
             "dev": true
         },
         "querystringify": {
@@ -18193,7 +18198,7 @@
         "random-bytes": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
-            "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ=="
+            "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
         },
         "randombytes": {
             "version": "2.1.0",
@@ -18296,7 +18301,7 @@
         "react-base16-styling": {
             "version": "0.5.3",
             "resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.5.3.tgz",
-            "integrity": "sha512-EPuchwVvYPSFFIjGpH0k6wM0HQsmJ0vCk7BSl5ryxMVFIWW4hX4Kksu4PNtxfgOxDebTLkJQ8iC7zwAql0eusg==",
+            "integrity": "sha1-OFjyTpxN2MvT9wLz901YHKKRcmk=",
             "requires": {
                 "base16": "^1.0.0",
                 "lodash.curry": "^4.0.1",
@@ -18365,7 +18370,7 @@
         "react-dock": {
             "version": "0.2.4",
             "resolved": "https://registry.npmjs.org/react-dock/-/react-dock-0.2.4.tgz",
-            "integrity": "sha512-ywUJPC/TIM9PO700skka0fH4aqbrH8RojUXejZFvjtqlc5KZ+xjHqFdo4A3j+dp+0NLFZ3Nai4xzcf3FUJ9BsQ==",
+            "integrity": "sha1-5yfcdVCztzEWY13LnA4E0Lev4Xw=",
             "requires": {
                 "lodash.debounce": "^3.1.1",
                 "prop-types": "^15.5.8"
@@ -18738,7 +18743,7 @@
         "react-themeable": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/react-themeable/-/react-themeable-1.1.0.tgz",
-            "integrity": "sha512-kl5tQ8K+r9IdQXZd8WLa+xxYN04lLnJXRVhHfdgwsUJr/SlKJxIejoc9z9obEkx1mdqbTw1ry43fxEUwyD9u7w==",
+            "integrity": "sha1-fURm3ZsrX6dQWHJ4JenxUro3mg4=",
             "requires": {
                 "object-assign": "^3.0.0"
             },
@@ -18746,7 +18751,7 @@
                 "object-assign": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
-                    "integrity": "sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ=="
+                    "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I="
                 }
             }
         },
@@ -18801,7 +18806,7 @@
         "read-pkg": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
-            "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==",
+            "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
             "requires": {
                 "load-json-file": "^1.0.0",
                 "normalize-package-data": "^2.3.2",
@@ -18811,7 +18816,7 @@
                 "path-type": {
                     "version": "1.1.0",
                     "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
-                    "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==",
+                    "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
                     "requires": {
                         "graceful-fs": "^4.1.2",
                         "pify": "^2.0.0",
@@ -18823,7 +18828,7 @@
         "read-pkg-up": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
-            "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==",
+            "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
             "requires": {
                 "find-up": "^1.0.0",
                 "read-pkg": "^1.0.0"
@@ -18832,7 +18837,7 @@
                 "find-up": {
                     "version": "1.1.2",
                     "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
-                    "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==",
+                    "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
                     "requires": {
                         "path-exists": "^2.0.0",
                         "pinkie-promise": "^2.0.0"
@@ -18841,7 +18846,7 @@
                 "path-exists": {
                     "version": "2.1.0",
                     "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
-                    "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==",
+                    "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
                     "requires": {
                         "pinkie-promise": "^2.0.0"
                     }
@@ -18887,12 +18892,12 @@
         "readline": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz",
-            "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg=="
+            "integrity": "sha1-xYDXfvLPyHUrEySYBg3JeTp6wBw="
         },
         "rechoir": {
             "version": "0.6.2",
             "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
-            "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
+            "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
             "requires": {
                 "resolve": "^1.1.6"
             }
@@ -18918,7 +18923,7 @@
         "redent": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
-            "integrity": "sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g==",
+            "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
             "requires": {
                 "indent-string": "^2.1.0",
                 "strip-indent": "^1.0.1"
@@ -18927,7 +18932,7 @@
         "reduce-flatten": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz",
-            "integrity": "sha512-j5WfFJfc9CoXv/WbwVLHq74i/hdTUpy+iNC534LxczMRP67vJeK3V9JOdnL0N1cIRbn9mYhE2yVjvvKXDxvNXQ=="
+            "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc="
         },
         "redux": {
             "version": "4.2.0",
@@ -18984,7 +18989,7 @@
         "registry-url": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz",
-            "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==",
+            "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=",
             "requires": {
                 "rc": "^1.0.1"
             }
@@ -19002,7 +19007,7 @@
         "relateurl": {
             "version": "0.2.7",
             "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
-            "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog=="
+            "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk="
         },
         "remark-gfm": {
             "version": "3.0.1",
@@ -19039,7 +19044,7 @@
         "remove-trailing-separator": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
-            "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw=="
+            "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
         },
         "renderkid": {
             "version": "3.0.0",
@@ -19125,12 +19130,12 @@
         "repeat-string": {
             "version": "1.6.1",
             "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
-            "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w=="
+            "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
         },
         "repeating": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
-            "integrity": "sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==",
+            "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
             "requires": {
                 "is-finite": "^1.0.0"
             }
@@ -19234,7 +19239,7 @@
         "require-directory": {
             "version": "2.1.1",
             "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
-            "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
+            "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
         },
         "require-from-string": {
             "version": "2.0.2",
@@ -19249,7 +19254,7 @@
         "require-package-name": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz",
-            "integrity": "sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q=="
+            "integrity": "sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk="
         },
         "require_optional": {
             "version": "1.0.1",
@@ -19263,14 +19268,14 @@
                 "resolve-from": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
-                    "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ=="
+                    "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c="
                 }
             }
         },
         "requires-port": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
-            "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+            "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
             "dev": true
         },
         "resize-observer-polyfill": {
@@ -19316,7 +19321,7 @@
         "resolve-url": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
-            "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg=="
+            "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
         },
         "responselike": {
             "version": "2.0.0",
@@ -19351,7 +19356,7 @@
         "retry": {
             "version": "0.12.0",
             "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
-            "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
+            "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
             "dev": true
         },
         "reveal.js": {
@@ -19362,7 +19367,7 @@
         "right-align": {
             "version": "0.1.3",
             "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
-            "integrity": "sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==",
+            "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
             "requires": {
                 "align-text": "^0.1.1"
             }
@@ -19397,7 +19402,7 @@
         "run-queue": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
-            "integrity": "sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg==",
+            "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
             "dev": true,
             "requires": {
                 "aproba": "^1.1.1"
@@ -19444,7 +19449,7 @@
         "safe-regex": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
-            "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==",
+            "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
             "requires": {
                 "ret": "~0.1.10"
             }
@@ -19532,13 +19537,13 @@
         "scss-loader": {
             "version": "0.0.1",
             "resolved": "https://registry.npmjs.org/scss-loader/-/scss-loader-0.0.1.tgz",
-            "integrity": "sha512-SbT/smRJjkvvdHSEdAYAplosVkrtaSwwgUlnQCOuDS5sOKNjrS/eYCMvKeV6+YxK5cCOCsOJZd3vltrXatFp+g==",
+            "integrity": "sha1-6uAXueDzjBKlMtslwiC5Avs05nE=",
             "dev": true
         },
         "scss-tokenizer": {
             "version": "0.2.3",
             "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
-            "integrity": "sha512-dYE8LhncfBUar6POCxMTm0Ln+erjeczqEvCJib5/7XNkdw1FkUGgwMPY360FY0FgPWQxHWCx29Jl3oejyGLM9Q==",
+            "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
             "requires": {
                 "js-base64": "^2.1.8",
                 "source-map": "^0.4.2"
@@ -19547,7 +19552,7 @@
                 "source-map": {
                     "version": "0.4.4",
                     "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
-                    "integrity": "sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A==",
+                    "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
                     "requires": {
                         "amdefine": ">=0.0.4"
                     }
@@ -19562,17 +19567,17 @@
         "section-iterator": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/section-iterator/-/section-iterator-2.0.0.tgz",
-            "integrity": "sha512-xvTNwcbeDayXotnV32zLb3duQsP+4XosHpb/F+tu6VzEZFmIjzPdNk6/O+QOOx5XTh08KL2ufdXeCO33p380pQ=="
+            "integrity": "sha1-v0RNev7rlK1Dw5rS+yYVFifMuio="
         },
         "select": {
             "version": "1.1.2",
             "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
-            "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
+            "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
         },
         "select-hose": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
-            "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==",
+            "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
             "dev": true
         },
         "selfsigned": {
@@ -19592,12 +19597,12 @@
         "semver-compare": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
-            "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow=="
+            "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w="
         },
         "semver-diff": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz",
-            "integrity": "sha512-gL8F8L4ORwsS0+iQ34yCYv///jsOq0ZL7WP55d1HnJ32o7tyFYEFQZQA22mrLIacZdU6xecaBBZ+uEiffGNyXw==",
+            "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=",
             "requires": {
                 "semver": "^5.0.3"
             }
@@ -19661,7 +19666,7 @@
         "serve-index": {
             "version": "1.9.1",
             "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
-            "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==",
+            "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
             "dev": true,
             "requires": {
                 "accepts": "~1.3.4",
@@ -19691,7 +19696,7 @@
                 "http-errors": {
                     "version": "1.6.3",
                     "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
-                    "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
+                    "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
                     "dev": true,
                     "requires": {
                         "depd": "~1.1.2",
@@ -19703,13 +19708,13 @@
                 "inherits": {
                     "version": "2.0.3",
                     "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
-                    "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
+                    "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
                     "dev": true
                 },
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
                     "dev": true
                 },
                 "setprototypeof": {
@@ -19740,7 +19745,7 @@
         "set-blocking": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
-            "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
+            "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
         },
         "set-value": {
             "version": "2.0.1",
@@ -19756,7 +19761,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -19766,7 +19771,7 @@
         "setimmediate": {
             "version": "1.0.5",
             "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
-            "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
+            "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
         },
         "setprototypeof": {
             "version": "1.2.0",
@@ -19928,7 +19933,7 @@
         "shebang-command": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
-            "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
+            "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
             "requires": {
                 "shebang-regex": "^1.0.0"
             }
@@ -19936,7 +19941,7 @@
         "shebang-regex": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
-            "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="
+            "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
         },
         "shelljs": {
             "version": "0.8.5",
@@ -19971,7 +19976,7 @@
         "simple-assign": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/simple-assign/-/simple-assign-0.1.0.tgz",
-            "integrity": "sha512-otdSSQzuVsmDoe5MnSm4ZgHd5sl0ak6A1CTjW1R/DUHQ8xoZuU1NUzf9x6n9Dvp3nxpvW51WNMQ/7rQ9432xDg=="
+            "integrity": "sha1-F/0wZqXz13OPUDIbsPFMooHMS6o="
         },
         "simple-concat": {
             "version": "1.0.1",
@@ -19991,7 +19996,7 @@
         "simple-swizzle": {
             "version": "0.2.2",
             "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
-            "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+            "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
             "requires": {
                 "is-arrayish": "^0.3.1"
             },
@@ -20006,7 +20011,7 @@
         "slash": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
-            "integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==",
+            "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
             "dev": true
         },
         "slice-ansi": {
@@ -20023,7 +20028,7 @@
         "sliced": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
-            "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA=="
+            "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E="
         },
         "snapdragon": {
             "version": "0.8.2",
@@ -20051,7 +20056,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
+                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -20059,7 +20064,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -20067,7 +20072,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
                 }
             }
         },
@@ -20084,7 +20089,7 @@
                 "define-property": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-                    "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
+                    "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
                     "requires": {
                         "is-descriptor": "^1.0.0"
                     }
@@ -20133,7 +20138,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -20229,7 +20234,7 @@
                 "component-emitter": {
                     "version": "1.2.1",
                     "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
-                    "integrity": "sha512-jPatnhd33viNplKjqXKRkGU345p263OIWzDL2wH3LGIGp5Kojo+uXizHmOADRvhGFFTnJqX3jBAKP6vvmSDKcA=="
+                    "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
                 },
                 "debug": {
                     "version": "4.1.1",
@@ -20242,7 +20247,7 @@
                 "isarray": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
-                    "integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ=="
+                    "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
                 }
             }
         },
@@ -20312,7 +20317,7 @@
         "source-map": {
             "version": "0.5.7",
             "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-            "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="
+            "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
         },
         "source-map-resolve": {
             "version": "0.5.3",
@@ -20355,7 +20360,7 @@
         "sparse-bitfield": {
             "version": "3.0.3",
             "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
-            "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
+            "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
             "optional": true,
             "requires": {
                 "memory-pager": "^1.0.2"
@@ -20458,7 +20463,7 @@
         "split-skip": {
             "version": "0.0.2",
             "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.2.tgz",
-            "integrity": "sha512-weHOi8BolsDnGIwhhWHbA+wKSuSpvWwjRrdj8SdbIIis2vSwOE37CQP8x3EleuzxanUr3AK8BdUy4MkiOULPZg=="
+            "integrity": "sha1-2J2Iu9L3Pka1FYqjcKVhIk6A1GE="
         },
         "split-string": {
             "version": "3.1.0",
@@ -20471,7 +20476,7 @@
         "sprintf-js": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
-            "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
+            "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
         },
         "sshpk": {
             "version": "1.17.0",
@@ -20523,7 +20528,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
+                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -20602,7 +20607,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
                 }
             }
         },
@@ -20692,7 +20697,7 @@
                 "magicli": {
                     "version": "0.0.5",
                     "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
-                    "integrity": "sha512-wZbMtnl2v1b+Jp3xlqA9FU/O4I6YhGXR8xSY/eU2+gDAvut/F+W3gl4qs61iL4LELC7jqSAE6aAD5668EbmQHA==",
+                    "integrity": "sha1-zufQ+7THBRiqyxHsPrfiX/SaSSE=",
                     "requires": {
                         "commander": "^2.9.0",
                         "get-stdin": "^5.0.1",
@@ -20734,7 +20739,7 @@
                 "get-stdin": {
                     "version": "4.0.1",
                     "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
-                    "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw=="
+                    "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4="
                 }
             }
         },
@@ -21107,7 +21112,7 @@
         "to-array": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
-            "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA="
+            "integrity": "sha512-LhVdShQD/4Mk4zXNroIQZJC+Ap3zgLcDuwEdcmLv9CCO73NWockQDwyUnW/m8VX/EElfL6FcYx7EeutN4HJA6A=="
         },
         "to-fast-properties": {
             "version": "2.0.0",
@@ -21130,7 +21135,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -21178,7 +21183,7 @@
                 "nopt": {
                     "version": "1.0.10",
                     "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
-                    "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
+                    "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
                     "requires": {
                         "abbrev": "1"
                     }
@@ -21313,7 +21318,7 @@
                 "arrify": {
                     "version": "1.0.1",
                     "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
-                    "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==",
+                    "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
                     "dev": true
                 }
             }
@@ -21717,7 +21722,7 @@
                 "jsonfile": {
                     "version": "4.0.0",
                     "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
-                    "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
+                    "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
                     "requires": {
                         "graceful-fs": "^4.1.6"
                     }
@@ -21747,12 +21752,12 @@
                 "camelcase": {
                     "version": "1.2.1",
                     "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
-                    "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g=="
+                    "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
                 },
                 "cliui": {
                     "version": "2.1.0",
                     "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
-                    "integrity": "sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==",
+                    "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
                     "requires": {
                         "center-align": "^0.1.1",
                         "right-align": "^0.1.1",
@@ -21833,7 +21838,7 @@
                 "pako": {
                     "version": "0.2.9",
                     "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
-                    "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA=="
+                    "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU="
                 }
             }
         },
@@ -21978,7 +21983,7 @@
                 "has-value": {
                     "version": "0.3.1",
                     "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
-                    "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==",
+                    "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
                     "requires": {
                         "get-value": "^2.0.3",
                         "has-values": "^0.1.4",
@@ -21988,7 +21993,7 @@
                         "isobject": {
                             "version": "2.1.0",
                             "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
-                            "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==",
+                            "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
                             "requires": {
                                 "isarray": "1.0.0"
                             }
@@ -21998,7 +22003,7 @@
                 "has-values": {
                     "version": "0.1.4",
                     "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
-                    "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ=="
+                    "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E="
                 }
             }
         },
@@ -22070,7 +22075,7 @@
                 "punycode": {
                     "version": "1.3.2",
                     "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
-                    "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==",
+                    "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
                     "dev": true
                 }
             }
@@ -22623,7 +22628,7 @@
                 "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==",
+                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
                     "dev": true
                 },
                 "debug": {
@@ -22648,7 +22653,7 @@
                 "memory-fs": {
                     "version": "0.4.1",
                     "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
-                    "integrity": "sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ==",
+                    "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
                     "dev": true,
                     "requires": {
                         "errno": "^0.1.3",
@@ -22694,7 +22699,7 @@
                 "resolve-cwd": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
-                    "integrity": "sha512-ccu8zQTrzVr954472aUVPLEcB3YpKSYR3cg/3lo1okzobPBM+1INXBbBZlDbnI/hbEocnf8j0QVo43hQKrbchg==",
+                    "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
                     "dev": true,
                     "requires": {
                         "resolve-from": "^3.0.0"
@@ -22703,7 +22708,7 @@
                 "resolve-from": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
-                    "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==",
+                    "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
                     "dev": true
                 },
                 "semver": {
@@ -23117,7 +23122,7 @@
                 "lodash": {
                     "version": "3.10.1",
                     "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
-                    "integrity": "sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ=="
+                    "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
                 }
             }
         },
@@ -23244,7 +23249,7 @@
         "yeast": {
             "version": "0.1.2",
             "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
-            "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk="
+            "integrity": "sha512-8HFIh676uyGYP6wP13R/j6OJ/1HwJ46snpvzE7aHAN3Ryqh2yX6Xox2B4CUmTwwOIzlG3Bs7ocsP5dZH/R1Qbg=="
         },
         "yn": {
             "version": "2.0.0",
diff --git a/package.json b/package.json
index ccbc73a79..c1a3c5fa4 100644
--- a/package.json
+++ b/package.json
@@ -222,6 +222,7 @@
         "jszip": "^3.7.1",
         "lodash": "^4.17.21",
         "material-ui": "^0.20.2",
+        "md5-file": "^5.0.0",
         "memorystream": "^0.3.1",
         "mobile-detect": "^1.4.5",
         "mobx": "^5.15.7",
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 886dd974b..465bb40f0 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -3,7 +3,6 @@ import { DateField } from '../../fields/DateField';
 import { AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, AclSym, DataSym, Doc, DocListCast, Opt } from '../../fields/Doc';
 import { InkTool } from '../../fields/InkField';
 import { List } from '../../fields/List';
-import { ScriptField } from '../../fields/ScriptField';
 import { Cast, ScriptCast } from '../../fields/Types';
 import { denormalizeEmail, distributeAcls, GetEffectiveAcl, inheritParentAcls, SharingPermissions } from '../../fields/util';
 import { returnFalse } from '../../Utils';
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 0a06b6e00..ee3f46818 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -42,6 +42,7 @@ interface CollectionViewProps_ extends FieldViewProps {
     isAnnotationOverlayScrollable?: boolean; // whether the annotation overlay can be vertically scrolled (just for tree views, currently)
     layoutEngine?: () => string;
     setPreviewCursor?: (func: (x: number, y: number, drag: boolean, hide: boolean) => void) => void;
+    setBrushViewer?: (func?: (view: { width: number; height: number; panX: number; panY: number }) => void) => void;
 
     // property overrides for child documents
     childDocuments?: Doc[]; // used to override the documents shown by the sub collection to an explicit list (see LinkBox)
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 7a075a7ff..a82bd2dc8 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -231,7 +231,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             pinDoc.presentationTargetDoc = doc;
             pinDoc.title = doc.title + ' - Slide';
             pinDoc.data = new List<Doc>(); // the children of the alias' layout are the presentation slide children.  the alias' data field might be children of a collection, PDF data, etc -- in any case we don't want the tree view to "see" this data
-            pinDoc.presMovement = pinProps?.pinDocView ? PresMovement.None : PresMovement.Zoom;
+            pinDoc.presMovement = pinProps?.pinDocView && !pinProps?.pinWithView ? PresMovement.None : PresMovement.Zoom;
             pinDoc.groupWithUp = false;
             pinDoc.context = curPres;
             // these should potentially all be props passed down by the CollectionTreeView to the TreeView elements.  That way the PresBox could configure all of its children at render time
@@ -367,7 +367,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     @action
     focusFunc = (doc: Doc, options?: DocFocusOptions) => {
         const shrinkwrap = options?.originalTarget === this._document && this.view?.ComponentView?.shrinkWrap;
-        if (shrinkwrap && this._document) {
+        if (options?.willZoom !== false && shrinkwrap && this._document) {
             const focusSpeed = NumCast(this._document.focusSpeed, 500);
             shrinkwrap();
             this._document._viewTransition = `transform ${focusSpeed}ms`;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 6927d429d..3cc425745 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -88,6 +88,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     private _cachedPool: Map<string, PoolData> = new Map();
     private _lastTap = 0;
     private _batch: UndoManager.Batch | undefined = undefined;
+    private _brushtimer: any;
+    private _brushtimer1: any;
 
     // private isWritingMode: boolean = true;
     // private writingModeDocs: Doc[] = [];
@@ -114,6 +116,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     @observable _marqueeRef = React.createRef<HTMLDivElement>();
     @observable _marqueeViewRef = React.createRef<MarqueeView>();
     @observable ChildDrag: DocumentView | undefined; // child document view being dragged.  needed to update drop areas of groups when a group item is dragged.
+    @observable _brushedView = { width: 0, height: 0, panX: 0, panY: 0, opacity: 0 }; // highlighted region of freeform canvas used by presentations to indicate a region
 
     @computed get views() {
         const viewsMask = this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z && ele.inkMask !== -1 && ele.inkMask !== undefined).map(ele => ele.ele);
@@ -1520,6 +1523,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     componentDidMount() {
         super.componentDidMount?.();
         this.props.setContentView?.(this);
+        this.props.setBrushViewer?.(this.brushView);
         setTimeout(
             action(() => {
                 this._firstRender = false;
@@ -1881,6 +1885,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                         </div>
                     ) : null}
                     <CollectionFreeFormViewPannableContents
+                        brushView={this._brushedView}
                         isAnnotationOverlay={this.isAnnotationOverlay}
                         isAnnotationOverlayScrollable={this.props.isAnnotationOverlayScrollable}
                         transform={this.contentTransform}
@@ -1916,9 +1921,25 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         }
     };
 
+    @action
+    brushView = (viewport: { width: number; height: number; panX: number; panY: number }) => {
+        this._brushedView = { ...viewport, panX: viewport.panX - viewport.width / 2, panY: viewport.panY - viewport.height / 2, opacity: 1 };
+        this._brushtimer1 && clearTimeout(this._brushtimer1);
+        this._brushtimer && clearTimeout(this._brushtimer);
+        this._brushtimer1 = setTimeout(
+            action(() => {
+                this._brushedView.opacity = 0;
+                this._brushtimer = setTimeout(
+                    action(() => (this._brushedView = { width: 0, height: 0, panX: 0, panY: 0, opacity: 0 })),
+                    500
+                );
+            }),
+            1000
+        );
+    };
+
     render() {
         TraceMobx();
-        const clientRect = this._mainCont?.getBoundingClientRect();
         return (
             <div
                 className={'collectionfreeformview-container'}
@@ -2004,6 +2025,7 @@ interface CollectionFreeFormViewPannableContentsProps {
     presPinView?: boolean;
     isAnnotationOverlay: boolean | undefined;
     isAnnotationOverlayScrollable: boolean | undefined;
+    brushView: { panX: number; panY: number; width: number; height: number; opacity: number };
 }
 
 @observer
@@ -2123,6 +2145,21 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF
                     //willChange: "transform"
                 }}>
                 {this.props.children()}
+                {!this.props.brushView.width ? null : (
+                    <div
+                        className="collectionFreeFormView-brushView"
+                        style={{
+                            zIndex: 1000,
+                            opacity: this.props.brushView.opacity,
+                            border: 'orange solid 2px',
+                            position: 'absolute',
+                            transform: `translate(${this.props.brushView.panX}px, ${this.props.brushView.panY}px)`,
+                            width: this.props.brushView.width,
+                            height: this.props.brushView.height,
+                            transition: 'opacity 2s',
+                        }}
+                    />
+                )}
                 {this.presPaths}
                 {this.progressivize}
                 {this.zoomProgressivize}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 58a00bbac..584c9690f 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -425,13 +425,11 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
     @undoBatch
     @action
     pinWithView = async () => {
-        const scale = Math.min(this.props.PanelWidth() / this.Bounds.width, this.props.PanelHeight() / this.Bounds.height);
         const doc = this.props.Document;
         const viewOptions: PinViewProps = {
             bounds: this.Bounds,
-            scale: scale,
         };
-        TabDocView.PinDoc(doc, { pinWithView: viewOptions });
+        TabDocView.PinDoc(doc, { pinWithView: viewOptions, pinDocView: true });
         MarqueeOptionsMenu.Instance.fadeOut(true);
         this.hideMarquee();
     };
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 2966c2a22..f24ceb5ae 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -86,6 +86,7 @@ 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
+    brushView?: (view: { width: number; height: number; panX: number; panY: number }) => void;
     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/ fitContentsToBox 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
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 345407c2f..001d9a5a6 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -195,6 +195,9 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         );
     }
 
+    brushView = (view: { width: number; height: number; panX: number; panY: number }) => {
+        this._pdfViewer?.brushView(view);
+    };
     scrollFocus = (doc: Doc, smooth: boolean) => {
         let didToggle = false;
         if (DocListCast(this.props.Document[this.fieldKey + '-sidebar']).includes(doc) && !this.SidebarShown) {
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 6a929ef80..ab59e6112 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -44,7 +44,6 @@ export interface PinProps {
 
 export interface PinViewProps {
     bounds: MarqueeViewBounds;
-    scale: number;
 }
 
 @observer
@@ -362,17 +361,32 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         bestTarget._viewTransition = presTransitionTime;
         if (clippable) bestTarget._clipWidth = activeItem.presPinClipWidth;
         if (temporal) bestTarget._currentTimecode = activeItem.presStartTime;
-        if (scrollable) bestTarget._scrollTop = activeItem.presPinViewScroll;
+        if (scrollable) {
+            bestTarget._scrollTop = activeItem.presPinViewScroll;
+            const contentBounds = Cast(activeItem.presPinViewBounds, listSpec('number'));
+            if (contentBounds) {
+                const dv = DocumentManager.Instance.getDocumentView(bestTarget)?.ComponentView;
+                dv?.brushView?.({ panX: (contentBounds[0] + contentBounds[2]) / 2, panY: (contentBounds[1] + contentBounds[3]) / 2, width: contentBounds[2] - contentBounds[0], height: contentBounds[3] - contentBounds[1] });
+            }
+        }
         if (dataview) Doc.GetProto(bestTarget).data = activeItem.presData instanceof ObjectField ? activeItem.presData[Copy]() : activeItem.presData;
         if (textview) Doc.GetProto(bestTarget).text = activeItem.presData instanceof ObjectField ? activeItem.presData[Copy]() : activeItem.presData;
         if (pannable) {
-            bestTarget._panX = activeItem.presPinViewX;
-            bestTarget._panY = activeItem.presPinViewY;
-            bestTarget._viewScale = activeItem.presPinViewScale;
             const contentBounds = Cast(activeItem.presPinViewBounds, listSpec('number'));
             if (contentBounds) {
+                const viewport = { panX: (contentBounds[0] + contentBounds[2]) / 2, panY: (contentBounds[1] + contentBounds[3]) / 2, width: contentBounds[2] - contentBounds[0], height: contentBounds[3] - contentBounds[1] };
+                bestTarget._panX = viewport.panX;
+                bestTarget._panY = viewport.panY;
                 const dv = DocumentManager.Instance.getDocumentView(bestTarget);
-                dv && (bestTarget._viewScale = Math.min(dv.props.PanelHeight() / (contentBounds[3] - contentBounds[1]), dv.props.PanelWidth() / (contentBounds[2] - contentBounds[0])));
+                if (dv) {
+                    const computedScale = NumCast(activeItem.presZoom, 1) * Math.min(dv.props.PanelWidth() / viewport.width, dv.props.PanelHeight() / viewport.height);
+                    activeItem.presMovement === 'zoom' && (bestTarget._viewScale = activeItem.presZoom !== undefined ? computedScale : Math.min(computedScale, NumCast(bestTarget._viewScale)));
+                    dv.ComponentView?.brushView?.(viewport);
+                }
+            } else {
+                bestTarget._panX = activeItem.presPinViewX;
+                bestTarget._panY = activeItem.presPinViewY;
+                activeItem.presMovement === 'zoom' && (bestTarget._viewScale = activeItem.presPinViewScale);
             }
         }
         return setTimeout(() => (bestTarget._viewTransition = undefined), transTime + 10);
@@ -389,7 +403,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             pinDoc.presPinView = true;
             pinDoc.presPinViewX = bounds.left + bounds.width / 2;
             pinDoc.presPinViewY = bounds.top + bounds.height / 2;
-            pinDoc.presPinViewScale = pinProps.pinWithView.scale;
             pinDoc.presPinViewBounds = new List<number>([bounds.left, bounds.top, bounds.left + bounds.width, bounds.top + bounds.height]);
         }
         if (pinProps?.pinDocView) {
@@ -401,12 +414,14 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             pinDoc.presWidth = NumCast(targetDoc.width);
             pinDoc.presHeight = NumCast(targetDoc.height);
 
-            if (scrollable) pinDoc.presPinViewScroll = pinDoc._scrollTop;
+            if (scrollable) {
+                pinDoc.presPinViewScroll = pinDoc._scrollTop;
+            }
             if (clippable) pinDoc.presPinClipWidth = pinDoc._clipWidth;
             if (temporal) pinDoc.presEndTime = NumCast((pinDoc.presStartTime = pinDoc._currentTimecode)) + 0.1;
             if (textview) pinDoc.presData = targetDoc.text instanceof ObjectField ? targetDoc.text[Copy]() : targetDoc.text;
             if (dataview) pinDoc.presData = targetDoc.data instanceof ObjectField ? targetDoc.data[Copy]() : targetDoc.data;
-            if (pannable) {
+            if (pannable || scrollable) {
                 const panX = NumCast(pinDoc._panX);
                 const panY = NumCast(pinDoc._panY);
                 const pw = NumCast(pinProps.panelWidth);
@@ -1131,7 +1146,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         let scale = Number(number) / 100;
         if (change) scale += change;
         if (scale < 0.01) scale = 0.01;
-        if (scale > 1.5) scale = 1.5;
+        if (scale > 1) scale = 1;
         this.selectedArray.forEach(doc => (doc.presZoom = scale));
     };
 
@@ -1246,28 +1261,22 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     })}>
                     <div className="ribbon-box">
                         Movement
-                        {isPresCollection || (isPresCollection && isPinWithView) ? (
-                            <div className="ribbon-property" style={{ marginLeft: 0, height: 25, textAlign: 'left', paddingLeft: 5, paddingRight: 5, fontSize: 10 }}>
-                                {this.scrollable ? 'Scroll to pinned view' : !isPinWithView ? 'No movement' : 'Pan & Zoom to pinned view'}
-                            </div>
-                        ) : (
-                            <div
-                                className="presBox-dropdown"
-                                onClick={action(e => {
-                                    e.stopPropagation();
-                                    this._openMovementDropdown = !this._openMovementDropdown;
-                                })}
-                                style={{ borderBottomLeftRadius: this._openMovementDropdown ? 0 : 5, border: this._openMovementDropdown ? `solid 2px ${Colors.MEDIUM_BLUE}` : 'solid 1px black' }}>
-                                {this.movementName(activeItem)}
-                                <FontAwesomeIcon className="presBox-dropdownIcon" style={{ gridColumn: 2, color: this._openMovementDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={'angle-down'} />
-                                <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onPointerDown={StopEvent} style={{ display: this._openMovementDropdown ? 'grid' : 'none' }}>
-                                    {presMovement(PresMovement.None)}
-                                    {presMovement(PresMovement.Zoom)}
-                                    {presMovement(PresMovement.Pan)}
-                                    {presMovement(PresMovement.Jump)}
-                                </div>
+                        <div
+                            className="presBox-dropdown"
+                            onClick={action(e => {
+                                e.stopPropagation();
+                                this._openMovementDropdown = !this._openMovementDropdown;
+                            })}
+                            style={{ borderBottomLeftRadius: this._openMovementDropdown ? 0 : 5, border: this._openMovementDropdown ? `solid 2px ${Colors.MEDIUM_BLUE}` : 'solid 1px black' }}>
+                            {this.movementName(activeItem)}
+                            <FontAwesomeIcon className="presBox-dropdownIcon" style={{ gridColumn: 2, color: this._openMovementDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={'angle-down'} />
+                            <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onPointerDown={StopEvent} style={{ display: this._openMovementDropdown ? 'grid' : 'none' }}>
+                                {isPresCollection || (isPresCollection && isPinWithView) ? null : presMovement(PresMovement.None)}
+                                {presMovement(PresMovement.Zoom)}
+                                {presMovement(PresMovement.Pan)}
+                                {isPresCollection || (isPresCollection && isPinWithView) ? null : presMovement(PresMovement.Jump)}
                             </div>
-                        )}
+                        </div>
                         <div className="ribbon-doubleButton" style={{ display: activeItem.presMovement === PresMovement.Zoom ? 'inline-flex' : 'none' }}>
                             <div className="presBox-subheading">Zoom (% screen filled)</div>
                             <div className="ribbon-property">
@@ -1282,7 +1291,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 </div>
                             </div>
                         </div>
-                        {inputter('0', '1', '150', zoom, activeItem.presMovement === PresMovement.Zoom, this.setZoom)}
+                        {inputter('0', '1', '100', zoom, activeItem.presMovement === PresMovement.Zoom, this.setZoom)}
                         <div className="ribbon-doubleButton" style={{ display: activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? 'inline-flex' : 'none' }}>
                             <div className="presBox-subheading">Movement Speed</div>
                             <div className="ribbon-property">
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 53d969c0a..5925c0392 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -64,6 +64,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
     private _styleRule: any; // stylesheet rule for making hyperlinks clickable
     private _retries = 0; // number of times tried to create the PDF viewer
     private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean) => void);
+    private _setBrushViewer: undefined | ((view: { width: number; height: number; panX: number; panY: number }) => void);
     private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
     private _disposers: { [name: string]: IReactionDisposer } = {};
     private _viewer: React.RefObject<HTMLDivElement> = React.createRef();
@@ -174,9 +175,8 @@ export class PDFViewer extends React.Component<IViewerProps> {
         }
         return focusSpeed;
     };
-    crop = (region: Doc | undefined, addCrop?: boolean) => {
-        return this.props.crop(region, addCrop);
-    };
+    crop = (region: Doc | undefined, addCrop?: boolean) => this.props.crop(region, addCrop);
+    brushView = (view: { width: number; height: number; panX: number; panY: number }) => this._setBrushViewer?.(view);
 
     @action
     setupPdfJsViewer = async () => {
@@ -446,6 +446,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
     };
 
     setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean) => void) => (this._setPreviewCursor = func);
+    setBrushViewer = (func?: (view: { width: number; height: number; panX: number; panY: number }) => void) => (this._setBrushViewer = func);
 
     @action
     onZoomWheel = (e: React.WheelEvent) => {
@@ -512,6 +513,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
                 fieldKey={this.props.fieldKey + '-annotations'}
                 CollectionView={undefined}
                 setPreviewCursor={this.setPreviewCursor}
+                setBrushViewer={this.setBrushViewer}
                 PanelHeight={this.panelHeight}
                 PanelWidth={this.panelWidth}
                 ScreenToLocalTransform={this.overlayTransform}
diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts
index c38f603a4..c28ae686b 100644
--- a/src/server/DashUploadUtils.ts
+++ b/src/server/DashUploadUtils.ts
@@ -2,7 +2,7 @@ import { green, red } from 'colors';
 import { ExifImage } from 'exif';
 import * as exifr from 'exifr';
 import { File } from 'formidable';
-import { createWriteStream, existsSync, readFileSync, rename, unlinkSync, writeFile } from 'fs';
+import { createReadStream, createWriteStream, exists, existsSync, readFileSync, rename, unlinkSync, writeFile } from 'fs';
 import * as path from 'path';
 import { basename } from 'path';
 import * as sharp from 'sharp';
@@ -22,6 +22,7 @@ const parse = require('pdf-parse');
 const ffmpeg = require('fluent-ffmpeg');
 const fs = require('fs');
 const requestImageSize = require('../client/util/request-image-size');
+const md5File = require('md5-file');
 
 export enum SizeSuffix {
     Small = '_s',
@@ -99,34 +100,58 @@ export namespace DashUploadUtils {
         };
     }
 
+    function resolveExistingFile(name: string, path: string, directory: Directory, type?: string, duration?: number, rawText?: string) {
+        const data = { size: 0, path, name, type: type ?? '' };
+        const file = { ...data, toJSON: () => ({ ...data, filename: data.path.replace(/.*\//, ''), mtime: duration?.toString(), mime: '', toJson: () => undefined as any }) };
+        return {
+            source: file,
+            result: {
+                accessPaths: {
+                    agnostic: getAccessPaths(directory, path),
+                },
+                rawText,
+                duration,
+            },
+        };
+    }
+
     export function uploadYoutube(videoId: string): Promise<Upload.FileResponse> {
         return new Promise<Upload.FileResponse<Upload.FileInformation>>((res, rej) => {
             console.log('Uploading YouTube video: ' + videoId);
             const name = videoId;
             const path = name.replace(/^-/, '__') + '.mp4';
-            exec(`youtube-dl -o ${path} "https://www.youtube.com/watch?v=${videoId}" -f "mp4[filesize<5M]/bestvideo[filesize<5M]+bestaudio/bestvideo+bestaudio"`, (error: any, stdout: any, stderr: any) => {
-                if (error) {
-                    console.log(`error: Error: ${error.message}`);
-                    res({
-                        source: {
-                            size: 0,
-                            path,
-                            name,
-                            type: '',
-                            toJSON: () => ({ name, path }),
-                        },
-                        result: { name: 'failed youtube query', message: `Could not upload YouTube video (${videoId}).  Error: ${error.message}` },
-                    });
-                } else {
-                    exec(`youtube-dl -o ${path} "https://www.youtube.com/watch?v=${videoId}" --get-duration`, (error: any, stdout: any, stderr: any) => {
-                        const time = Array.from(stdout.trim().split(':')).reverse();
-                        const duration = (time.length > 2 ? Number(time[2]) * 1000 * 60 : 0) + (time.length > 1 ? Number(time[1]) * 60 : 0) + (time.length > 0 ? Number(time[0]) : 0);
-                        const data = { size: 0, path, name, type: 'video/mp4' };
-                        const file = { ...data, toJSON: () => ({ ...data, filename: data.path.replace(/.*\//, ''), mtime: duration.toString(), mime: '', toJson: () => undefined as any }) };
-                        res(MoveParsedFile(file, Directory.videos));
-                    });
-                }
-            });
+            const finalPath = serverPathToFile(Directory.videos, path);
+            if (existsSync(finalPath)) {
+                exec(`youtube-dl -o ${finalPath} "https://www.youtube.com/watch?v=${videoId}" --get-duration`, (error: any, stdout: any, stderr: any) => {
+                    const time = Array.from(stdout.trim().split(':')).reverse();
+                    const duration = (time.length > 2 ? Number(time[2]) * 1000 * 60 : 0) + (time.length > 1 ? Number(time[1]) * 60 : 0) + (time.length > 0 ? Number(time[0]) : 0);
+                    res(resolveExistingFile(name, finalPath, Directory.videos, 'video/mp4', duration, undefined));
+                });
+            } else {
+                exec(`youtube-dl -o ${path} "https://www.youtube.com/watch?v=${videoId}" -f "mp4[filesize<5M]/bestvideo[filesize<5M]+bestaudio/bestvideo+bestaudio"`, (error: any, stdout: any, stderr: any) => {
+                    if (error) {
+                        console.log(`error: Error: ${error.message}`);
+                        res({
+                            source: {
+                                size: 0,
+                                path,
+                                name,
+                                type: '',
+                                toJSON: () => ({ name, path }),
+                            },
+                            result: { name: 'failed youtube query', message: `Could not upload YouTube video (${videoId}).  Error: ${error.message}` },
+                        });
+                    } else {
+                        exec(`youtube-dl -o ${path} "https://www.youtube.com/watch?v=${videoId}" --get-duration`, (error: any, stdout: any, stderr: any) => {
+                            const time = Array.from(stdout.trim().split(':')).reverse();
+                            const duration = (time.length > 2 ? Number(time[2]) * 1000 * 60 : 0) + (time.length > 1 ? Number(time[1]) * 60 : 0) + (time.length > 0 ? Number(time[0]) : 0);
+                            const data = { size: 0, path, name, type: 'video/mp4' };
+                            const file = { ...data, toJSON: () => ({ ...data, filename: data.path.replace(/.*\//, ''), mtime: duration.toString(), mime: '', toJson: () => undefined as any }) };
+                            res(MoveParsedFile(file, Directory.videos));
+                        });
+                    }
+                });
+            }
         });
     }
 
@@ -144,6 +169,7 @@ export namespace DashUploadUtils {
                     const result = await UploadImage(path, basename(path));
                     return { source: file, result };
                 }
+                fs.unlink(path, () => {});
                 return { source: file, result: { name: 'Unsupported image format', message: `Could not upload unsupported file (${name}). Please convert to an .jpg` } };
             case 'video':
                 if (format.includes('x-matroska')) {
@@ -167,21 +193,25 @@ export namespace DashUploadUtils {
                             res();
                         })
                     );
-                    if (abort) return { source: file, result: { name: 'Unsupported video format', message: `Could not upload unsupported file (${name}). Please convert to an .mp4` } };
-                    // bcz: instead of aborting, we could convert the file using the code below to an mp4.  Problem is that this takes a long time and will clog up the server.
-                    // await new Promise(res =>
-                    //     ffmpeg(file.path)
-                    //         .videoCodec('libx264') // this will copy the data instead of reencode it
-                    //         .audioCodec('mp2')
-                    //         .save(file.path.replace('.MOV', '.mp4').replace('.mov', '.mp4'))
-                    //         .on('end', res)
-                    // );
-                    // file.path = file.path.replace('.mov', '.mp4').replace('.MOV', '.mp4');
-                    // format = '.mp4';
+                    if (abort) {
+                        // bcz: instead of aborting, we could convert the file using the code below to an mp4.  Problem is that this takes a long time and will clog up the server.
+                        // await new Promise(res =>
+                        //     ffmpeg(file.path)
+                        //         .videoCodec('libx264') // this will copy the data instead of reencode it
+                        //         .audioCodec('mp2')
+                        //         .save(file.path.replace('.MOV', '.mp4').replace('.mov', '.mp4'))
+                        //         .on('end', res)
+                        // );
+                        // file.path = file.path.replace('.mov', '.mp4').replace('.MOV', '.mp4');
+                        // format = '.mp4';
+                        fs.unlink(path, () => {});
+                        return { source: file, result: { name: 'Unsupported video format', message: `Could not upload unsupported file (${name}). Please convert to an .mp4` } };
+                    }
                 }
                 if (videoFormats.includes(format)) {
                     return MoveParsedFile(file, Directory.videos);
                 }
+                fs.unlink(path, () => {});
                 return { source: file, result: { name: 'Unsupported video format', message: `Could not upload unsupported file (${name}). Please convert to an .mp4` } };
             case 'application':
                 if (applicationFormats.includes(format)) {
@@ -195,6 +225,7 @@ export namespace DashUploadUtils {
                 if (audioFormats.includes(format)) {
                     return UploadAudio(file, format);
                 }
+                fs.unlink(path, () => {});
                 return { source: file, result: { name: 'Unsupported audio format', message: `Could not upload unsupported file (${name}). Please convert to an .mp3` } };
             case 'text':
                 if (types[1] == 'csv') {
@@ -203,20 +234,28 @@ export namespace DashUploadUtils {
         }
 
         console.log(red(`Ignoring unsupported file (${name}) with upload type (${type}).`));
+        fs.unlink(path, () => {});
         return { source: file, result: new Error(`Could not upload unsupported file (${name}) with upload type (${type}).`) };
     }
 
     async function UploadPdf(file: File) {
-        const { path: sourcePath } = file;
-        const dataBuffer = readFileSync(sourcePath);
+        const fileKey = (await md5File(file.path)) + '.pdf';
+        const textFilename = `${fileKey.substring(0, fileKey.length - 4)}.txt`;
+        if (fExists(fileKey, Directory.pdfs) && fExists(textFilename, Directory.text)) {
+            return new Promise<Upload.FileResponse>(res => {
+                const textFilename = `${fileKey.substring(0, fileKey.length - 4)}.txt`;
+                const readStream = createReadStream(serverPathToFile(Directory.text, textFilename));
+                var rawText = '';
+                readStream.on('data', chunk => (rawText += chunk.toString())).on('end', () => res(resolveExistingFile(file.name, fileKey, Directory.pdfs, file.type, undefined, rawText)));
+            });
+        }
+        const dataBuffer = readFileSync(file.path);
         const result: ParsedPDF = await parse(dataBuffer);
         await new Promise<void>((resolve, reject) => {
-            const name = path.basename(sourcePath);
-            const textFilename = `${name.substring(0, name.length - 4)}.txt`;
             const writeStream = createWriteStream(serverPathToFile(Directory.text, textFilename));
             writeStream.write(result.text, error => (error ? reject(error) : resolve()));
         });
-        return MoveParsedFile(file, Directory.pdfs, undefined, result.text);
+        return MoveParsedFile(file, Directory.pdfs, undefined, result.text, undefined, fileKey);
     }
 
     async function UploadCsv(file: File) {
@@ -368,9 +407,9 @@ export namespace DashUploadUtils {
      * @param suffix If the file doesn't have a suffix and you want to provide it one
      * to appear in the new location
      */
-    export async function MoveParsedFile(file: formidable.File, destination: Directory, suffix: string | undefined = undefined, text?: string, duration?: number): Promise<Upload.FileResponse> {
+    export async function MoveParsedFile(file: formidable.File, destination: Directory, suffix: string | undefined = undefined, text?: string, duration?: number, targetName?: string): Promise<Upload.FileResponse> {
         const { path: sourcePath } = file;
-        let name = path.basename(sourcePath);
+        let name = targetName ?? path.basename(sourcePath);
         suffix && (name += suffix);
         return new Promise(resolve => {
             const destinationPath = serverPathToFile(destination, name);
@@ -391,6 +430,11 @@ export namespace DashUploadUtils {
         });
     }
 
+    export function fExists(name: string, destination: Directory) {
+        const destinationPath = serverPathToFile(destination, name);
+        return existsSync(destinationPath);
+    }
+
     export function getAccessPaths(directory: Directory, fileName: string) {
         return {
             client: clientPathToFile(directory, fileName),
-- 
cgit v1.2.3-70-g09d2


From d14cece23d1dac76d3bc1643e05b5b51071466ca Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 26 Sep 2022 11:14:50 -0400
Subject: added explore mode option to lightbox view.  turned of ink and
 explore mode when leaving light box.

---
 src/client/views/LightboxView.scss                       | 16 ++++++++++++++++
 src/client/views/LightboxView.tsx                        | 14 ++++++++++++++
 .../collectionFreeForm/CollectionFreeFormView.tsx        |  8 +++-----
 3 files changed, 33 insertions(+), 5 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/LightboxView.scss b/src/client/views/LightboxView.scss
index ae5dc9902..f86a1d211 100644
--- a/src/client/views/LightboxView.scss
+++ b/src/client/views/LightboxView.scss
@@ -46,6 +46,22 @@
         opacity: 1;
     }
 }
+.lightboxView-exploreBtn {
+    margin: auto;
+    position: absolute;
+    right: 100;
+    top: 10;
+    background: transparent;
+    border-radius: 8;
+    color: white;
+    opacity: 0.7;
+    width: 25;
+    flex-direction: column;
+    display: flex;
+    &:hover {
+        opacity: 1;
+    }
+}
 .lightboxView-frame {
     position: absolute;
     top: 0;
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index e3e8403df..e8b8a3eaa 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -16,6 +16,7 @@ import { CollectionStackedTimeline } from './collections/CollectionStackedTimeli
 import { TabDocView } from './collections/TabDocView';
 import { GestureOverlay } from './GestureOverlay';
 import './LightboxView.scss';
+import { MainView } from './MainView';
 import { DocumentView } from './nodes/DocumentView';
 import { DefaultStyleProvider, wavyBorderPath } from './StyleProvider';
 
@@ -53,6 +54,8 @@ export class LightboxView extends React.Component<LightboxViewProps> {
         if (!doc) {
             this._docFilters && (this._docFilters.length = 0);
             this._future = this._history = [];
+            Doc.ActiveTool = InkTool.None;
+            MainView.Instance._exploreMode = false;
         } else {
             if (doc) {
                 const l = DocUtils.MakeLinkToActiveAudio(() => doc).lastElement();
@@ -292,6 +295,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                             isContentActive={returnTrue}
                             addDocTab={this.addDocTab}
                             pinToPres={TabDocView.PinDoc}
+                            onBrowseClick={MainView.Instance.exploreMode}
                             rootSelected={returnTrue}
                             docViewPath={returnEmptyDoclist}
                             docFilters={this.docFilters}
@@ -367,6 +371,16 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                     }}>
                     <FontAwesomeIcon color={Doc.ActiveTool === InkTool.Pen ? 'black' : 'white'} icon={'pen'} size="2x" />
                 </div>
+                <div
+                    className="lightboxView-exploreBtn"
+                    title="toggle explore mode to navigate among documents only"
+                    style={{ background: MainView.Instance._exploreMode ? 'white' : undefined }}
+                    onClick={action(e => {
+                        e.stopPropagation();
+                        MainView.Instance._exploreMode = !MainView.Instance._exploreMode;
+                    })}>
+                    <FontAwesomeIcon color={MainView.Instance._exploreMode ? 'black' : 'white'} icon={'globe-americas'} size="2x" />
+                </div>
             </div>
         );
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 3cc425745..e9d0826cd 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1101,10 +1101,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     @action
     zoomSmoothlyAboutPt(docpt: number[], scale: number, transitionTime = 500) {
         if (this.Document._isGroup) return;
-        setTimeout(
-            action(() => (this._viewTransition = 0)),
-            (this._viewTransition = transitionTime)
-        ); // set transition to be smooth, then reset
+        this._viewTransition = transitionTime;
         const screenXY = this.getTransform().inverse().transformPoint(docpt[0], docpt[1]);
         this.layoutDoc[this.scaleFieldKey] = scale;
         const newScreenXY = this.getTransform().inverse().transformPoint(docpt[0], docpt[1]);
@@ -1112,6 +1109,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         const newpan = this.getTransform().transformDirection(scrDelta.x, scrDelta.y);
         this.layoutDoc._panX = NumCast(this.layoutDoc._panX) - newpan[0];
         this.layoutDoc._panY = NumCast(this.layoutDoc._panY) - newpan[1];
+        return new Promise<number>(res => setTimeout(() => res(runInAction(() => (this._viewTransition = 0))), this._viewTransition)); // set transition to be smooth, then reset
     }
 
     focusDocument = (doc: Doc, options?: DocFocusOptions) => {
@@ -2237,7 +2235,7 @@ export function CollectionBrowseClick(dv: DocumentView, clientX: number, clientY
                 const selfFfview = dv.ComponentView instanceof CollectionFreeFormView ? dv.ComponentView : undefined;
                 const parFfview = dv.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView;
                 const ffview = selfFfview && selfFfview.rootDoc[selfFfview.props.scaleField || '_viewScale'] !== 0.5 ? selfFfview : parFfview; // if focus doc is a freeform that is not at it's default 0.5 scale, then zoom out on it.  Otherwise, zoom out on the parent ffview
-                ffview?.zoomSmoothlyAboutPt(ffview.getTransform().transformPoint(clientX, clientY), 0.5);
+                await ffview?.zoomSmoothlyAboutPt(ffview.getTransform().transformPoint(clientX, clientY), 0.5);
             }
             return ViewAdjustment.doNothing;
         },
-- 
cgit v1.2.3-70-g09d2


From 4580a4193edb451f628eee8be2d3c31d06b1a3a7 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 27 Sep 2022 14:56:28 -0400
Subject: fixed so that following link to video doesn't zoom the video (works
 the same way as PDFs or web pages -- if the document is 'scrollable', then
 don't zoom in on it as well).

---
 src/client/documents/Documents.ts                  |  2 +-
 src/client/util/DocumentManager.ts                 |  4 +-
 .../views/collections/CollectionNoteTakingView.tsx |  2 +-
 .../collections/CollectionStackedTimeline.tsx      |  6 +-
 .../views/collections/CollectionStackingView.tsx   |  2 +-
 src/client/views/collections/TabDocView.tsx        |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  8 +--
 src/client/views/nodes/DocumentView.tsx            | 83 +++++++++++-----------
 8 files changed, 55 insertions(+), 54 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index f046af684..fb68fba38 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1307,7 +1307,7 @@ export namespace DocUtils {
         });
     }
 
-    export function DefaultFocus(doc: Doc, options?: DocFocusOptions) {
+    export function DefaultFocus(doc: Doc, options: DocFocusOptions) {
         options?.afterFocus?.(false);
     }
 
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 3a6c43773..50190061a 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -228,7 +228,7 @@ export class DocumentManager {
                 );
                 return;
             } else if (!docView && targetDoc.type !== DocumentType.MARKER) {
-                annoContainerView.focus(targetDoc); // this allows something like a PDF view to remove its doc filters to expose the target so that it can be found in the retry code below
+                annoContainerView.focus(targetDoc, {}); // this allows something like a PDF view to remove its doc filters to expose the target so that it can be found in the retry code below
             }
         }
         if (focusView) {
@@ -337,7 +337,7 @@ export function DocFocusOrOpen(doc: Doc, collectionDoc?: Doc) {
         const showDoc = context || doc;
         const bestAlias = showDoc === Doc.GetProto(showDoc) ? DocListCast(showDoc.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail) : showDoc;
 
-        CollectionDockingView.AddSplit(bestAlias ? bestAlias : Doc.MakeAlias(showDoc), 'right') && context && setTimeout(() => DocumentManager.Instance.getDocumentView(Doc.GetProto(doc))?.focus(doc));
+        CollectionDockingView.AddSplit(bestAlias ? bestAlias : Doc.MakeAlias(showDoc), 'right') && context && setTimeout(() => DocumentManager.Instance.getDocumentView(Doc.GetProto(doc))?.focus(doc, {}));
     }
 }
 ScriptingGlobals.add(DocFocusOrOpen);
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 92c0bc341..b0f64ed60 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -193,7 +193,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
     };
 
     // let's dive in and get the actual document we want to drag/move around
-    focusDocument = (doc: Doc, options?: DocFocusOptions) => {
+    focusDocument = (doc: Doc, options: DocFocusOptions) => {
         Doc.BrushDoc(doc);
         let focusSpeed = 0;
         const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName('documentView-node')).find((node: any) => node.id === doc[Id]);
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index c694e17fb..7bf798656 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -23,7 +23,7 @@ import { AudioWaveform } from '../AudioWaveform';
 import { CollectionSubView } from '../collections/CollectionSubView';
 import { Colors } from '../global/globalEnums';
 import { LightboxView } from '../LightboxView';
-import { DocAfterFocusFunc, DocFocusFunc, DocumentView, DocumentViewProps, DocumentViewSharedProps } from '../nodes/DocumentView';
+import { DocFocusFunc, DocFocusOptions, DocumentView, DocumentViewProps, DocumentViewSharedProps } from '../nodes/DocumentView';
 import { LabelBox } from '../nodes/LabelBox';
 import './CollectionStackedTimeline.scss';
 import { VideoBox } from '../nodes/VideoBox';
@@ -828,9 +828,9 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
     // renders anchor LabelBox
     renderInner = computedFn(function (this: StackedTimelineAnchor, mark: Doc, script: undefined | (() => ScriptField), doublescript: undefined | (() => ScriptField), screenXf: () => Transform, width: () => number, height: () => number) {
         const anchor = observable({ view: undefined as any });
-        const focusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, docTransform?: Transform) => {
+        const focusFunc = (doc: Doc, options: DocFocusOptions) => {
             this.props.playLink(mark);
-            this.props.focus(doc, { willZoom, scale, afterFocus, docTransform });
+            this.props.focus(doc, options);
         };
         return {
             anchor,
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index cc006c734..ba29b1d6f 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -251,7 +251,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
     };
 
     // let's dive in and get the actual document we want to drag/move around
-    focusDocument = (doc: Doc, options?: DocFocusOptions) => {
+    focusDocument = (doc: Doc, options: DocFocusOptions) => {
         Doc.BrushDoc(doc);
 
         let focusSpeed = 0;
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 35edbe684..b1f57f3fd 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -367,7 +367,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
         return NumCast(Cast(PresBox.Instance.childDocs[PresBox.Instance.itemIndex].presentationTargetDoc, Doc, null)._currentFrame);
     };
     @action
-    focusFunc = (doc: Doc, options?: DocFocusOptions) => {
+    focusFunc = (doc: Doc, options: DocFocusOptions) => {
         const shrinkwrap = options?.originalTarget === this._document && this.view?.ComponentView?.shrinkWrap;
         if (options?.willZoom !== false && shrinkwrap && this._document) {
             const focusSpeed = NumCast(this._document.focusSpeed, 500);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index e9d0826cd..7b6944e1e 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1112,7 +1112,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         return new Promise<number>(res => setTimeout(() => res(runInAction(() => (this._viewTransition = 0))), this._viewTransition)); // set transition to be smooth, then reset
     }
 
-    focusDocument = (doc: Doc, options?: DocFocusOptions) => {
+    focusDocument = (doc: Doc, options: DocFocusOptions) => {
         const state = HistoryUtil.getState();
 
         // TODO This technically isn't correct if type !== "doc", as
@@ -1131,13 +1131,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         // if (SelectionManager.Views().length !== 1 || SelectionManager.Views()[0].Document !== doc) {
         //     SelectionManager.DeselectAll();
         // }
-        if (this.props.Document.scrollHeight || this.props.Document.scrollTop !== undefined) {
+        if (this.props.Document.scrollHeight || this.props.Document.scrollTop !== undefined || this.props.Document.currentTimecode !== undefined) {
             this.props.focus(doc, options);
         } else {
             const xfToCollection = options?.docTransform ?? Transform.Identity();
             const savedState = { panX: NumCast(this.Document._panX), panY: NumCast(this.Document._panY), scale: options?.willZoom ? this.Document[this.scaleFieldKey] : undefined };
             const newState = HistoryUtil.getState();
-            const cantTransform = /*this.props.isAnnotationOverlay ||*/ (this.rootDoc._isGroup || this.layoutDoc._lockedTransform) && !LightboxView.LightboxDoc;
+            const cantTransform = (this.rootDoc._isGroup || this.layoutDoc._lockedTransform) && !LightboxView.LightboxDoc;
             const { panX, panY, scale } = cantTransform ? savedState : this.calculatePanIntoView(doc, xfToCollection, options?.willZoom ? options?.scale || 0.75 : undefined);
             if (!cantTransform) {
                 // only pan and zoom to focus on a document if the document is not an annotation in an annotation overlay collection
@@ -1175,7 +1175,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 ? new Transform(NumCast(this.rootDoc.x), NumCast(this.rootDoc.y), this.rootDoc[WidthSym]() / Doc.NativeWidth(this.rootDoc))
                 : new Transform(NumCast(this.rootDoc.x) + this.rootDoc[WidthSym]() / 2 - NumCast(this.rootDoc._panX), NumCast(this.rootDoc.y) + this.rootDoc[HeightSym]() / 2 - NumCast(this.rootDoc._panY), 1);
 
-            this.props.focus(cantTransform ? doc : this.rootDoc, {
+            this.props.focus(!cantTransform ? this.rootDoc : doc, {
                 ...options,
                 docTransform: xf,
                 afterFocus: (didFocus: boolean) => new Promise<ViewAdjustment>(res => setTimeout(async () => res(await endFocus(didMove || didFocus)), Math.max(0, focusSpeed - (Date.now() - startTime)))),
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index f18fd8024..ba061ce8f 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -80,7 +80,7 @@ export interface DocFocusOptions {
     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 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
@@ -534,7 +534,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         }
     };
 
-    focus = (anchor: Doc, options?: DocFocusOptions) => {
+    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)))
@@ -1259,46 +1259,47 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             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 || Doc.noviceMode ? null : (
-            <div
-                className={`documentView-titleWrapper${showTitleHover ? '-hover' : ''}`}
-                key="title"
-                style={{
-                    position: this.headerMargin ? 'relative' : 'absolute',
-                    height: this.titleHeight,
-                    width: !this.headerMargin ? `calc(100% - 18px)` : '100%', // leave room for annotation button
-                    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;
+        const titleView =
+            !showTitle || Doc.noviceMode ? null : (
+                <div
+                    className={`documentView-titleWrapper${showTitleHover ? '-hover' : ''}`}
+                    key="title"
+                    style={{
+                        position: this.headerMargin ? 'relative' : 'absolute',
+                        height: this.titleHeight,
+                        width: !this.headerMargin ? `calc(100% - 18px)` : '100%', // leave room for annotation button
+                        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 {
-                                Doc.UserDoc().showTitle = input?.substring(1) ? input.substring(1) : 'creationDate';
+                                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);
                             }
-                        } 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 true;
+                        })}
+                    />
+                </div>
+            );
         return this.props.hideTitle || (!showTitle && !showCaption) ? (
             this.contents
         ) : (
@@ -1557,7 +1558,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     }
 
     toggleNativeDimensions = () => this.docView && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.NativeDimScaling, this.props.PanelWidth(), this.props.PanelHeight());
-    focus = (doc: Doc, options?: DocFocusOptions) => this.docView?.focus(doc, options);
+    focus = (doc: Doc, options: DocFocusOptions) => this.docView?.focus(doc, options);
     getBounds = () => {
         if (!this.docView || !this.docView.ContentDiv || this.props.Document.presBox || this.docView.props.treeViewDoc || Doc.AreProtosEqual(this.props.Document, Doc.UserDoc())) {
             return undefined;
-- 
cgit v1.2.3-70-g09d2


From 2de2e154912d95a15e5f890c9d1a3a7a11610107 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 29 Sep 2022 20:44:33 -0400
Subject: a bunch of changes to trails: link to trail to initiate trail when
 following link.  cleanly separate pin layout data vs. content data.

---
 src/client/documents/Documents.ts                  |   3 +
 src/client/util/CurrentUserUtils.ts                |   2 +-
 src/client/util/DocumentManager.ts                 |   2 +-
 src/client/util/type_decls.d                       |   3 +
 src/client/views/DocumentButtonBar.scss            |  22 ++-
 src/client/views/DocumentButtonBar.tsx             |  71 +++++++---
 src/client/views/DocumentDecorations.tsx           |   3 +-
 src/client/views/MainView.tsx                      |   1 +
 src/client/views/collections/TabDocView.tsx        |   2 +-
 src/client/views/collections/TreeView.tsx          |   2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   6 +-
 .../collectionFreeForm/MarqueeOptionsMenu.tsx      |  42 +++---
 .../collections/collectionFreeForm/MarqueeView.tsx |  12 +-
 .../collectionLinear/CollectionLinearView.tsx      |   2 +-
 src/client/views/nodes/DocumentView.tsx            |   4 +-
 src/client/views/nodes/ScriptingBox.tsx            |   5 +
 src/client/views/nodes/trails/PresBox.tsx          | 147 +++++++++------------
 src/client/views/nodes/trails/PresElementBox.tsx   |  66 ++++++---
 18 files changed, 225 insertions(+), 170 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index fb68fba38..4ca9972f8 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1398,6 +1398,9 @@ export namespace DocUtils {
                         heading: Doc.name,
                         checked: 'boolean',
                         containingTreeView: Doc.name,
+                        altKey: 'boolean',
+                        ctrlKey: 'boolean',
+                        shiftKey: 'boolean',
                     });
                 }
             });
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index fdac3c00a..6f9975be4 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -657,7 +657,7 @@ export class CurrentUserUtils {
                     CollectionViewType.Carousel3D, CollectionViewType.Linear, CollectionViewType.Map,
                     CollectionViewType.Grid, CollectionViewType.NoteTaking]),
               title: "Perspective",                    toolTip: "View",                 btnType: ButtonType.DropdownList,                                                                                    ignoreClick: true, width: 100, scripts: { script: 'setView(value, _readOnly_)'}},
-            { title: "Pin",     icon: "map-pin",       toolTip: "Pin View to Trail",    btnType: ButtonType.ClickButton,         funcs: {hidden: '!SelectionManager_selectedDocType(undefined, "tab")'},                        width: 20,  scripts: { onClick: 'pinWithView(_readOnly_)'}},
+            { title: "Pin",     icon: "map-pin",       toolTip: "Pin View to Trail",    btnType: ButtonType.ClickButton,         funcs: {hidden: '!SelectionManager_selectedDocType(undefined, "tab")'},                        width: 20,  scripts: { onClick: 'pinWithView(_readOnly_, altKey)'}},
             { title: "Back",    icon: "chevron-left",  toolTip: "Prev Animation Frame", btnType: ButtonType.ClickButton,         funcs: {hidden: '!SelectionManager_selectedDocType(undefined, "freeform") || IsNoviceMode()'}, width: 20,  scripts: { onClick: 'prevKeyFrame(_readOnly_)'}},
             { title: "Num",     icon: "",              toolTip: "Frame Number",         btnType: ButtonType.TextButton,          funcs: {hidden: '!SelectionManager_selectedDocType(undefined, "freeform") || IsNoviceMode()', buttonText: 'selectedDocs()?.lastElement()?.currentFrame.toString()'}, width: 20,  scripts: {}},
             { title: "Fwd",     icon: "chevron-right", toolTip: "Next Animation Frame", btnType: ButtonType.ClickButton,         funcs: {hidden: '!SelectionManager_selectedDocType(undefined, "freeform") || IsNoviceMode()'}, width: 20,  scripts: { onClick: 'nextKeyFrame(_readOnly_)'}},
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 50190061a..9a46d20de 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -244,7 +244,7 @@ export class DocumentManager {
                             res(ViewAdjustment.doNothing);
                         }),
                 });
-            if (focusView.props.Document.layoutKey === 'layout_icon') {
+            if (focusView.props.Document.layoutKey === 'layout_icon' && focusView.rootDoc.type !== DocumentType.SCRIPTING) {
                 focusView.iconify(() => doFocus(true));
             } else {
                 doFocus(false);
diff --git a/src/client/util/type_decls.d b/src/client/util/type_decls.d
index 9063dc894..1a93bbe59 100644
--- a/src/client/util/type_decls.d
+++ b/src/client/util/type_decls.d
@@ -67,6 +67,9 @@ interface RegExp {
     readonly sticky: boolean;
     readonly unicode: boolean;
 }
+interface Date {
+    now() : string;
+}
 interface String {
     codePointAt(pos: number): number | undefined;
     includes(searchString: string, position?: number): boolean;
diff --git a/src/client/views/DocumentButtonBar.scss b/src/client/views/DocumentButtonBar.scss
index a112f4745..1e93ba5e2 100644
--- a/src/client/views/DocumentButtonBar.scss
+++ b/src/client/views/DocumentButtonBar.scss
@@ -1,6 +1,6 @@
-@import "global/globalCssVariables";
+@import 'global/globalCssVariables';
 
-$linkGap : 3px;
+$linkGap: 3px;
 
 .documentButtonBar-linkFlyout {
     grid-column: 2/4;
@@ -18,6 +18,21 @@ $linkGap : 3px;
     cursor: pointer;
 }
 
+.documentButtonBar-pinTypes {
+    position: absolute;
+    display: flex;
+    width: 60px;
+    top: -14px;
+    background: black;
+    height: 20px;
+    align-items: center;
+}
+.documentButtonBar-pinIcon {
+    &:hover {
+        background-color: lightblue;
+    }
+}
+
 .documentButtonBar-linkButton-empty,
 .documentButtonBar-linkButton-nonempty {
     height: 20px;
@@ -99,7 +114,6 @@ $linkGap : 3px;
     transform: scale(1.05);
 }
 
-
 @-moz-keyframes spin {
     100% {
         -moz-transform: rotate(360deg);
@@ -127,4 +141,4 @@ $linkGap : 3px;
     100% {
         box-shadow: 0 0 0 10px rgba(0, 255, 0, 0);
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 0bfe6e87a..d42ff436f 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -5,8 +5,8 @@ import { action, computed, observable, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import { Doc } from '../../fields/Doc';
 import { RichTextField } from '../../fields/RichTextField';
-import { Cast, DocCast, NumCast } from '../../fields/Types';
-import { emptyFunction, returnFalse, setupMoveUpEvents, simulateMouseClick } from '../../Utils';
+import { Cast, NumCast } from '../../fields/Types';
+import { emptyFunction, setupMoveUpEvents, simulateMouseClick } from '../../Utils';
 import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
 import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils';
 import { Docs } from '../documents/Documents';
@@ -26,7 +26,6 @@ import { DashFieldView } from './nodes/formattedText/DashFieldView';
 import { GoogleRef } from './nodes/formattedText/FormattedTextBox';
 import { TemplateMenu } from './TemplateMenu';
 import React = require('react');
-import { DocumentType } from '../documents/DocumentTypes';
 const higflyout = require('@hig/flyout');
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -159,12 +158,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         })();
 
         return !targetDoc || !dataDoc || !dataDoc[GoogleRef] ? null : (
-            <Tooltip
-                title={
-                    <>
-                        <div className="dash-tooltip">{title}</div>
-                    </>
-                }>
+            <Tooltip title={<div className="dash-tooltip">{title}</div>}>
                 <div
                     className="documentButtonBar-button"
                     style={{ backgroundColor: this.pullColor }}
@@ -202,14 +196,12 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
                         size="sm"
                         style={{ WebkitAnimation: animation, MozAnimation: animation }}
                         icon={(() => {
+                            // prettier-ignore
                             switch (this.openHover) {
                                 default:
-                                case UtilityButtonState.Default:
-                                    return dataDoc.googleDocUnchanged === false ? (this.pullIcon as any) : fetch;
-                                case UtilityButtonState.OpenRight:
-                                    return 'arrow-alt-circle-right';
-                                case UtilityButtonState.OpenExternally:
-                                    return 'share';
+                                case UtilityButtonState.Default: return dataDoc.googleDocUnchanged === false ? (this.pullIcon as any) : fetch;
+                                case UtilityButtonState.OpenRight: return 'arrow-alt-circle-right';
+                                case UtilityButtonState.OpenExternally: return 'share';
                             }
                         })()}
                     />
@@ -231,21 +223,66 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
             </Tooltip>
         );
     }
+    @observable expandPin = false;
+    @observable subPin = '';
     @computed
     get pinButton() {
         const targetDoc = this.view0?.props.Document;
+        const pinBtn = (pinDocLayout: boolean, pinDocContent: boolean, icon: IconProp) => {
+            const tooltip = `Pin Document and Save ${this.subPin} to trail`;
+            return !tooltip ? null : (
+                <Tooltip title={<div className="dash-tooltip">{tooltip}</div>}>
+                    <div className="documentButtonBar-pinIcon">
+                        <FontAwesomeIcon
+                            className="documentdecorations-icon"
+                            style={{ width: 20 }}
+                            key={icon.toString()}
+                            size="sm"
+                            icon={icon}
+                            onPointerEnter={action(
+                                e =>
+                                    (this.subPin =
+                                        (pinDocLayout ? 'Layout' : '') +
+                                        (pinDocLayout && pinDocContent ? ' &' : '') +
+                                        (pinDocContent ? ' Content View' : '') +
+                                        (pinDocLayout && pinDocContent ? '(shift+alt)' : pinDocLayout ? '(shift)' : pinDocContent ? '(alt)' : ''))
+                            )}
+                            onPointerLeave={action(e => (this.subPin = ''))}
+                            onClick={e => {
+                                const docs = this.props
+                                    .views()
+                                    .filter(v => v)
+                                    .map(dv => dv!.rootDoc);
+                                TabDocView.PinDoc(docs, { pinDocLayout, pinDocContent, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null) });
+                                e.stopPropagation();
+                            }}
+                        />
+                    </div>
+                </Tooltip>
+            );
+        };
         return !targetDoc ? null : (
-            <Tooltip title={<div className="dash-tooltip">{SelectionManager.Views().length > 1 ? 'Pin multiple documents to trail (use shift to pin with view)' : 'Pin to trail (use shift to pin with view)'}</div>}>
+            <Tooltip title={<div className="dash-tooltip">{`Pin Document ${SelectionManager.Views().length > 1 ? 'multiple documents' : ''} to Trail`}</div>}>
                 <div
                     className="documentButtonBar-icon"
                     style={{ color: 'white' }}
+                    onPointerEnter={action(e => (this.expandPin = true))}
+                    onPointerLeave={action(e => (this.expandPin = false))}
                     onClick={e => {
                         const docs = this.props
                             .views()
                             .filter(v => v)
                             .map(dv => dv!.rootDoc);
-                        TabDocView.PinDoc(docs, { pinDocView: e.shiftKey, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null) });
+                        TabDocView.PinDoc(docs, { pinDocLayout: e.shiftKey, pinDocContent: e.altKey, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null) });
+                        e.stopPropagation();
                     }}>
+                    {this.expandPin ? (
+                        <div className="documentButtonBar-pinTypes">
+                            {pinBtn(true, false, 'window-maximize')}
+                            {pinBtn(false, true, 'address-card')}
+                            {pinBtn(true, true, 'id-card')}
+                        </div>
+                    ) : null}
                     <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin" />
                 </div>
             </Tooltip>
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 4675571c2..3e0de6d15 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -678,8 +678,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         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));
 
-        // Rotation constants: Only allow rotation on ink and images
-        const useRotation = seldoc.ComponentView instanceof InkingStroke || seldoc.ComponentView instanceof ImageBox || seldoc.ComponentView instanceof VideoBox;
+        const useRotation = true; // when do we want an object to not rotate?
         const rotation = NumCast(seldoc.rootDoc._jitterRotation);
 
         const resizerScheme = colorScheme ? 'documentDecorations-resizer' + colorScheme : '';
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 857a5522c..350883f70 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -303,6 +303,7 @@ export class MainView extends React.Component {
                 fa.faStop,
                 fa.faCalculator,
                 fa.faWindowMaximize,
+                fa.faIdCard,
                 fa.faAddressCard,
                 fa.faQuestionCircle,
                 fa.faArrowLeft,
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index b1f57f3fd..c4da70371 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -233,7 +233,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             pinDoc.presentationTargetDoc = doc;
             pinDoc.title = doc.title + ' - Slide';
             pinDoc.data = new List<Doc>(); // the children of the alias' layout are the presentation slide children.  the alias' data field might be children of a collection, PDF data, etc -- in any case we don't want the tree view to "see" this data
-            pinDoc.presMovement = pinProps?.pinDocView && !pinProps?.pinWithView ? PresMovement.None : PresMovement.Zoom;
+            pinDoc.presMovement = doc.type === DocumentType.SCRIPTING || pinProps?.pinDocLayout ? PresMovement.None : PresMovement.Zoom;
             pinDoc.groupWithUp = false;
             pinDoc.context = curPres;
             // these should potentially all be props passed down by the CollectionTreeView to the TreeView elements.  That way the PresBox could configure all of its children at render time
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index c34a6faaa..640984ad6 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -782,7 +782,7 @@ export class TreeView extends React.Component<TreeViewProps> {
 
     onChildDoubleClick = () => ScriptCast(this.props.treeView.Document.treeViewChildDoubleClick, !this.props.treeView.outlineMode ? this._openScript?.() : null);
 
-    refocus = () => this.props.treeView.props.focus(this.props.treeView.props.Document);
+    refocus = () => this.props.treeView.props.focus(this.props.treeView.props.Document, {});
     ignoreEvent = (e: any) => {
         if (this.props.isContentActive(true)) {
             e.stopPropagation();
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 7b6944e1e..8824c2b01 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1719,7 +1719,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             event: () => (this.Document._fitContentsToBox = !this.fitContentsToBox),
             icon: !this.fitContentsToBox ? 'expand-arrows-alt' : 'compress-arrows-alt',
         });
-        appearanceItems.push({ description: `Pin View`, event: () => TabDocView.PinDoc(this.rootDoc, { pinDocView: true, panelWidth: this.props.PanelWidth(), panelHeight: this.props.PanelHeight() }), icon: 'map-pin' });
+        appearanceItems.push({ description: `Pin View`, event: () => TabDocView.PinDoc(this.rootDoc, { pinViewport: MarqueeView.CurViewBounds(this.rootDoc, this.props.PanelWidth(), this.props.PanelHeight()) }), icon: 'map-pin' });
         //appearanceItems.push({ description: `update icon`, event: this.updateIcon, icon: "compress-arrows-alt" });
         this.props.ContainingCollectionView && appearanceItems.push({ description: 'Ungroup collection', event: this.promoteCollection, icon: 'table' });
 
@@ -2249,6 +2249,6 @@ ScriptingGlobals.add(function nextKeyFrame(readOnly: boolean) {
 ScriptingGlobals.add(function prevKeyFrame(readOnly: boolean) {
     !readOnly && (SelectionManager.Views()[0].ComponentView as CollectionFreeFormView)?.changeKeyFrame(true);
 });
-ScriptingGlobals.add(function pinWithView(readOnly: boolean) {
-    !readOnly && SelectionManager.Views().forEach(view => TabDocView.PinDoc(view.rootDoc, { pinDocView: true, panelWidth: view.props.PanelWidth(), panelHeight: view.props.PanelHeight() }));
+ScriptingGlobals.add(function pinWithView(readOnly: boolean, pinDocContent: boolean) {
+    !readOnly && SelectionManager.Views().forEach(view => TabDocView.PinDoc(view.rootDoc, { pinDocContent, pinViewport: MarqueeView.CurViewBounds(view.rootDoc, view.props.PanelWidth(), view.props.PanelHeight()) }));
 });
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
index 8a8b528f6..488f51d77 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
@@ -1,11 +1,11 @@
-import React = require("react");
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Tooltip } from "@material-ui/core";
-import { observer } from "mobx-react";
-import { unimplementedFunction } from "../../../../Utils";
-import { DocumentType } from "../../../documents/DocumentTypes";
-import { SelectionManager } from "../../../util/SelectionManager";
-import { AntimodeMenu, AntimodeMenuProps } from "../../AntimodeMenu";
+import React = require('react');
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Tooltip } from '@material-ui/core';
+import { observer } from 'mobx-react';
+import { unimplementedFunction } from '../../../../Utils';
+import { DocumentType } from '../../../documents/DocumentTypes';
+import { SelectionManager } from '../../../util/SelectionManager';
+import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu';
 
 @observer
 export class MarqueeOptionsMenu extends AntimodeMenu<AntimodeMenuProps> {
@@ -25,44 +25,34 @@ export class MarqueeOptionsMenu extends AntimodeMenu<AntimodeMenuProps> {
     }
 
     render() {
-        const presPinWithViewIcon = <img src="/assets/pinWithView.png" style={{ margin: "auto", width: 19, transform: 'translate(-2px, -2px)' }} />;
+        const presPinWithViewIcon = <img src="/assets/pinWithView.png" style={{ margin: 'auto', width: 19, transform: 'translate(-2px, -2px)' }} />;
         const buttons = [
             <Tooltip key="collect" title={<div className="dash-tooltip">Create a Collection</div>} placement="bottom">
-                <button
-                    className="antimodeMenu-button"
-                    onPointerDown={this.createCollection}>
+                <button className="antimodeMenu-button" onPointerDown={this.createCollection}>
                     <FontAwesomeIcon icon="object-group" size="lg" />
                 </button>
             </Tooltip>,
             <Tooltip key="group" title={<div className="dash-tooltip">Create a Grouping</div>} placement="bottom">
-                <button
-                    className="antimodeMenu-button"
-                    onPointerDown={e => this.createCollection(e, true)}>
+                <button className="antimodeMenu-button" onPointerDown={e => this.createCollection(e, true)}>
                     <FontAwesomeIcon icon="layer-group" size="lg" />
                 </button>
             </Tooltip>,
             <Tooltip key="summarize" title={<div className="dash-tooltip">Summarize Documents</div>} placement="bottom">
-                <button
-                    className="antimodeMenu-button"
-                    onPointerDown={this.summarize}>
+                <button className="antimodeMenu-button" onPointerDown={this.summarize}>
                     <FontAwesomeIcon icon="compress-arrows-alt" size="lg" />
                 </button>
             </Tooltip>,
             <Tooltip key="delete" title={<div className="dash-tooltip">Delete Documents</div>} placement="bottom">
-                <button
-                    className="antimodeMenu-button"
-                    onPointerDown={this.delete}>
+                <button className="antimodeMenu-button" onPointerDown={this.delete}>
                     <FontAwesomeIcon icon="trash-alt" size="lg" />
                 </button>
             </Tooltip>,
-            <Tooltip key="pinWithView" title={<div className="dash-tooltip">Pin with selected region</div>} placement="bottom">
-                <button
-                    className="antimodeMenu-button"
-                    onPointerDown={this.pinWithView}>
+            <Tooltip key="pinWithView" title={<div className="dash-tooltip">Pin selected region to trail</div>} placement="bottom">
+                <button className="antimodeMenu-button" onPointerDown={this.pinWithView}>
                     {presPinWithViewIcon}
                 </button>
             </Tooltip>,
         ];
         return this.getElement(buttons);
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 584c9690f..a020b67cd 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -18,7 +18,7 @@ import { Transform } from '../../../util/Transform';
 import { undoBatch, UndoManager } from '../../../util/UndoManager';
 import { ContextMenu } from '../../ContextMenu';
 import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
-import { PinViewProps, PresBox } from '../../nodes/trails/PresBox';
+import { PresBox } from '../../nodes/trails/PresBox';
 import { VideoBox } from '../../nodes/VideoBox';
 import { pasteImageBitmap } from '../../nodes/WebBoxRenderer';
 import { PreviewCursor } from '../../PreviewCursor';
@@ -61,6 +61,11 @@ export interface MarqueeViewBounds {
 
 @observer
 export class MarqueeView extends React.Component<SubCollectionViewProps & MarqueeViewProps> {
+    public static CurViewBounds(pinDoc: Doc, panelWidth: number, panelHeight: number) {
+        const ps = NumCast(pinDoc._viewScale, 1);
+        return { left: NumCast(pinDoc._panX) - panelWidth / 2 / ps, top: NumCast(pinDoc._panY) - panelHeight / 2 / ps, width: panelWidth / ps, height: panelHeight / ps };
+    }
+
     private _commandExecuted = false;
     @observable _lastX: number = 0;
     @observable _lastY: number = 0;
@@ -426,10 +431,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
     @action
     pinWithView = async () => {
         const doc = this.props.Document;
-        const viewOptions: PinViewProps = {
-            bounds: this.Bounds,
-        };
-        TabDocView.PinDoc(doc, { pinWithView: viewOptions, pinDocView: true });
+        TabDocView.PinDoc(doc, { pinViewport: this.Bounds });
         MarqueeOptionsMenu.Instance.fadeOut(true);
         this.hideMarquee();
     };
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index f6eb2fce4..92f6bbb64 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -208,7 +208,7 @@ export class CollectionLinearView extends CollectionSubView() {
                         checked={BoolCast(this.props.Document.linearViewIsExpanded)}
                         ref={this.addMenuToggle}
                         onChange={action(e => {
-                            ScriptCast(this.Document.onClick).script.run({
+                            ScriptCast(this.Document.onClick)?.script.run({
                                 this: this.layoutDoc,
                                 self: this.rootDoc,
                                 _readOnly_: false,
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index ba061ce8f..913d5a7ef 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -577,6 +577,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                                 documentView: this.props.DocumentView(),
                                 clientX,
                                 clientY,
+                                altKey,
                                 shiftKey,
                             },
                             console.log
@@ -589,7 +590,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                 }
             } else if (this.onClickHandler?.script && !isScriptBox()) {
                 // bcz: hack? don't execute script if you're clicking on a scripting box itself
-                const { clientX, clientY, shiftKey } = e;
+                const { clientX, clientY, shiftKey, altKey } = e;
                 const func = () =>
                     this.onClickHandler.script.run(
                         {
@@ -602,6 +603,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                             clientX,
                             clientY,
                             shiftKey,
+                            altKey,
                         },
                         console.log
                     ).result?.select === true
diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx
index 1c9b0bc0e..37afcdd8b 100644
--- a/src/client/views/nodes/ScriptingBox.tsx
+++ b/src/client/views/nodes/ScriptingBox.tsx
@@ -115,6 +115,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
 
     @action
     componentDidMount() {
+        this.props.setContentView?.(this);
         this.rawText = this.rawScript;
         const observer = new _global.ResizeObserver(
             action((entries: any) => {
@@ -480,6 +481,10 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
         return value;
     }
 
+    scrollFocus = () => {
+        return undefined;
+    };
+
     getSuggestedParams(pos: number) {
         const firstScript = this.rawText.slice(0, pos);
         const indexP = firstScript.lastIndexOf('.');
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 0c4d514cd..18441aace 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -31,19 +31,16 @@ import { CollectionFreeFormDocumentView } from '../CollectionFreeFormDocumentVie
 import { FieldView, FieldViewProps } from '../FieldView';
 import './PresBox.scss';
 import { PresEffect, PresMovement, PresStatus } from './PresEnums';
+import { privateEncrypt } from 'crypto';
+import { ScriptingBox } from '../ScriptingBox';
 
 export interface PinProps {
     audioRange?: boolean;
     activeFrame?: number;
     hidePresBox?: boolean;
-    pinWithView?: PinViewProps;
-    pinDocView?: boolean; // whether the current view specs of the document should be saved the pinned document
-    panelWidth?: number; // panel width and height of the document (used to compute the bounds of the pinned view area)
-    panelHeight?: number;
-}
-
-export interface PinViewProps {
-    bounds: MarqueeViewBounds;
+    pinViewport?: MarqueeViewBounds; // pin a specific viewport on a freeform view (use MarqueeView.CurViewBounds to compute if no region has been selected)
+    pinDocLayout?: boolean; // pin layout info (width/height/x/y)
+    pinDocContent?: boolean; // pin data info (scroll/pan/zoom/text)
 }
 
 @observer
@@ -268,6 +265,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             // Case 3: Last slide and presLoop is toggled ON or it is in Edit mode
             this.nextSlide(0);
         }
+        return this.itemIndex;
     };
 
     // Called when the user activates 'back' - to move to the previous part of the pres. trail
@@ -298,6 +296,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             // Case 3: Pres loop is on so it should go to the last slide
             this.gotoDocument(this.childDocs.length - 1, activeItem);
         }
+        return this.itemIndex;
     };
 
     //The function that is called when a document is clicked or reached through next or back.
@@ -351,7 +350,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         const pannable = [DocumentType.IMG].includes(target.type as any) || (target.type === DocumentType.COL && target._viewType === CollectionViewType.Freeform);
         const temporal = [DocumentType.AUDIO, DocumentType.VID].includes(target.type as any);
         const clippable = [DocumentType.COMPARISON].includes(target.type as any);
-        const dataview = [DocumentType.INK].includes(target.type as any) && target.activeFrame === undefined;
+        const dataview = [DocumentType.INK, DocumentType.COL].includes(target.type as any) && target.activeFrame === undefined;
         const textview = [DocumentType.RTF].includes(target.type as any) && target.activeFrame === undefined;
         return { scrollable, pannable, temporal, clippable, dataview, textview };
     }
@@ -383,7 +382,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 const dv = DocumentManager.Instance.getDocumentView(bestTarget);
                 if (dv) {
                     const computedScale = NumCast(activeItem.presZoom, 1) * Math.min(dv.props.PanelWidth() / viewport.width, dv.props.PanelHeight() / viewport.height);
-                    activeItem.presMovement === 'zoom' && (bestTarget._viewScale = activeItem.presZoom !== undefined ? computedScale : Math.min(computedScale, NumCast(bestTarget._viewScale)));
+                    activeItem.presMovement === 'zoom' && (bestTarget._viewScale = computedScale);
                     dv.ComponentView?.brushView?.(viewport);
                 }
             } else {
@@ -400,47 +399,40 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     /// target doc when navigating to it.
     @action
     static pinDocView(pinDoc: Doc, pinProps: PinProps | undefined, targetDoc: Doc) {
-        if (pinProps?.pinWithView) {
-            // If pinWithView option set then update scale and x / y props of slide
-            const bounds = pinProps.pinWithView.bounds;
-            pinDoc.presPinView = true;
-            pinDoc.presPinViewX = bounds.left + bounds.width / 2;
-            pinDoc.presPinViewY = bounds.top + bounds.height / 2;
-            pinDoc.presPinViewBounds = new List<number>([bounds.left, bounds.top, bounds.left + bounds.width, bounds.top + bounds.height]);
-        }
-        if (pinProps?.pinDocView) {
-            const { scrollable, pannable, temporal, clippable, dataview, textview } = this.pinDataTypes(pinDoc);
-            pinDoc.presPinView = (pinProps?.pinWithView ? true : false) || scrollable || temporal || pannable || clippable || dataview || textview || pinProps.activeFrame !== undefined;
+        const { scrollable, pannable, temporal, clippable, dataview, textview } = this.pinDataTypes(pinDoc);
+        if (pinProps?.pinDocLayout) {
+            pinDoc.presPinLayout = true;
             pinDoc.presX = NumCast(targetDoc.x);
             pinDoc.presY = NumCast(targetDoc.y);
             pinDoc.presRot = NumCast(targetDoc.jitterRotation);
             pinDoc.presWidth = NumCast(targetDoc.width);
             pinDoc.presHeight = NumCast(targetDoc.height);
-
-            if (scrollable) {
-                pinDoc.presPinViewScroll = pinDoc._scrollTop;
-            }
+        }
+        if (pinProps?.pinDocContent) {
+            pinDoc.presPinData = scrollable || temporal || pannable || clippable || dataview || textview || pinProps.activeFrame !== undefined;
+            if (textview) pinDoc.presData = targetDoc.text instanceof ObjectField ? targetDoc.text[Copy]() : targetDoc.text;
+            if (scrollable) pinDoc.presPinViewScroll = pinDoc._scrollTop;
             if (clippable) pinDoc.presPinClipWidth = pinDoc._clipWidth;
+            if (dataview) pinDoc.presData = targetDoc.data instanceof ObjectField ? targetDoc.data[Copy]() : targetDoc.data;
+            if (pannable) {
+                pinDoc.presPinViewX = NumCast(pinDoc._panX);
+                pinDoc.presPinViewY = NumCast(pinDoc._panY);
+                pinDoc.presPinViewScale = NumCast(pinDoc._viewScale, 1);
+            }
             if (temporal) {
                 pinDoc.presStartTime = pinDoc._currentTimecode;
                 const duration = NumCast(pinDoc[`${Doc.LayoutFieldKey(pinDoc)}-duration`], NumCast(pinDoc.presStartTime) + 0.1);
                 pinDoc.presEndTime = NumCast(pinDoc.clipEnd, duration);
             }
-            if (textview) pinDoc.presData = targetDoc.text instanceof ObjectField ? targetDoc.text[Copy]() : targetDoc.text;
-            if (dataview) pinDoc.presData = targetDoc.data instanceof ObjectField ? targetDoc.data[Copy]() : targetDoc.data;
-            if (pannable || scrollable) {
-                const panX = NumCast(pinDoc._panX);
-                const panY = NumCast(pinDoc._panY);
-                const pw = NumCast(pinProps.panelWidth);
-                const ph = NumCast(pinProps.panelHeight);
-                const ps = NumCast(pinDoc._viewScale, 1);
-                if (pw && ph && ps) {
-                    pinDoc.presPinViewBounds = new List<number>([panX - pw / 2 / ps, panY - ph / 2 / ps, panX + pw / 2 / ps, panY + ph / 2 / ps]);
-                }
-                pinDoc.presPinViewX = panX;
-                pinDoc.presPinViewY = panY;
-                pinDoc.presPinViewScale = ps;
-            }
+        }
+        if (pinProps?.pinViewport) {
+            // If pinWithView option set then update scale and x / y props of slide
+            const bounds = pinProps.pinViewport;
+            pinDoc.presPinView = true;
+            pinDoc.presPinViewScale = NumCast(pinDoc._viewScale, 1);
+            pinDoc.presPinViewX = bounds.left + bounds.width / 2;
+            pinDoc.presPinViewY = bounds.top + bounds.height / 2;
+            pinDoc.presPinViewBounds = new List<number>([bounds.left, bounds.top, bounds.left + bounds.width, bounds.top + bounds.height]);
         }
     }
 
@@ -497,7 +489,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     };
 
     static NavigateToTarget(targetDoc: Doc, activeItem: Doc, openInTab: any, srcContext: Doc, finished?: () => void) {
-        if (activeItem.presPinView && DocCast(targetDoc.context)?._currentFrame === undefined) {
+        if ((activeItem.presPinLayout || activeItem.presPinView) && DocCast(targetDoc.context)?._currentFrame === undefined) {
             const transTime = NumCast(activeItem.presTransition, 500);
             const presTransitionTime = `all ${transTime}ms`;
             targetDoc._dataTransition = presTransitionTime;
@@ -514,11 +506,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         } else if (targetDoc && activeItem.presMovement !== PresMovement.None) {
             LightboxView.SetLightboxDoc(undefined);
             const zooming = activeItem.presMovement !== PresMovement.Pan;
-            DocumentManager.Instance.jumpToDocument(targetDoc, zooming, openInTab, srcContext ? [srcContext] : [], undefined, undefined, undefined, finished, undefined, true, NumCast(activeItem.presZoom));
+            DocumentManager.Instance.jumpToDocument(targetDoc, zooming, openInTab, srcContext ? [srcContext] : [], undefined, undefined, undefined, finished, undefined, true, NumCast(activeItem.presZoom, 1));
+        } else if (activeItem.presMovement === PresMovement.None && targetDoc.type === DocumentType.SCRIPTING) {
+            (DocumentManager.Instance.getFirstDocumentView(targetDoc)?.ComponentView as ScriptingBox)?.onRun?.();
         }
         // After navigating to the document, if it is added as a presPinView then it will
         // adjust the pan and scale to that of the pinView when it was added.
-        if (activeItem.presPinView) {
+        if (activeItem.presPinData || activeItem.presPinView) {
             clearTimeout(PresBox._navTimer);
             // targetDoc may or may not be displayed.  this gets the first available document (or alias) view that matches targetDoc
             const bestTarget = DocumentManager.Instance.getFirstDocumentView(targetDoc)?.props.Document;
@@ -615,42 +609,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     //The function that starts or resets presentaton functionally, depending on presStatus of the layoutDoc
     @action
     startAutoPres = (startSlide: number) => {
-        this.updateCurrentPresentation();
-        let activeItem: Doc = this.activeItem;
-        let targetDoc: Doc = this.targetDoc;
-        let duration = NumCast(activeItem.presDuration) + NumCast(activeItem.presTransition);
-        const timer = (ms: number) => new Promise(res => (this._presTimer = setTimeout(res, ms)));
-        const load = async () => {
-            // Wrap the loop into an async function for this to work
-            for (var i = startSlide; i < this.childDocs.length; i++) {
-                activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
-                targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
-                duration = NumCast(activeItem.presDuration) + NumCast(activeItem.presTransition);
-                if (duration < 100) {
-                    duration = 2500;
-                }
-                if (NumCast(targetDoc.lastFrame) > 0) {
-                    for (var f = 0; f < NumCast(targetDoc.lastFrame); f++) {
-                        await timer(duration / NumCast(targetDoc.lastFrame));
-                        this.next();
-                    }
-                }
-
-                await timer(duration);
-                this.next(); // then the created Promise can be awaited
-                if (i === this.childDocs.length - 1) {
-                    setTimeout(() => {
-                        clearTimeout(this._presTimer);
-                        if (this.layoutDoc.presStatus === 'auto' && !this.layoutDoc.presLoop) this.layoutDoc.presStatus = PresStatus.Manual;
-                        else if (this.layoutDoc.presLoop) this.startAutoPres(0);
-                    }, duration);
-                }
-            }
-        };
         this.layoutDoc.presStatus = PresStatus.Autoplay;
         this.startPresentation(startSlide);
-        this.gotoDocument(startSlide, activeItem);
-        load();
+        clearTimeout(this._presTimer);
+        const func = (itemIndex: number) => {
+            if (itemIndex === this.next()) this.layoutDoc.presStatus = PresStatus.Manual;
+            else
+                this._presTimer = setTimeout(
+                    () => this.layoutDoc.presStatus !== PresStatus.Manual && func(this.itemIndex),
+                    NumCast(this.activeItem.presDuration, this.activeItem.type === DocumentType.SCRIPTING ? 0 : 2500) + NumCast(this.activeItem.presTransition)
+                );
+        };
+
+        func(this.itemIndex);
     };
 
     // The function pauses the auto presentation
@@ -659,7 +630,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         if (this.layoutDoc.presStatus === PresStatus.Autoplay) {
             if (this._presTimer) clearTimeout(this._presTimer);
             this.layoutDoc.presStatus = PresStatus.Manual;
-            this.layoutDoc.presLoop = false;
             this.childDocs.forEach(this.stopTempMedia);
         }
     };
@@ -667,7 +637,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     //The function that resets the presentation by removing every action done by it. It also
     //stops the presentaton.
     resetPresentation = () => {
-        this.rootDoc._itemIndex = 0;
         this.childDocs
             .map(doc => Cast(doc.presentationTargetDoc, Doc, null))
             .filter(doc => doc instanceof Doc)
@@ -706,8 +675,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
      * @param startIndex: index that the presentation will start at
      */
     startPresentation = (startIndex: number) => {
-        this.updateCurrentPresentation();
-        this.childDocs.map(doc => {
+        this.childDocs.forEach(doc => {
             const tagDoc = doc.presentationTargetDoc as Doc;
             if (doc.presHideBefore && this.childDocs.indexOf(doc) > startIndex) {
                 tagDoc.opacity = 0;
@@ -716,6 +684,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 tagDoc.opacity = 0;
             }
         });
+        this.gotoDocument(startIndex, this.activeItem);
     };
 
     /**
@@ -996,7 +965,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 break;
             case 'Spacebar':
             case ' ':
-                if (this.layoutDoc.presStatus === PresStatus.Manual) this.startAutoPres(this.itemIndex);
+                if (this.layoutDoc.presStatus === PresStatus.Manual) this.startOrPause(true);
                 else if (this.layoutDoc.presStatus === PresStatus.Autoplay) if (this._presTimer) clearTimeout(this._presTimer);
                 handled = true;
                 break;
@@ -1254,7 +1223,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         if (activeItem && targetDoc) {
             const type = targetDoc.type;
             const transitionSpeed = activeItem.presTransition ? NumCast(activeItem.presTransition) / 1000 : 0.5;
-            const zoom = activeItem.presZoom ? NumCast(activeItem.presZoom) * 100 : 75;
+            const zoom = NumCast(activeItem.presZoom, 1) * 100;
             let duration = activeItem.presDuration ? NumCast(activeItem.presDuration) / 1000 : 2;
             if (activeItem.type === DocumentType.AUDIO) duration = NumCast(activeItem.duration);
             const effect = this.activeItem.presEffect ? this.activeItem.presEffect : 'None';
@@ -1808,6 +1777,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         );
     }
 
+    scrollFocus = () => {
+        this.startOrPause(false);
+        return undefined;
+    };
+
     // Case in which the document has keyframes to navigate to next key frame
     @action
     nextKeyframe = (tagDoc: Doc, curDoc: Doc): void => {
@@ -2480,7 +2454,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     <FontAwesomeIcon icon={'arrow-left'} />
                 </div>
                 <Tooltip title={<div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? 'Pause' : 'Autoplay'}</div>}>
-                    <div className="presPanel-button" onClick={this.startOrPause}>
+                    <div className="presPanel-button" onClick={e => this.startOrPause(true)}>
                         <FontAwesomeIcon icon={this.layoutDoc.presStatus === PresStatus.Autoplay ? 'pause' : 'play'} />
                     </div>
                 </Tooltip>
@@ -2529,7 +2503,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     }
 
     @action
-    startOrPause = () => {
+    startOrPause = (makeActive = true) => {
+        makeActive && this.updateCurrentPresentation();
         if (this.layoutDoc.presStatus === PresStatus.Manual || this.layoutDoc.presStatus === PresStatus.Edit) this.startAutoPres(this.itemIndex);
         else this.pauseAutoPres();
     };
@@ -2613,7 +2588,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         <FontAwesomeIcon icon={'arrow-left'} />
                     </div>
                     <Tooltip title={<div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? 'Pause' : 'Autoplay'}</div>}>
-                        <div className="presPanel-button" onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, this.startOrPause, false, false)}>
+                        <div className="presPanel-button" onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, () => this.startOrPause(true), false, false)}>
                             <FontAwesomeIcon icon={this.layoutDoc.presStatus === 'auto' ? 'pause' : 'play'} />
                         </div>
                     </Tooltip>
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index e6d08cd53..fe2668492 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -26,6 +26,7 @@ import { PresMovement } from './PresEnums';
 import React = require('react');
 import { InkField } from '../../../../fields/InkField';
 import { RichTextField } from '../../../../fields/RichTextField';
+import { MarqueeView } from '../../collections/collectionFreeForm';
 /**
  * This class models the view a document added to presentation will have in the presentation.
  * It involves some functionality for its buttons and options.
@@ -142,7 +143,6 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     this.presExpandDocumentClick();
                 }}>
                 <div className="presItem-groupNum">{`${ind + 1}.`}</div>
-                {/* style={{ maxWidth: showMore ? (toolbarWidth - 195) : toolbarWidth - 105, cursor: isSelected ? 'text' : 'grab' }} */}
                 <div className="presItem-name">
                     <EditableView
                         ref={this._titleRef}
@@ -304,7 +304,22 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
      */
     @undoBatch
     @action
-    updateView = (targetDoc: Doc, activeItem: Doc) => {
+    updateCapturedContainerLayout = (targetDoc: Doc, activeItem: Doc) => {
+        activeItem.presX = NumCast(targetDoc.x);
+        activeItem.presY = NumCast(targetDoc.y);
+        activeItem.presRot = NumCast(targetDoc.jitterRotation);
+        activeItem.presWidth = NumCast(targetDoc.width);
+        activeItem.presHeight = NumCast(targetDoc.height);
+    };
+    /**
+     * Method called for updating the view of the currently selected document
+     *
+     * @param targetDoc
+     * @param activeItem
+     */
+    @undoBatch
+    @action
+    updateCapturedViewContents = (targetDoc: Doc, activeItem: Doc) => {
         switch (targetDoc.type) {
             case DocumentType.PDF:
             case DocumentType.WEB:
@@ -326,20 +341,22 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 const clipWidth = targetDoc._clipWidth;
                 activeItem.presPinClipWidth = clipWidth;
                 break;
+            case DocumentType.COL:
             default:
-                const x = targetDoc._panX;
-                const y = targetDoc._panY;
-                const scale = targetDoc._viewScale;
-                activeItem.presPinViewX = x;
-                activeItem.presPinViewY = y;
-                activeItem.presPinViewScale = scale;
+                const bestView = DocumentManager.Instance.getFirstDocumentView(targetDoc);
+                if (activeItem.presPinViewBounds && bestView) {
+                    const bounds = MarqueeView.CurViewBounds(targetDoc, bestView.props.PanelWidth(), bestView.props.PanelHeight());
+                    activeItem.presPinView = true;
+                    activeItem.presPinViewScale = NumCast(targetDoc._viewScale, 1);
+                    activeItem.presPinViewX = bounds.left + bounds.width / 2;
+                    activeItem.presPinViewY = bounds.top + bounds.height / 2;
+                    activeItem.presPinViewBounds = new List<number>([bounds.left, bounds.top, bounds.left + bounds.width, bounds.top + bounds.height]);
+                } else {
+                    activeItem.presPinViewX = targetDoc._panX;
+                    activeItem.presPinViewY = targetDoc._panY;
+                    activeItem.presPinViewScale = targetDoc._viewScale;
+                }
         }
-
-        activeItem.presX = NumCast(targetDoc.x);
-        activeItem.presY = NumCast(targetDoc.y);
-        activeItem.presRot = NumCast(targetDoc.jitterRotation);
-        activeItem.presWidth = NumCast(targetDoc.width);
-        activeItem.presHeight = NumCast(targetDoc.height);
     };
 
     @computed get recordingIsInOverlay() {
@@ -506,16 +523,23 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         {/* <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
+                            <Tooltip title={<div className="dash-tooltip">Update captured doc layout</div>}>
+                                <div className="slideButton" onClick={() => this.updateCapturedContainerLayout(targetDoc, activeItem)} style={{ fontWeight: 700, display: activeItem.presPinLayout ? 'flex' : 'none' }}>
+                                    L
                                 </div>
                             </Tooltip>
-                            {!Doc.noviceMode && <Tooltip title={<div className="dash-tooltip">{this.recordingIsInOverlay ? 'Hide Recording' : `${PresElementBox.videoIsRecorded(activeItem) ? 'Show' : 'Start'} recording`}</div>}>
-                                <div className="slideButton" onClick={e => (this.recordingIsInOverlay ? this.hideRecording(e, true) : this.startRecording(e, activeItem))} style={{ fontWeight: 700 }}>
-                                    <FontAwesomeIcon icon={`video${this.recordingIsInOverlay ? '-slash' : ''}`} onPointerDown={e => e.stopPropagation()} />
+                            <Tooltip title={<div className="dash-tooltip">Update captured doc content</div>}>
+                                <div className="slideButton" onClick={() => this.updateCapturedViewContents(targetDoc, activeItem)} style={{ fontWeight: 700, display: activeItem.presPinData || activeItem.presPinView ? 'flex' : 'none' }}>
+                                    C
                                 </div>
-                            </Tooltip>}
+                            </Tooltip>
+                            {!Doc.noviceMode && (
+                                <Tooltip title={<div className="dash-tooltip">{this.recordingIsInOverlay ? 'Hide Recording' : `${PresElementBox.videoIsRecorded(activeItem) ? 'Show' : 'Start'} recording`}</div>}>
+                                    <div className="slideButton" onClick={e => (this.recordingIsInOverlay ? this.hideRecording(e, true) : this.startRecording(e, activeItem))} style={{ fontWeight: 700 }}>
+                                        <FontAwesomeIcon icon={`video${this.recordingIsInOverlay ? '-slash' : ''}`} onPointerDown={e => e.stopPropagation()} />
+                                    </div>
+                                </Tooltip>
+                            )}
                             <Tooltip title={<div className="dash-tooltip">{activeItem.groupWithUp ? 'Ungroup' : 'Group with up'}</div>}>
                                 <div
                                     className="slideButton"
-- 
cgit v1.2.3-70-g09d2


From 8e8cca45755426e2921e2de78556ad60d79a98a8 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 4 Oct 2022 11:54:55 -0400
Subject: fix to show close and open icons of hideResizers documents. fixes for
 native size control of text and freeform collections.  fixes for lightbox
 view of native size collections.   fix for 'false' script.

---
 src/client/documents/Documents.ts                  |  1 +
 src/client/views/DocumentDecorations.tsx           | 24 ++++++++++------------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  5 ++++-
 src/fields/Doc.ts                                  |  6 ++++++
 src/fields/ScriptField.ts                          |  2 +-
 5 files changed, 23 insertions(+), 15 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index fb68fba38..cd647f5e8 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -396,6 +396,7 @@ export namespace Docs {
                         _yMargin: 10,
                         nativeDimModifiable: true,
                         treeViewGrowsHorizontally: true,
+                        nativeHeightUnfrozen: true,
                         forceReflow: true,
                         links: '@links(self)',
                     },
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 4675571c2..d5db45494 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -1,8 +1,10 @@
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Tooltip } from '@material-ui/core';
+import { IconButton } from 'browndash-components';
 import { action, computed, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
+import { FaUndo } from 'react-icons/fa';
 import { DateField } from '../../fields/DateField';
 import { AclAdmin, AclEdit, DataSym, Doc, DocListCast, Field, HeightSym, WidthSym } from '../../fields/Doc';
 import { Document } from '../../fields/documentSchemas';
@@ -28,10 +30,8 @@ import { LightboxView } from './LightboxView';
 import { DocumentView } from './nodes/DocumentView';
 import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
 import { ImageBox } from './nodes/ImageBox';
-import React = require('react');
-import { IconButton } from 'browndash-components';
-import { FaUndo } from 'react-icons/fa';
 import { VideoBox } from './nodes/VideoBox';
+import React = require('react');
 
 @observer
 export class DocumentDecorations extends React.Component<{ PanelWidth: number; PanelHeight: number; boundsLeft: number; boundsTop: number }, { value: string }> {
@@ -503,7 +503,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                     }
                     let actualdW = Math.max(width + dW * scale, 20);
                     let actualdH = Math.max(height + dH * scale, 20);
-                    const fixedAspect = nwidth && nheight && (!doc._fitWidth || e.ctrlKey || doc.nativeHeightUnfrozen);
+                    const fixedAspect = nwidth && nheight && (!doc._fitWidth || e.ctrlKey || doc.nativeHeightUnfrozen || doc.nativeDimModifiable);
                     if (fixedAspect) {
                         if ((Math.abs(dW) > Math.abs(dH) && ((!dragBottom && !dragTop) || !modifyNativeDim)) || dragRight) {
                             if (dragRight && modifyNativeDim) {
@@ -534,7 +534,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                             } else doc._height = actualdH;
                         }
                     } else {
-                        const maxHeight = 0; //Math.max(nheight, NumCast(doc.scrollHeight, NumCast(doc[docView.LayoutFieldKey + '-scrollHeight']))) * docView.NativeDimScaling();
+                        const maxHeight = doc.nativHeightUnfrozen || !nheight ? 0 : Math.max(nheight, NumCast(doc.scrollHeight, NumCast(doc[docView.LayoutFieldKey + '-scrollHeight']))) * docView.NativeDimScaling();
                         dH && (doc._height = actualdH > maxHeight && maxHeight ? maxHeight : actualdH);
                         dW && (doc._width = actualdW);
                         dH && (doc._autoHeight = false);
@@ -722,14 +722,12 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                                 width: bounds.r - bounds.x + this._resizeBorderWidth + 'px',
                                 height: bounds.b - bounds.y + this._resizeBorderWidth + this._titleHeight + 'px',
                             }}>
-                            {hideResizers ? null : (
-                                <div className="documentDecorations-topbar">
-                                    {hideDeleteButton ? <div /> : topBtn('close', 'times', undefined, e => this.onCloseClick(true), 'Close')}
-                                    {hideDeleteButton ? <div /> : topBtn('minimize', 'window-maximize', undefined, e => this.onCloseClick(undefined), 'Minimize')}
-                                    {titleArea}
-                                    {hideOpenButton ? null : topBtn('open', 'external-link-alt', this.onMaximizeDown, undefined, 'Open in Tab (ctrl: as alias, shift: in new collection)')}
-                                </div>
-                            )}
+                            <div className="documentDecorations-topbar">
+                                {hideDeleteButton ? <div /> : topBtn('close', 'times', undefined, e => this.onCloseClick(true), 'Close')}
+                                {hideResizers || hideDeleteButton ? <div /> : topBtn('minimize', 'window-maximize', undefined, e => this.onCloseClick(undefined), 'Minimize')}
+                                {hideResizers ? <div /> : titleArea}
+                                {hideOpenButton ? <div /> : topBtn('open', 'external-link-alt', this.onMaximizeDown, undefined, 'Open in Lightbox (ctrl: as alias, shift: in new collection)')}
+                            </div>
                             {hideResizers ? null : (
                                 <>
                                     <div key="tl" className={`documentDecorations-topLeftResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={e => e.preventDefault()} />
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 7b6944e1e..93bf143df 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -156,7 +156,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     }
     @computed get cachedCenteringShiftY(): number {
         const scaling = this.fitContentsToBox || !this.nativeDimScaling ? 1 : this.nativeDimScaling;
-        return this.props.isAnnotationOverlay ? 0 : this.props.PanelHeight() / 2 / scaling; // shift so pan position is at center of window for non-overlay collections
+        // if freeform has a native aspect, then the panel height needs to be adjusted to match it
+        const aspect = this.props.DocumentView?.().nativeHeight ? this.props.DocumentView?.().nativeHeight / this.props.DocumentView?.().nativeWidth : 1;
+        return this.props.isAnnotationOverlay ? 0 : (aspect * this.props.PanelHeight()) / 2 / scaling; // shift so pan position is at center of window for non-overlay collections
     }
     @computed get cachedGetLocalTransform(): Transform {
         return Transform.Identity()
@@ -190,6 +192,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     onChildDoubleClickHandler = () => this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick);
     elementFunc = () => this._layoutElements;
     shrinkWrap = () => {
+        if (this.props.DocumentView?.().nativeWidth) return;
         const vals = this.fitToContentVals;
         this.layoutDoc._panX = vals.bounds.cx;
         this.layoutDoc._panY = vals.bounds.cy;
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index ea3c122a4..0ceaff968 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1402,11 +1402,17 @@ export namespace Doc {
                 layoutDoc._viewScale = NumCast(layoutDoc._viewScale, 1) * contentScale;
                 layoutDoc._nativeWidth = undefined;
                 layoutDoc._nativeHeight = undefined;
+                layoutDoc._forceReflow = undefined;
+                layoutDoc._nativeHeightUnfrozen = undefined;
+                layoutDoc._nativeDimModifiable = undefined;
             } else {
                 layoutDoc._autoHeight = false;
                 if (!Doc.NativeWidth(layoutDoc)) {
                     layoutDoc._nativeWidth = NumCast(layoutDoc._width, panelWidth);
                     layoutDoc._nativeHeight = NumCast(layoutDoc._height, panelHeight);
+                    layoutDoc._forceReflow = true;
+                    layoutDoc._nativeHeightUnfrozen = true;
+                    layoutDoc._nativeDimModifiable = true;
                 }
             }
         });
diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts
index 3cb50a4c0..4896c027d 100644
--- a/src/fields/ScriptField.ts
+++ b/src/fields/ScriptField.ts
@@ -104,7 +104,7 @@ export class ScriptField extends ObjectField {
         }
         this.rawscript = rawscript;
         this.setterscript = setterscript;
-        this.script = script ?? (CompileScript('false') as CompiledScript);
+        this.script = script ?? (CompileScript('false', { addReturn: true }) as CompiledScript);
     }
 
     //     init(callback: (res: Field) => any) {
-- 
cgit v1.2.3-70-g09d2


From 1a0e7817754c9fbed5be0820872e9eff3c96d9bb Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 5 Oct 2022 10:37:00 -0400
Subject: Update CollectionFreeFormView.tsx

---
 .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx   | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 93bf143df..adf573061 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -157,8 +157,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     @computed get cachedCenteringShiftY(): number {
         const scaling = this.fitContentsToBox || !this.nativeDimScaling ? 1 : this.nativeDimScaling;
         // if freeform has a native aspect, then the panel height needs to be adjusted to match it
-        const aspect = this.props.DocumentView?.().nativeHeight ? this.props.DocumentView?.().nativeHeight / this.props.DocumentView?.().nativeWidth : 1;
-        return this.props.isAnnotationOverlay ? 0 : (aspect * this.props.PanelHeight()) / 2 / scaling; // shift so pan position is at center of window for non-overlay collections
+        const aspect = (this.props.DocumentView?.().nativeHeight || this.props.PanelHeight()) / (this.props.DocumentView?.().nativeWidth || this.props.PanelWidth());
+        return this.props.isAnnotationOverlay ? 0 : (aspect * this.props.PanelWidth()) / 2 / scaling; // shift so pan position is at center of window for non-overlay collections
     }
     @computed get cachedGetLocalTransform(): Transform {
         return Transform.Identity()
-- 
cgit v1.2.3-70-g09d2


From 68249e9662043e4216564f07b74ea4286cc185aa Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 5 Oct 2022 10:51:58 -0400
Subject: from last - fixing pan to be in center of freeform views when they
 have native width/heights & are fitWidth in lightbox

---
 .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx    | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index adf573061..0d061a325 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -155,9 +155,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         return this.props.isAnnotationOverlay ? 0 : this.props.PanelWidth() / 2 / scaling; // shift so pan position is at center of window for non-overlay collections
     }
     @computed get cachedCenteringShiftY(): number {
+        const dv = this.props.DocumentView?.();
         const scaling = this.fitContentsToBox || !this.nativeDimScaling ? 1 : this.nativeDimScaling;
         // if freeform has a native aspect, then the panel height needs to be adjusted to match it
-        const aspect = (this.props.DocumentView?.().nativeHeight || this.props.PanelHeight()) / (this.props.DocumentView?.().nativeWidth || this.props.PanelWidth());
+        const aspect = dv?.nativeWidth && dv?.nativeHeight && !dv.layoutDoc.fitWidth ? dv.nativeHeight / dv.nativeWidth : this.props.PanelHeight() / this.props.PanelWidth();
         return this.props.isAnnotationOverlay ? 0 : (aspect * this.props.PanelWidth()) / 2 / scaling; // shift so pan position is at center of window for non-overlay collections
     }
     @computed get cachedGetLocalTransform(): Transform {
-- 
cgit v1.2.3-70-g09d2


From 0e3892e63758accd7dae274072ad7893934c3624 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 18 Oct 2022 15:07:31 -0400
Subject: cleaned up gestureutils a bit.  added recognize gestures option, but
 it probably shouldn't be used until the geometry gesture recognition
 descriptions are improved.

---
 src/client/util/CurrentUserUtils.ts                |   8 +-
 src/client/util/InteractionUtils.tsx               |  26 ++-
 src/client/util/SettingsManager.tsx                |   4 +
 src/client/views/GestureOverlay.tsx                |  49 ++---
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   6 +-
 src/client/views/nodes/button/FontIconBox.tsx      |   9 +-
 src/pen-gestures/GestureUtils.ts                   |  48 ++---
 src/pen-gestures/ndollar.ts                        | 230 ++++++++++++---------
 8 files changed, 204 insertions(+), 176 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 1c9f89fa0..bfa868dbc 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -12,6 +12,7 @@ import { ComputedField, ScriptField } from "../../fields/ScriptField";
 import { Cast, DateCast, DocCast, PromiseValue, StrCast } from "../../fields/Types";
 import { nullAudio } from "../../fields/URLField";
 import { SetCachedGroups, SharingPermissions } from "../../fields/util";
+import { GestureUtils } from "../../pen-gestures/GestureUtils";
 import { OmitKeys, Utils } from "../../Utils";
 import { DocServer } from "../DocServer";
 import { Docs, DocumentOptions, DocUtils, FInfo } from "../documents/Documents";
@@ -631,9 +632,9 @@ export class CurrentUserUtils {
             { title: "Write",  toolTip: "Write (Ctrl+Shift+P)",  btnType: ButtonType.ToggleButton, icon: "pen",                         scripts: {onClick:'{ return setActiveTool("write", _readOnly_);}'} },
             { title: "Eraser", toolTip: "Eraser (Ctrl+E)",       btnType: ButtonType.ToggleButton, icon: "eraser",                      scripts: {onClick:'{ return setActiveTool("eraser", _readOnly_);}' }},
             // { title: "Highlighter", toolTip: "Highlighter (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter", scripts:{onClick: 'setActiveTool("highlighter")'} },
-            { title: "Circle", toolTip: "Circle (Ctrl+Shift+C)", btnType: ButtonType.ToggleButton, icon: "circle",                      scripts: {onClick:'{ return setActiveTool("circle", _readOnly_);}'} },
-            // { title: "Square", toolTip: "Square (Ctrl+Shift+S)", btnType: ButtonType.ToggleButton, icon: "square", click: 'setActiveTool("square")' },
-            { title: "Line",   toolTip: "Line (Ctrl+Shift+L)",   btnType: ButtonType.ToggleButton, icon: "minus",                       scripts: {onClick:'{ return setActiveTool("line", _readOnly_);}' }},
+            { title: "Circle", toolTip: "Circle (Ctrl+Shift+C)", btnType: ButtonType.ToggleButton, icon: "circle",                      scripts: {onClick:`{ return setActiveTool("${GestureUtils.Gestures.Circle}", _readOnly_);}`} },
+            { title: "Square", toolTip: "Square (Ctrl+Shift+S)", btnType: ButtonType.ToggleButton, icon: "square",                      scripts: {onClick:`{ return setActiveTool("${GestureUtils.Gestures.Rectangle}", _readOnly_);}`} },
+            { title: "Line",   toolTip: "Line (Ctrl+Shift+L)",   btnType: ButtonType.ToggleButton, icon: "minus",                       scripts: {onClick:`{ return setActiveTool("${GestureUtils.Gestures.Line}", _readOnly_);}`} },
             { title: "Mask",   toolTip: "Mask",                  btnType: ButtonType.ToggleButton, icon: "user-circle",                 scripts: {onClick:'{ return setIsInkMask(_readOnly_);}'} },
             { title: "Fill",   toolTip: "Fill color",            btnType: ButtonType.ColorButton,  icon: "fill-drip",ignoreClick: true, scripts: {script: '{ return setFillColor(value, _readOnly_);}'} },
             { title: "Width",  toolTip: "Stroke width",          btnType: ButtonType.NumberButton,                   ignoreClick: true, scripts: {script: '{ return setStrokeWidth(value, _readOnly_);}'}, numBtnType: NumButtonType.Slider, numBtnMin: 1},
@@ -797,6 +798,7 @@ export class CurrentUserUtils {
         doc._raiseWhenDragged ?? (doc._raiseWhenDragged = true);
         doc._showLabel ?? (doc._showLabel = true);
         doc.textAlign ?? (doc.textAlign = "left");
+        doc.activeTool = InkTool.None;
         doc.activeInkColor ?? (doc.activeInkColor = "rgb(0, 0, 0)");;
         doc.activeInkWidth ?? (doc.activeInkWidth = 1);
         doc.activeInkBezier ?? (doc.activeInkBezier = "0");
diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx
index 85700da37..6622b498d 100644
--- a/src/client/util/InteractionUtils.tsx
+++ b/src/client/util/InteractionUtils.tsx
@@ -1,4 +1,5 @@
 import React = require('react');
+import { GestureUtils } from '../../pen-gestures/GestureUtils';
 import { Utils } from '../../Utils';
 import './InteractionUtils.scss';
 
@@ -186,7 +187,7 @@ export namespace InteractionUtils {
     export function makePolygon(shape: string, points: { X: number; Y: number }[]) {
         if (points.length > 1 && points[points.length - 1].X === points[0].X && points[points.length - 1].Y + 1 === points[0].Y) {
             //pointer is up (first and last points are the same)
-            if (shape === 'arrow' || shape === 'line' || shape === 'circle') {
+            if (shape === GestureUtils.Gestures.Arrow || shape === GestureUtils.Gestures.Line || shape === GestureUtils.Gestures.Circle) {
                 //if arrow or line, the two end points should be the starting and the ending point
                 var left = points[0].X;
                 var top = points[0].Y;
@@ -208,7 +209,7 @@ export namespace InteractionUtils {
             left = points[0].X;
             bottom = points[points.length - 1].Y;
             top = points[0].Y;
-            if (shape !== 'arrow' && shape !== 'line' && shape !== 'circle') {
+            if (shape !== GestureUtils.Gestures.Arrow && shape !== GestureUtils.Gestures.Line && shape !== GestureUtils.Gestures.Circle) {
                 //switch left/right and top/bottom if needed
                 if (left > right) {
                     const temp = right;
@@ -224,20 +225,20 @@ export namespace InteractionUtils {
         }
         points = [];
         switch (shape) {
-            case 'rectangle':
+            case GestureUtils.Gestures.Rectangle:
                 points.push({ X: left, Y: top });
                 points.push({ X: right, Y: top });
                 points.push({ X: right, Y: bottom });
                 points.push({ X: left, Y: bottom });
                 points.push({ X: left, Y: top });
                 break;
-            case 'triangle':
+            case GestureUtils.Gestures.Triangle:
                 points.push({ X: left, Y: bottom });
                 points.push({ X: right, Y: bottom });
                 points.push({ X: (right + left) / 2, Y: top });
                 points.push({ X: left, Y: bottom });
                 break;
-            case 'circle':
+            case GestureUtils.Gestures.Circle:
                 const centerX = (Math.max(left, right) + Math.min(left, right)) / 2;
                 const centerY = (Math.max(top, bottom) + Math.min(top, bottom)) / 2;
                 const radius = Math.max(centerX - Math.min(left, right), centerY - Math.min(top, bottom));
@@ -253,7 +254,7 @@ export namespace InteractionUtils {
                 points.push({ X: Math.min(left, right), Y: Math.sqrt(Math.pow(radius, 2) - Math.pow(Math.min(left, right) - centerX, 2)) + centerY });
                 break;
 
-            case 'line':
+            case GestureUtils.Gestures.Line:
                 points.push({ X: left, Y: top });
                 points.push({ X: right, Y: bottom });
                 break;
@@ -266,17 +267,14 @@ export namespace InteractionUtils {
      * @param type - InteractionUtils.(PENTYPE | ERASERTYPE | MOUSETYPE | TOUCHTYPE)
      */
     export function IsType(e: PointerEvent | React.PointerEvent, type: string): boolean {
+        // prettier-ignore
         switch (type) {
             // pen and eraser are both pointer type 'pen', but pen is button 0 and eraser is button 5. -syip2
-            case PENTYPE:
-                return e.pointerType === PENTYPE && (e.button === -1 || e.button === 0);
-            case ERASERTYPE:
-                return e.pointerType === PENTYPE && e.button === (e instanceof PointerEvent ? ERASER_BUTTON : ERASER_BUTTON);
-            case TOUCHTYPE:
-                return e.pointerType === TOUCHTYPE;
-            default:
-                return e.pointerType === type;
+            case PENTYPE: return e.pointerType === PENTYPE && (e.button === -1 || e.button === 0);
+            case ERASERTYPE: return e.pointerType === PENTYPE && e.button === (e instanceof PointerEvent ? ERASER_BUTTON : ERASER_BUTTON);
+            case TOUCHTYPE: return e.pointerType === TOUCHTYPE;
         }
+        return e.pointerType === type;
     }
 
     /**
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index a185c8936..92032a8f9 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -186,6 +186,10 @@ export class SettingsManager extends React.Component<{}> {
                     <input type="checkbox" onChange={e => FontIconBox.SetShowLabels(!FontIconBox.GetShowLabels())} checked={FontIconBox.GetShowLabels()} />
                     <div className="preferences-check">Show button labels</div>
                 </div>
+                <div>
+                    <input type="checkbox" onChange={e => FontIconBox.SetRecognizeGesturs(!FontIconBox.GetRecognizeGestures())} checked={FontIconBox.GetRecognizeGestures()} />
+                    <div className="preferences-check">Recognize ink Gesturs</div>
+                </div>
             </div>
         );
     }
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 850688e7e..23b03bc50 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -684,7 +684,7 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
             }
             //if any of the shape is activated in the CollectionFreeFormViewChrome
             else if (this.InkShape) {
-                this.makePolygon(this.InkShape, false);
+                this.makeBezierPolygon(this.InkShape, false);
                 this.dispatchGesture(GestureUtils.Gestures.Stroke);
                 this._points.length = 0;
                 if (!CollectionFreeFormViewChrome.Instance?._keepPrimitiveMode) {
@@ -699,27 +699,17 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
                 let actionPerformed = false;
                 if (Doc.UserDoc().recognizeGestures && result && result.Score > 0.7) {
                     switch (result.Name) {
-                        case GestureUtils.Gestures.Box:
-                            actionPerformed = this.dispatchGesture(GestureUtils.Gestures.Box);
-                            break;
+                        case GestureUtils.Gestures.Triangle:
+                        case GestureUtils.Gestures.Rectangle:
+                        case GestureUtils.Gestures.Circle:
+                            this.makeBezierPolygon(result.Name, true);
                         case GestureUtils.Gestures.StartBracket:
-                            actionPerformed = this.dispatchGesture(GestureUtils.Gestures.StartBracket);
-                            break;
                         case GestureUtils.Gestures.EndBracket:
-                            actionPerformed = this.dispatchGesture('endbracket');
+                            actionPerformed = this.dispatchGesture(result.Name);
                             break;
                         case GestureUtils.Gestures.Line:
                             actionPerformed = this.handleLineGesture();
                             break;
-                        case GestureUtils.Gestures.Triangle:
-                            actionPerformed = this.makePolygon('triangle', true);
-                            break;
-                        case GestureUtils.Gestures.Circle:
-                            actionPerformed = this.makePolygon('circle', true);
-                            break;
-                        case GestureUtils.Gestures.Rectangle:
-                            actionPerformed = this.makePolygon('rectangle', true);
-                            break;
                         case GestureUtils.Gestures.Scribble:
                             console.log('scribble');
                             break;
@@ -760,11 +750,7 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
         CollectionFreeFormViewChrome.Instance?.primCreated();
     };
 
-    makePolygon = (shape: string, gesture: boolean) => {
-        //take off gesture recognition for now
-        if (gesture) {
-            return false;
-        }
+    makeBezierPolygon = (shape: string, gesture: boolean) => {
         const xs = this._points.map(p => p.X);
         const ys = this._points.map(p => p.Y);
         var right = Math.max(...xs);
@@ -794,7 +780,7 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
             left = this._points[0].X;
             bottom = this._points[this._points.length - 2].Y;
             top = this._points[0].Y;
-            if (shape !== 'arrow' && shape !== 'line' && shape !== 'circle') {
+            if (shape !== GestureUtils.Gestures.Arrow && shape !== GestureUtils.Gestures.Line && shape !== GestureUtils.Gestures.Circle) {
                 if (left > right) {
                     const temp = right;
                     right = left;
@@ -809,9 +795,7 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
         }
         this._points.length = 0;
         switch (shape) {
-            //must push an extra point in the end so InteractionUtils knows pointer is up.
-            //must be (points[0].X,points[0]-1)
-            case 'rectangle':
+            case GestureUtils.Gestures.Rectangle:
                 this._points.push({ X: left, Y: top });
                 this._points.push({ X: left, Y: top });
                 this._points.push({ X: right, Y: top });
@@ -834,7 +818,7 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
 
                 break;
 
-            case 'triangle':
+            case GestureUtils.Gestures.Triangle:
                 this._points.push({ X: left, Y: bottom });
                 this._points.push({ X: left, Y: bottom });
 
@@ -852,7 +836,7 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
                 this._points.push({ X: left, Y: bottom });
 
                 break;
-            case 'circle':
+            case GestureUtils.Gestures.Circle:
                 // Approximation of a circle using 4 Bézier curves in which the constant "c" reduces the maximum radial drift to 0.019608%,
                 // making the curves indistinguishable from a circle.
                 // Source: https://spencermortensen.com/articles/bezier-circle/
@@ -884,7 +868,7 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
 
                 break;
 
-            case 'line':
+            case GestureUtils.Gestures.Line:
                 if (Math.abs(firstx - lastx) < 10 && Math.abs(firsty - lasty) > 10) {
                     lastx = firstx;
                 }
@@ -897,7 +881,7 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
                 this._points.push({ X: lastx, Y: lasty });
                 this._points.push({ X: lastx, Y: lasty });
                 break;
-            case 'arrow':
+            case GestureUtils.Gestures.Arrow:
                 const x1 = left;
                 const y1 = top;
                 const x2 = right;
@@ -914,12 +898,11 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
                 this._points.push({ X: x3, Y: y3 });
                 this._points.push({ X: x4, Y: y4 });
                 this._points.push({ X: x2, Y: y2 });
-            // this._points.push({ X: x1, Y: y1 - 1 });
         }
-        return true;
+        return false;
     };
 
-    dispatchGesture = (gesture: 'box' | 'line' | 'startbracket' | 'endbracket' | 'stroke' | 'scribble' | 'text', stroke?: InkData, data?: any) => {
+    dispatchGesture = (gesture: GestureUtils.Gestures, stroke?: InkData, data?: any) => {
         const target = document.elementFromPoint((stroke ?? this._points)[0].X, (stroke ?? this._points)[0].Y);
         return (
             target?.dispatchEvent(
@@ -1136,7 +1119,7 @@ ScriptingGlobals.add(function resetPen() {
 }, 'resets the pen tool');
 ScriptingGlobals.add(
     function createText(text: any, x: any, y: any) {
-        GestureOverlay.Instance.dispatchGesture('text', [{ X: x, Y: y }], text);
+        GestureOverlay.Instance.dispatchGesture(GestureUtils.Gestures.Text, [{ X: x, Y: y }], text);
     },
     'creates a text document with inputted text and coordinates',
     '(text: any, x: any, y: any)'
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 5d4e1c999..daf69d4f6 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -568,6 +568,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     @undoBatch
     onGesture = (e: Event, ge: GestureUtils.GestureEvent) => {
         switch (ge.gesture) {
+            default:
+            case GestureUtils.Gestures.Circle:
+            case GestureUtils.Gestures.Rectangle:
+            case GestureUtils.Gestures.Triangle:
             case GestureUtils.Gestures.Stroke:
                 const points = ge.points;
                 const B = this.getTransform().transformBounds(ge.bounds.left, ge.bounds.top, ge.bounds.width, ge.bounds.height);
@@ -597,7 +601,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 this.addDocument(inkDoc);
                 e.stopPropagation();
                 break;
-            case GestureUtils.Gestures.Box:
+            case GestureUtils.Gestures.Rectangle:
                 const lt = this.getTransform().transformPoint(Math.min(...ge.points.map(p => p.X)), Math.min(...ge.points.map(p => p.Y)));
                 const rb = this.getTransform().transformPoint(Math.max(...ge.points.map(p => p.X)), Math.max(...ge.points.map(p => p.Y)));
                 const bounds = { x: lt[0], r: rb[0], y: lt[1], b: rb[1] };
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index 6d1751b25..6eaf3c31a 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -11,6 +11,7 @@ import { InkTool } from '../../../../fields/InkField';
 import { ScriptField } from '../../../../fields/ScriptField';
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
 import { WebField } from '../../../../fields/URLField';
+import { GestureUtils } from '../../../../pen-gestures/GestureUtils';
 import { aggregateBounds, Utils } from '../../../../Utils';
 import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
 import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
@@ -85,6 +86,12 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
     static SetShowLabels(show: boolean) {
         Doc.UserDoc()._showLabel = show;
     }
+    static GetRecognizeGestures() {
+        return BoolCast(Doc.UserDoc()._recognizeGestures);
+    }
+    static SetRecognizeGesturs(show: boolean) {
+        Doc.UserDoc()._recognizeGestures = show;
+    }
 
     // Determining UI Specs
     @computed get label() {
@@ -775,7 +782,7 @@ ScriptingGlobals.add(function setActiveTool(tool: string, checkResult?: boolean)
     if (checkResult) {
         return (Doc.ActiveTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool ? Colors.MEDIUM_BLUE : 'transparent';
     }
-    if (['circle', 'square', 'line'].includes(tool)) {
+    if ([GestureUtils.Gestures.Circle, GestureUtils.Gestures.Rectangle, GestureUtils.Gestures.Line, GestureUtils.Gestures.Triangle].includes(tool as any)) {
         if (GestureOverlay.Instance.InkShape === tool) {
             Doc.ActiveTool = InkTool.None;
             GestureOverlay.Instance.InkShape = InkTool.None;
diff --git a/src/pen-gestures/GestureUtils.ts b/src/pen-gestures/GestureUtils.ts
index 65f2bf80c..2d3b1fdb8 100644
--- a/src/pen-gestures/GestureUtils.ts
+++ b/src/pen-gestures/GestureUtils.ts
@@ -1,40 +1,34 @@
-import { Rect } from "react-measure";
-import { PointData } from "../fields/InkField";
-import { NDollarRecognizer } from "./ndollar";
+import { Rect } from 'react-measure';
+import { PointData } from '../fields/InkField';
+import { NDollarRecognizer } from './ndollar';
 
 export namespace GestureUtils {
     export class GestureEvent {
-        constructor(
-            readonly gesture: Gestures,
-            readonly points: PointData[],
-            readonly bounds: Rect,
-            readonly text?: any
-        ) { }
+        constructor(readonly gesture: Gestures, readonly points: PointData[], readonly bounds: Rect, readonly text?: any) {}
     }
 
-    export interface GestureEventDisposer { (): void; }
+    export interface GestureEventDisposer {
+        (): void;
+    }
 
-    export function MakeGestureTarget(
-        element: HTMLElement,
-        func: (e: Event, ge: GestureEvent) => void
-    ): GestureEventDisposer {
+    export function MakeGestureTarget(element: HTMLElement, func: (e: Event, ge: GestureEvent) => void): GestureEventDisposer {
         const handler = (e: Event) => func(e, (e as CustomEvent<GestureEvent>).detail);
-        element.addEventListener("dashOnGesture", handler);
-        return () => element.removeEventListener("dashOnGesture", handler);
+        element.addEventListener('dashOnGesture', handler);
+        return () => element.removeEventListener('dashOnGesture', handler);
     }
 
     export enum Gestures {
-        Box = "box",
-        Line = "line",
-        StartBracket = "startbracket",
-        EndBracket = "endbracket",
-        Stroke = "stroke",
-        Scribble = "scribble",
-        Text = "text",
-        Triangle = "triangle",
-        Circle = "circle",
-        Rectangle = "rectangle",
+        Line = 'line',
+        StartBracket = 'startbracket',
+        EndBracket = 'endbracket',
+        Stroke = 'stroke',
+        Scribble = 'scribble',
+        Text = 'text',
+        Triangle = 'triangle',
+        Circle = 'circle',
+        Rectangle = 'rectangle',
+        Arrow = 'arrow',
     }
 
     export const GestureRecognizer = new NDollarRecognizer(false);
-}
\ No newline at end of file
+}
diff --git a/src/pen-gestures/ndollar.ts b/src/pen-gestures/ndollar.ts
index ecd8df3e7..b10a9da17 100644
--- a/src/pen-gestures/ndollar.ts
+++ b/src/pen-gestures/ndollar.ts
@@ -1,4 +1,4 @@
-import { GestureUtils } from "./GestureUtils";
+import { GestureUtils } from './GestureUtils';
 
 /**
  * The $N Multistroke Recognizer (JavaScript version)
@@ -69,20 +69,20 @@ import { GestureUtils } from "./GestureUtils";
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
-**/
+ **/
 
 //
 // Point class
 //
 export class Point {
-    constructor(public X: number, public Y: number) { }
+    constructor(public X: number, public Y: number) {}
 }
 
 //
 // Rectangle class
 //
 export class Rectangle {
-    constructor(public X: number, public Y: number, public Width: number, public Height: number) { }
+    constructor(public X: number, public Y: number, public Width: number, public Height: number) {}
 }
 
 //
@@ -113,8 +113,11 @@ export class Multistroke {
     public NumStrokes: number;
     public Unistrokes: Unistroke[];
 
-    constructor(public Name: string, useBoundedRotationInvariance: boolean, strokes: any[]) // constructor
-    {
+    constructor(
+        public Name: string,
+        useBoundedRotationInvariance: boolean,
+        strokes: any[] // constructor
+    ) {
         this.NumStrokes = strokes.length; // number of individual strokes
 
         const order = new Array(strokes.length); // array of integer indices
@@ -136,13 +139,13 @@ export class Multistroke {
 // Result class
 //
 export class Result {
-    constructor(public Name: string, public Score: any, public Time: any) { }
+    constructor(public Name: string, public Score: any, public Time: any) {}
 }
 
 //
 // NDollarRecognizer constants
 //
-const NumMultistrokes = 7;
+const NumMultistrokes = 6;
 const NumPoints = 96;
 const SquareSize = 250.0;
 const OneDThreshold = 0.25; // customize to desired gesture set (usually 0.20 - 0.35)
@@ -152,7 +155,7 @@ const HalfDiagonal = 0.5 * Diagonal;
 const AngleRange = Deg2Rad(45.0);
 const AnglePrecision = Deg2Rad(2.0);
 const Phi = 0.5 * (-1.0 + Math.sqrt(5.0)); // Golden Ratio
-const StartAngleIndex = (NumPoints / 8); // eighth of gesture length
+const StartAngleIndex = NumPoints / 8; // eighth of gesture length
 const AngleSimilarityThreshold = Deg2Rad(30.0);
 
 //
@@ -164,48 +167,68 @@ export class NDollarRecognizer {
     /**
      * @IMPORTANT - IF YOU'RE ADDING A NEW GESTURE, BE SURE TO INCREMENT THE NumMultiStrokes CONST RIGHT ABOVE THIS CLASS.
      */
-    constructor(useBoundedRotationInvariance: boolean) // constructor
-    {
+    constructor(
+        useBoundedRotationInvariance: boolean // constructor
+    ) {
         //
         // one predefined multistroke for each multistroke type
         //
         this.Multistrokes = new Array(NumMultistrokes);
-        this.Multistrokes[0] = new Multistroke(GestureUtils.Gestures.Box, useBoundedRotationInvariance, new Array(
+        this.Multistrokes[0] = new Multistroke(
+            GestureUtils.Gestures.Rectangle,
+            useBoundedRotationInvariance,
             new Array(
-                new Point(30, 146), //new Point(29, 160), new Point(30, 180), new Point(31, 200),
-                new Point(30, 222), //new Point(50, 219), new Point(70, 225), new Point(90, 230),
-                new Point(106, 225), //new Point(100, 200), new Point(106, 180), new Point(110, 160),
-                new Point(106, 146), //new Point(80, 150), new Point(50, 146),
-                new Point(30, 143))
-        ));
-        this.Multistrokes[1] = new Multistroke(GestureUtils.Gestures.Line, useBoundedRotationInvariance, new Array(
-            new Array(new Point(12, 347), new Point(119, 347))
-        ));
-        this.Multistrokes[2] = new Multistroke(GestureUtils.Gestures.StartBracket, useBoundedRotationInvariance, new Array(
-            // new Array(new Point(145, 20), new Point(30, 21), new Point(34, 150))
-            new Array(new Point(31, 25), new Point(145, 20), new Point(31, 25), new Point(34, 150))
-        ));
-        this.Multistrokes[3] = new Multistroke(GestureUtils.Gestures.EndBracket, useBoundedRotationInvariance, new Array(
-            // new Array(new Point(150, 21), new Point(149, 150), new Point(26, 152))
-            // new Array(new Point(150, 150), new Point(150, 0), new Point(150, 150), new Point(0, 150))
-            new Array(new Point(10, 100), new Point(100, 100), new Point(150, 12), new Point(200, 103), new Point(300, 100))
-        ));
-        this.Multistrokes[4] = new Multistroke(GestureUtils.Gestures.Triangle, useBoundedRotationInvariance, new Array(
-            new Array(new Point(40, 100), new Point(100, 200), new Point(140, 102), new Point(42, 100))
-        ));
-        this.Multistrokes[5] = new Multistroke(GestureUtils.Gestures.Circle, useBoundedRotationInvariance, new Array(
-            new Array(new Point(200, 250), new Point(240, 230), new Point(248, 210), new Point(248, 190), new Point(240, 170), new Point(200, 150), new Point(160, 170), new Point(151, 190), new Point(151, 210), new Point(160, 230), new Point(201, 250))
-        ));
-        this.Multistrokes[6] = new Multistroke(GestureUtils.Gestures.Rectangle, useBoundedRotationInvariance, new Array(
+                new Array(
+                    new Point(30, 146), //new Point(29, 160), new Point(30, 180), new Point(31, 200),
+                    new Point(30, 222), //new Point(50, 219), new Point(70, 225), new Point(90, 230),
+                    new Point(106, 225), //new Point(100, 200), new Point(106, 180), new Point(110, 160),
+                    new Point(106, 146), //new Point(80, 150), new Point(50, 146),
+                    new Point(30, 143)
+                )
+            )
+        );
+        this.Multistrokes[1] = new Multistroke(GestureUtils.Gestures.Line, useBoundedRotationInvariance, new Array(new Array(new Point(12, 347), new Point(119, 347))));
+        this.Multistrokes[2] = new Multistroke(
+            GestureUtils.Gestures.StartBracket,
+            useBoundedRotationInvariance,
             new Array(
-                new Point(30, 146), //new Point(29, 160), new Point(30, 180), new Point(31, 200),
-                new Point(30, 222), //new Point(50, 219), new Point(70, 225), new Point(90, 230),
-                new Point(106, 225), //new Point(100, 200), new Point(106, 180), new Point(110, 160),
-                new Point(106, 146), //new Point(80, 150), new Point(50, 146),
-                new Point(30, 143),
-                new Point(29, 220))
-        ));
-
+                // new Array(new Point(145, 20), new Point(30, 21), new Point(34, 150))
+                new Array(new Point(31, 25), new Point(145, 20), new Point(31, 25), new Point(34, 150))
+            )
+        );
+        this.Multistrokes[3] = new Multistroke(
+            GestureUtils.Gestures.EndBracket,
+            useBoundedRotationInvariance,
+            new Array(
+                // new Array(new Point(150, 21), new Point(149, 150), new Point(26, 152))
+                // new Array(new Point(150, 150), new Point(150, 0), new Point(150, 150), new Point(0, 150))
+                new Array(new Point(10, 100), new Point(100, 100), new Point(150, 12), new Point(200, 103), new Point(300, 100))
+            )
+        );
+        this.Multistrokes[4] = new Multistroke(
+            GestureUtils.Gestures.Triangle, // equilateral
+            useBoundedRotationInvariance,
+            new Array(new Array(new Point(40, 100), new Point(100, 200), new Point(140, 102), new Point(42, 100)))
+        );
+        this.Multistrokes[5] = new Multistroke(
+            GestureUtils.Gestures.Circle,
+            useBoundedRotationInvariance,
+            new Array(
+                new Array(
+                    new Point(200, 250),
+                    new Point(240, 230),
+                    new Point(248, 210),
+                    new Point(248, 190),
+                    new Point(240, 170),
+                    new Point(200, 150),
+                    new Point(160, 170),
+                    new Point(151, 190),
+                    new Point(151, 210),
+                    new Point(160, 230),
+                    new Point(201, 250)
+                )
+            )
+        );
         //
         // PREDEFINED STROKES
         //
@@ -281,23 +304,25 @@ export class NDollarRecognizer {
     Recognize = (strokes: any[], useBoundedRotationInvariance: boolean = false, requireSameNoOfStrokes: boolean = false, useProtractor: boolean = true) => {
         const t0 = Date.now();
         const points = CombineStrokes(strokes); // make one connected unistroke from the given strokes
-        const candidate = new Unistroke("", useBoundedRotationInvariance, points);
+        const candidate = new Unistroke('', useBoundedRotationInvariance, points);
 
         var u = -1;
         var b = +Infinity;
-        for (var i = 0; i < this.Multistrokes.length; i++) // for each multistroke template
-        {
-            if (!requireSameNoOfStrokes || strokes.length === this.Multistrokes[i].NumStrokes) // optional -- only attempt match when same # of component strokes
-            {
-                for (const unistroke of this.Multistrokes[i].Unistrokes) // for each unistroke within this multistroke
-                {
-                    if (AngleBetweenUnitVectors(candidate.StartUnitVector, unistroke.StartUnitVector) <= AngleSimilarityThreshold) // strokes start in the same direction
-                    {
+        for (
+            var i = 0;
+            i < this.Multistrokes.length;
+            i++ // for each multistroke template
+        ) {
+            if (!requireSameNoOfStrokes || strokes.length === this.Multistrokes[i].NumStrokes) {
+                // optional -- only attempt match when same # of component strokes
+                for (const unistroke of this.Multistrokes[i].Unistrokes) {
+                    // for each unistroke within this multistroke
+                    if (AngleBetweenUnitVectors(candidate.StartUnitVector, unistroke.StartUnitVector) <= AngleSimilarityThreshold) {
+                        // strokes start in the same direction
                         var d;
                         if (useProtractor) {
                             d = OptimalCosineDistance(unistroke.Vector, candidate.Vector); // Protractor
-                        }
-                        else {
+                        } else {
                             d = DistanceAtBestAngle(candidate.Points, unistroke, -AngleRange, +AngleRange, AnglePrecision); // Golden Section Search (original $N)
                         }
                         if (d < b) {
@@ -309,8 +334,8 @@ export class NDollarRecognizer {
             }
         }
         const t1 = Date.now();
-        return (u === -1) ? null : new Result(this.Multistrokes[u].Name, useProtractor ? (1.0 - b) : (1.0 - b / HalfDiagonal), t1 - t0);
-    }
+        return u === -1 ? null : new Result(this.Multistrokes[u].Name, useProtractor ? 1.0 - b : 1.0 - b / HalfDiagonal, t1 - t0);
+    };
 
     AddGesture = (name: string, useBoundedRotationInvariance: boolean, strokes: any[]) => {
         this.Multistrokes[this.Multistrokes.length] = new Multistroke(name, useBoundedRotationInvariance, strokes);
@@ -321,15 +346,14 @@ export class NDollarRecognizer {
             }
         }
         return num;
-    }
+    };
 
     DeleteUserGestures = () => {
         this.Multistrokes.length = NumMultistrokes; // clear any beyond the original set
         return NumMultistrokes;
-    }
+    };
 }
 
-
 //
 // Private helper functions from here on down
 //
@@ -339,11 +363,13 @@ function HeapPermute(n: number, order: any[], /*out*/ orders: any[]) {
     } else {
         for (var i = 0; i < n; i++) {
             HeapPermute(n - 1, order, orders);
-            if (n % 2 === 1) { // swap 0, n-1
+            if (n % 2 === 1) {
+                // swap 0, n-1
                 const tmp = order[0];
                 order[0] = order[n - 1];
                 order[n - 1] = tmp;
-            } else { // swap i, n-1
+            } else {
+                // swap i, n-1
                 const tmp = order[i];
                 order[i] = order[n - 1];
                 order[n - 1] = tmp;
@@ -355,15 +381,18 @@ function HeapPermute(n: number, order: any[], /*out*/ orders: any[]) {
 function MakeUnistrokes(strokes: any, orders: any) {
     const unistrokes = new Array(); // array of point arrays
     for (const order of orders) {
-        for (var b = 0; b < Math.pow(2, order.length); b++) // use b's bits for directions
-        {
+        for (
+            var b = 0;
+            b < Math.pow(2, order.length);
+            b++ // use b's bits for directions
+        ) {
             const unistroke = new Array(); // array of points
             for (var i = 0; i < order.length; i++) {
                 var pts;
-                if (((b >> i) & 1) === 1) {// is b's bit at index i on?
+                if (((b >> i) & 1) === 1) {
+                    // is b's bit at index i on?
                     pts = strokes[order[i]].slice().reverse(); // copy and reverse
-                }
-                else {
+                } else {
                     pts = strokes[order[i]].slice(); // copy
                 }
                 for (const point of pts) {
@@ -391,17 +420,17 @@ function Resample(points: any, n: any) {
     const newpoints = new Array(points[0]);
     for (var i = 1; i < points.length; i++) {
         const d = Distance(points[i - 1], points[i]);
-        if ((D + d) >= I) {
+        if (D + d >= I) {
             const qx = points[i - 1].X + ((I - D) / d) * (points[i].X - points[i - 1].X);
             const qy = points[i - 1].Y + ((I - D) / d) * (points[i].Y - points[i - 1].Y);
             const q = new Point(qx, qy);
             newpoints[newpoints.length] = q; // append new point 'q'
             points.splice(i, 0, q); // insert 'q' at position i in points s.t. 'q' will be the next i
             D = 0.0;
-        }
-        else D += d;
+        } else D += d;
     }
-    if (newpoints.length === n - 1) {// sometimes we fall a rounding-error short of adding the last point, so add it if so
+    if (newpoints.length === n - 1) {
+        // sometimes we fall a rounding-error short of adding the last point, so add it if so
         newpoints[newpoints.length] = new Point(points[points.length - 1].X, points[points.length - 1].Y);
     }
     return newpoints;
@@ -410,8 +439,8 @@ function IndicativeAngle(points: any) {
     const c = Centroid(points);
     return Math.atan2(c.Y - points[0].Y, c.X - points[0].X);
 }
-function RotateBy(points: any, radians: any) // rotates points around centroid
-{
+function RotateBy(points: any, radians: any) {
+    // rotates points around centroid
     const c = Centroid(points);
     const cos = Math.cos(radians);
     const sin = Math.sin(radians);
@@ -423,8 +452,8 @@ function RotateBy(points: any, radians: any) // rotates points around centroid
     }
     return newpoints;
 }
-function ScaleDimTo(points: any, size: any, ratio1D: any) // scales bbox uniformly for 1D, non-uniformly for 2D
-{
+function ScaleDimTo(points: any, size: any, ratio1D: any) {
+    // scales bbox uniformly for 1D, non-uniformly for 2D
     const B = BoundingBox(points);
     const uniformly = Math.min(B.Width / B.Height, B.Height / B.Width) <= ratio1D; // 1D or 2D gesture test
     const newpoints = new Array();
@@ -435,8 +464,8 @@ function ScaleDimTo(points: any, size: any, ratio1D: any) // scales bbox uniform
     }
     return newpoints;
 }
-function TranslateTo(points: any, pt: any) // translates points' centroid
-{
+function TranslateTo(points: any, pt: any) {
+    // translates points' centroid
     const c = Centroid(points);
     const newpoints = new Array();
     for (const { X, Y } of points) {
@@ -446,8 +475,8 @@ function TranslateTo(points: any, pt: any) // translates points' centroid
     }
     return newpoints;
 }
-function Vectorize(points: any, useBoundedRotationInvariance: any) // for Protractor
-{
+function Vectorize(points: any, useBoundedRotationInvariance: any) {
+    // for Protractor
     var cos = 1.0;
     var sin = 0.0;
     if (useBoundedRotationInvariance) {
@@ -471,8 +500,8 @@ function Vectorize(points: any, useBoundedRotationInvariance: any) // for Protra
     }
     return vector;
 }
-function OptimalCosineDistance(v1: any, v2: any) // for Protractor
-{
+function OptimalCosineDistance(v1: any, v2: any) {
+    // for Protractor
     var a = 0.0;
     var b = 0.0;
     for (var i = 0; i < v1.length; i += 2) {
@@ -509,7 +538,8 @@ function DistanceAtAngle(points: any, T: any, radians: any) {
     return PathDistance(newpoints, T.Points);
 }
 function Centroid(points: any) {
-    var x = 0.0, y = 0.0;
+    var x = 0.0,
+        y = 0.0;
     for (const point of points) {
         x += point.X;
         y += point.Y;
@@ -519,7 +549,10 @@ function Centroid(points: any) {
     return new Point(x, y);
 }
 function BoundingBox(points: any) {
-    var minX = +Infinity, maxX = -Infinity, minY = +Infinity, maxY = -Infinity;
+    var minX = +Infinity,
+        maxX = -Infinity,
+        minY = +Infinity,
+        maxY = -Infinity;
     for (const { X, Y } of points) {
         minX = Math.min(minX, X);
         minY = Math.min(minY, Y);
@@ -528,38 +561,41 @@ function BoundingBox(points: any) {
     }
     return new Rectangle(minX, minY, maxX - minX, maxY - minY);
 }
-function PathDistance(pts1: any, pts2: any) // average distance between corresponding points in two paths
-{
+function PathDistance(pts1: any, pts2: any) {
+    // average distance between corresponding points in two paths
     var d = 0.0;
-    for (var i = 0; i < pts1.length; i++) {// assumes pts1.length == pts2.length
+    for (var i = 0; i < pts1.length; i++) {
+        // assumes pts1.length == pts2.length
         d += Distance(pts1[i], pts2[i]);
     }
     return d / pts1.length;
 }
-function PathLength(points: any) // length traversed by a point path
-{
+function PathLength(points: any) {
+    // length traversed by a point path
     var d = 0.0;
     for (var i = 1; i < points.length; i++) {
         d += Distance(points[i - 1], points[i]);
     }
     return d;
 }
-function Distance(p1: any, p2: any) // distance between two points
-{
+function Distance(p1: any, p2: any) {
+    // distance between two points
     const dx = p2.X - p1.X;
     const dy = p2.Y - p1.Y;
     return Math.sqrt(dx * dx + dy * dy);
 }
-function CalcStartUnitVector(points: any, index: any) // start angle from points[0] to points[index] normalized as a unit vector
-{
+function CalcStartUnitVector(points: any, index: any) {
+    // start angle from points[0] to points[index] normalized as a unit vector
     const v = new Point(points[index]?.X - points[0]?.X, points[index]?.Y - points[0]?.Y);
     const len = Math.sqrt(v.X * v.X + v.Y * v.Y);
     return new Point(v.X / len, v.Y / len);
 }
-function AngleBetweenUnitVectors(v1: any, v2: any) // gives acute angle between unit vectors from (0,0) to v1, and (0,0) to v2
-{
-    const n = (v1.X * v2.X + v1.Y * v2.Y);
+function AngleBetweenUnitVectors(v1: any, v2: any) {
+    // gives acute angle between unit vectors from (0,0) to v1, and (0,0) to v2
+    const n = v1.X * v2.X + v1.Y * v2.Y;
     const c = Math.max(-1.0, Math.min(1.0, n)); // ensure [-1,+1]
     return Math.acos(c); // arc cosine of the vector dot product
 }
-function Deg2Rad(d: any) { return (d * Math.PI / 180.0); }
\ No newline at end of file
+function Deg2Rad(d: any) {
+    return (d * Math.PI) / 180.0;
+}
-- 
cgit v1.2.3-70-g09d2


From a81ab2e6f75681bc4fb3a7b49d2056144e396b94 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 19 Oct 2022 12:38:19 -0400
Subject: fixed erasing straight line stroke segments caused by intersections
 with other strokes. cleaned up more with gestures.  changed docView lock icon
 to be part of docDecorations.

---
 src/client/views/DocumentDecorations.scss          | 28 ++++++-
 src/client/views/DocumentDecorations.tsx           | 41 +++++++++-
 src/client/views/GestureOverlay.tsx                | 21 +++---
 src/client/views/StyleProvider.scss                | 18 ++---
 src/client/views/StyleProvider.tsx                 |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 58 ++++++--------
 src/client/views/nodes/DocumentView.tsx            |  2 +-
 src/client/views/nodes/ImageBox.tsx                |  5 +-
 src/client/views/nodes/button/FontIconBox.tsx      | 20 ++---
 src/pen-gestures/GestureUtils.ts                   |  2 -
 src/pen-gestures/ndollar.ts                        | 88 +++++++++-------------
 11 files changed, 148 insertions(+), 137 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 5c8dd36cc..4e0b061a6 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -1,7 +1,7 @@
 @import 'global/globalCssVariables';
 
 $linkGap: 3px;
-$headerHeight: 20px;
+$headerHeight: 25px;
 $resizeHandler: 8px;
 
 .documentDecorations-Dark,
@@ -54,6 +54,8 @@ $resizeHandler: 8px;
         grid-column-end: 4;
         flex-direction: row;
         gap: 2px;
+        pointer-events: all;
+        cursor: move;
 
         .documentDecorations-openButton {
             display: flex;
@@ -236,8 +238,8 @@ $resizeHandler: 8px;
     .documentDecorations-borderRadius {
         position: absolute;
         border-radius: 100%;
-        left: 3px;
-        top: 23px;
+        left: 7px;
+        top: 27px;
         background: $medium-gray;
         height: 10;
         width: 10;
@@ -245,6 +247,21 @@ $resizeHandler: 8px;
         cursor: nwse-resize;
     }
 
+    .documentDecorations-lock {
+        position: absolute;
+        background: black;
+        right: 11;
+        top: 30px;
+        color: gray;
+        height: 14;
+        width: 14;
+        pointer-events: all;
+        margin: auto;
+        display: flex;
+        align-items: center;
+        flex-direction: column;
+    }
+
     .documentDecorations-rotationPath {
         position: absolute;
         width: 100%;
@@ -260,6 +277,7 @@ $resizeHandler: 8px;
         cursor: nwse-resize;
         background: unset;
         opacity: 1;
+        transform: scale(2);
     }
 
     .documentDecorations-topLeftResizer {
@@ -314,6 +332,7 @@ $resizeHandler: 8px;
     .documentDecorations-topLeftResizer:hover,
     .documentDecorations-bottomRightResizer:hover {
         opacity: 1;
+        background: black;
     }
 
     .documentDecorations-bottomRightResizer {
@@ -325,6 +344,7 @@ $resizeHandler: 8px;
         cursor: nesw-resize;
         background: unset;
         opacity: 1;
+        transform: scale(2);
     }
 
     .documentDecorations-topRightResizer {
@@ -339,7 +359,6 @@ $resizeHandler: 8px;
 
     .documentDecorations-topRightResizer:hover,
     .documentDecorations-bottomLeftResizer:hover {
-        cursor: nesw-resize;
         background: black;
         opacity: 1;
     }
@@ -392,6 +411,7 @@ $resizeHandler: 8px;
     justify-content: center;
     align-items: center;
     gap: 5px;
+    top: 4px;
     background: $light-gray;
 }
 
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 9881ef9f1..6cf7df357 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -140,6 +140,16 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         }
     };
 
+    @action onContainerDown = (e: React.PointerEvent): void => {
+        setupMoveUpEvents(
+            this,
+            e,
+            e => this.onBackgroundMove(true, e),
+            e => {},
+            emptyFunction
+        );
+    };
+
     @action onTitleDown = (e: React.PointerEvent): void => {
         setupMoveUpEvents(
             this,
@@ -311,6 +321,27 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         );
     };
 
+    @action
+    onLockDown = (e: React.PointerEvent): void => {
+        // Call util move event function
+        setupMoveUpEvents(
+            this, // target
+            e, // pointerEvent
+            returnFalse, // moveEvent
+            emptyFunction, // upEvent
+            e => {
+                UndoManager.RunInBatch(
+                    () =>
+                        SelectionManager.Views().map(dv => {
+                            dv.rootDoc._lockedPosition = !dv.rootDoc._lockedPosition;
+                            dv.rootDoc._pointerEvents = dv.rootDoc._lockedPosition ? 'none' : undefined;
+                        }),
+                    'toggleBackground'
+                );
+            } // clickEvent
+        );
+    };
+
     setRotateCenter = (seldocview: DocumentView, rotCenter: number[]) => {
         const newloccentern = seldocview.props.ScreenToLocalTransform().transformPoint(rotCenter[0], rotCenter[1]);
         const newlocenter = [newloccentern[0] - NumCast(seldocview.layoutDoc._width) / 2, newloccentern[1] - NumCast(seldocview.layoutDoc._height) / 2];
@@ -791,7 +822,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                                 width: bounds.r - bounds.x + this._resizeBorderWidth + 'px',
                                 height: bounds.b - bounds.y + this._resizeBorderWidth + this._titleHeight + 'px',
                             }}>
-                            <div className="documentDecorations-topbar">
+                            <div className="documentDecorations-topbar" onPointerDown={this.onContainerDown}>
                                 {hideDeleteButton ? <div /> : topBtn('close', 'times', undefined, e => this.onCloseClick(true), 'Close')}
                                 {hideResizers || hideDeleteButton ? <div /> : topBtn('minimize', 'window-maximize', undefined, e => this.onCloseClick(undefined), 'Minimize')}
                                 {hideResizers ? <div /> : titleArea}
@@ -817,21 +848,23 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                                     key="rad"
                                     style={{
                                         background: `${this._isRounding ? Colors.MEDIUM_BLUE : undefined}`,
-                                        left: `${radiusHandleLocation + 3}`,
-                                        top: `${radiusHandleLocation + 23}`,
+                                        transform: `translate(${radiusHandleLocation}px, ${radiusHandleLocation}px)`,
                                     }}
                                     className={`documentDecorations-borderRadius`}
                                     onPointerDown={this.onRadiusDown}
                                     onContextMenu={e => e.preventDefault()}
                                 />
                             )}
+                            <div key="lock" className="documentDecorations-lock" style={{ color: seldocview.rootDoc._lockedPosition ? 'red' : undefined }} onPointerDown={this.onLockDown} onContextMenu={e => e.preventDefault()}>
+                                <FontAwesomeIcon size="sm" icon="lock" />
+                            </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) `,
+                                        transform: `translate(${-this._resizeBorderWidth / 2 + 10}px, ${this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `,
                                     }}>
                                     <DocumentButtonBar views={SelectionManager.Views} />
                                 </div>
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 23b03bc50..362aa3c86 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -1,7 +1,7 @@
 import React = require('react');
 import * as fitCurve from 'fit-curve';
 import { action, computed, observable, runInAction, trace } from 'mobx';
-import { Doc } from '../../fields/Doc';
+import { Doc, Opt } from '../../fields/Doc';
 import { InkData, InkTool } from '../../fields/InkField';
 import { List } from '../../fields/List';
 import { ScriptField } from '../../fields/ScriptField';
@@ -49,7 +49,7 @@ interface GestureOverlayProps {
 export class GestureOverlay extends Touchable<GestureOverlayProps> {
     static Instance: GestureOverlay;
 
-    @observable public InkShape: string = '';
+    @observable public InkShape: Opt<GestureUtils.Gestures>;
     @observable public SavedColor?: string;
     @observable public SavedWidth?: number;
     @observable public Tool: ToolglassTools = ToolglassTools.None;
@@ -644,8 +644,6 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
         if (this._points.length > 1) {
             const B = this.svgBounds;
             const points = this._points.map(p => ({ X: p.X - B.left, Y: p.Y - B.top }));
-            //push first points to so interactionUtil knows pointer is up
-            this._points.push({ X: this._points[0].X, Y: this._points[0].Y });
 
             const initialPoint = this._points[0];
             const xInGlass = initialPoint.X > (this._thumbX ?? Number.MAX_SAFE_INTEGER) && initialPoint.X < (this._thumbX ?? Number.MAX_SAFE_INTEGER) + this.height;
@@ -685,10 +683,10 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
             //if any of the shape is activated in the CollectionFreeFormViewChrome
             else if (this.InkShape) {
                 this.makeBezierPolygon(this.InkShape, false);
-                this.dispatchGesture(GestureUtils.Gestures.Stroke);
+                this.dispatchGesture(this.InkShape);
                 this._points.length = 0;
                 if (!CollectionFreeFormViewChrome.Instance?._keepPrimitiveMode) {
-                    this.InkShape = '';
+                    this.InkShape = undefined;
                     Doc.ActiveTool = InkTool.None;
                 }
             }
@@ -703,12 +701,13 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
                         case GestureUtils.Gestures.Rectangle:
                         case GestureUtils.Gestures.Circle:
                             this.makeBezierPolygon(result.Name, true);
-                        case GestureUtils.Gestures.StartBracket:
-                        case GestureUtils.Gestures.EndBracket:
                             actionPerformed = this.dispatchGesture(result.Name);
                             break;
                         case GestureUtils.Gestures.Line:
-                            actionPerformed = this.handleLineGesture();
+                            if (!(actionPerformed = this.handleLineGesture())) {
+                                this.makeBezierPolygon(result.Name, true);
+                                actionPerformed = this.dispatchGesture(GestureUtils.Gestures.Stroke);
+                            }
                             break;
                         case GestureUtils.Gestures.Scribble:
                             console.log('scribble');
@@ -972,7 +971,7 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
                                 ActiveDash(),
                                 1,
                                 1,
-                                this.InkShape,
+                                this.InkShape ?? '',
                                 'none',
                                 1.0,
                                 false
@@ -999,7 +998,7 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
                             ActiveDash(),
                             1,
                             1,
-                            this.InkShape,
+                            this.InkShape ?? '',
                             'none',
                             1.0,
                             false
diff --git a/src/client/views/StyleProvider.scss b/src/client/views/StyleProvider.scss
index 8929954c8..b1c97164a 100644
--- a/src/client/views/StyleProvider.scss
+++ b/src/client/views/StyleProvider.scss
@@ -1,11 +1,11 @@
 .styleProvider-lock {
-    font-size: 12px;
-    width: 20; 
-    height: 20; 
-    position: absolute; 
-    right: -25; 
-    top: -5;
-    background: transparent;
+    font-size: 10;
+    width: 15;
+    height: 15;
+    position: absolute;
+    right: -0;
+    top: 0;
+    background: black;
     pointer-events: all;
     opacity: 0.3;
     display: flex;
@@ -15,7 +15,7 @@
     cursor: default;
 }
 .styleProvider-lock:hover {
-    opacity:1;
+    opacity: 1;
 }
 
 .styleProvider-treeView-icon,
@@ -26,4 +26,4 @@
 
 .styleProvider-treeView-icon {
     opacity: 0;
-}
\ No newline at end of file
+}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index aadcd7169..a5a886f42 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -276,7 +276,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
         case StyleProp.Decorations:
             if (props?.ContainingCollectionDoc?._viewType === CollectionViewType.Freeform || doc?.x !== undefined || doc?.y !== undefined) {
                 return doc &&
-                    (isBackground() || selected) &&
+                    isBackground() &&
                     !Doc.IsSystem(doc) &&
                     (props?.renderDepth || 0) > 0 &&
                     ((doc.type === DocumentType.COL && doc._viewType !== CollectionViewType.Pile) || [DocumentType.RTF, DocumentType.IMG, DocumentType.INK].includes(doc.type as DocumentType)) ? (
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index daf69d4f6..983cf4f9b 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -568,6 +568,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     @undoBatch
     onGesture = (e: Event, ge: GestureUtils.GestureEvent) => {
         switch (ge.gesture) {
+            case GestureUtils.Gestures.Line:
+                break;
             default:
             case GestureUtils.Gestures.Circle:
             case GestureUtils.Gestures.Rectangle:
@@ -602,33 +604,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 e.stopPropagation();
                 break;
             case GestureUtils.Gestures.Rectangle:
-                const lt = this.getTransform().transformPoint(Math.min(...ge.points.map(p => p.X)), Math.min(...ge.points.map(p => p.Y)));
-                const rb = this.getTransform().transformPoint(Math.max(...ge.points.map(p => p.X)), Math.max(...ge.points.map(p => p.Y)));
-                const bounds = { x: lt[0], r: rb[0], y: lt[1], b: rb[1] };
-                const bWidth = bounds.r - bounds.x;
-                const bHeight = bounds.b - bounds.y;
-                const sel = this.getActiveDocuments().filter(doc => {
-                    const l = NumCast(doc.x);
-                    const r = l + doc[WidthSym]();
-                    const t = NumCast(doc.y);
-                    const b = t + doc[HeightSym]();
-                    const pass = !(bounds.x > r || bounds.r < l || bounds.y > b || bounds.b < t);
-                    if (pass) {
-                        doc.x = l - bounds.x - bWidth / 2;
-                        doc.y = t - bounds.y - bHeight / 2;
-                    }
-                    return pass;
-                });
-                this.addDocument(Docs.Create.FreeformDocument(sel, { title: 'nested collection', x: bounds.x, y: bounds.y, _width: bWidth, _height: bHeight, _panX: 0, _panY: 0 }));
-                sel.forEach(d => this.props.removeDocument?.(d));
-                e.stopPropagation();
-                break;
-            case GestureUtils.Gestures.StartBracket:
-                const start = this.getTransform().transformPoint(Math.min(...ge.points.map(p => p.X)), Math.min(...ge.points.map(p => p.Y)));
-                this._inkToTextStartX = start[0];
-                this._inkToTextStartY = start[1];
-                break;
-            case GestureUtils.Gestures.EndBracket:
                 if (this._inkToTextStartX && this._inkToTextStartY) {
                     const end = this.getTransform().transformPoint(Math.max(...ge.points.map(p => p.X)), Math.max(...ge.points.map(p => p.Y)));
                     const setDocs = this.getActiveDocuments().filter(s => s.proto?.type === 'rtf' && s.color);
@@ -805,15 +780,15 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 const prevPointInkSpace = inkStroke.ptFromScreen(lastPoint);
                 const currPointInkSpace = inkStroke.ptFromScreen(currPoint);
                 for (var i = 0; i < inkData.length - 3; i += 4) {
-                    const intersects = Array.from(
-                        new Set(
-                            InkField.Segment(inkData, i).intersects({
-                                // compute all unique intersections
-                                p1: { x: prevPointInkSpace.X, y: prevPointInkSpace.Y },
-                                p2: { x: currPointInkSpace.X, y: currPointInkSpace.Y },
-                            }) as (number | string)[]
-                        )
-                    ); // convert to more manageable union array type
+                    const rawIntersects = InkField.Segment(inkData, i).intersects({
+                        // compute all unique intersections
+                        p1: { x: prevPointInkSpace.X, y: prevPointInkSpace.Y },
+                        p2: { x: currPointInkSpace.X, y: currPointInkSpace.Y },
+                    });
+                    const intersects = Array.from(new Set(rawIntersects as (number | string)[])); // convert to more manageable union array type
+                    if (intersects.length) {
+                        console.log();
+                    }
                     // return tuples of the inkingStroke intersected, and the t value of the intersection
                     intersections.push(...intersects.map(t => ({ inkView, t: +t + Math.floor(i / 4) }))); // convert string t's to numbers and add start of curve segment to convert from local t value to t value along complete curve
                 }
@@ -862,6 +837,15 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         return segments;
     };
 
+    // for some reason bezier.js doesn't handle the case of intersecting a linear curve, so we wrap the intersection
+    // call in a test for linearity
+    bintersects = (curve: Bezier, otherCurve: Bezier) => {
+        if ((otherCurve as any)._linear) {
+            return curve.lineIntersects({ p1: otherCurve.points[0], p2: otherCurve.points[3] });
+        }
+        return curve.intersects(otherCurve);
+    };
+
     /**
      * Determines all possible intersections of the current curve of the intersected ink stroke with all other curves of all
      * ink strokes in the current collection.
@@ -886,7 +870,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                     if (ink?.Document === otherInk.props.Document && neighboringSegment) continue;
 
                     const otherCurve = new Bezier(otherCtrlPts.slice(j, j + 4).map(p => ({ x: p.X, y: p.Y })));
-                    curve.intersects(otherCurve).forEach((val: string | number, i: number) => {
+                    this.bintersects(curve, otherCurve).forEach((val: string | number, i: number) => {
                         // Converting the Bezier.js Split type to a t-value number.
                         const t = +val.toString().split('/')[0];
                         if (i % 2 === 0 && !tVals.includes(t)) tVals.push(t); // bcz: Hack!  don't know why but intersection points are doubled from bezier.js (but not identical).
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 1c48d47e9..040e03150 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1082,7 +1082,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     <DocumentLinksButton
                         View={this.props.DocumentView()}
                         scaling={this.linkButtonInverseScaling}
-                        Offset={[this.topMost ? 0 : !this.props.isSelected() ? -15 : -36, undefined, undefined, this.topMost ? 10 : !this.props.isSelected() ? -15 : -28]}
+                        Offset={[this.topMost ? 0 : !this.props.isSelected() ? -15 : -36, undefined, undefined, this.topMost ? 10 : !this.props.isSelected() ? -15 : -32]}
                     />
                 )}
                 {audioView}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 959c641a8..461d6984d 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -8,7 +8,7 @@ import { List } from '../../../fields/List';
 import { ObjectField } from '../../../fields/ObjectField';
 import { createSchema } from '../../../fields/Schema';
 import { ComputedField } from '../../../fields/ScriptField';
-import { Cast, NumCast } from '../../../fields/Types';
+import { Cast, NumCast, StrCast } from '../../../fields/Types';
 import { ImageField } from '../../../fields/URLField';
 import { TraceMobx } from '../../../fields/util';
 import { emptyFunction, OmitKeys, returnFalse, returnOne, setupMoveUpEvents, Utils } from '../../../Utils';
@@ -77,10 +77,11 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
             ({ forceFull, scrSize, selected }) => (this._curSuffix = selected ? '_o' : this.fieldKey === 'icon' ? '_m' : forceFull ? '_o' : scrSize < 0.25 ? '_s' : scrSize < 0.5 ? '_m' : scrSize < 0.8 ? '_l' : '_o'),
             { fireImmediately: true, delay: 1000 }
         );
+        const layoutDoc = this.layoutDoc;
         this._disposers.path = reaction(
             () => ({ nativeSize: this.nativeSize, width: this.layoutDoc[WidthSym]() }),
             ({ nativeSize, width }) => {
-                if (true || !this.layoutDoc._height) {
+                if (layoutDoc === this.layoutDoc || !this.layoutDoc._height) {
                     this.layoutDoc._height = (width * nativeSize.nativeHeight) / nativeSize.nativeWidth;
                 }
             },
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index 6eaf3c31a..fd0c0d141 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -771,36 +771,26 @@ export function createInkGroup(inksToGroup?: Doc[], isSubGroup?: boolean) {
     CollectionFreeFormView.collectionsWithUnprocessedInk.clear();
 }
 
-/** INK
- *      setActiveTool
- *      setStrokeWidth
- *      setStrokeColor
- **/
-
-ScriptingGlobals.add(function setActiveTool(tool: string, checkResult?: boolean) {
+ScriptingGlobals.add(function setActiveTool(tool: InkTool | GestureUtils.Gestures, checkResult?: boolean) {
     InkTranscription.Instance?.createInkGroup();
     if (checkResult) {
         return (Doc.ActiveTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool ? Colors.MEDIUM_BLUE : 'transparent';
     }
-    if ([GestureUtils.Gestures.Circle, GestureUtils.Gestures.Rectangle, GestureUtils.Gestures.Line, GestureUtils.Gestures.Triangle].includes(tool as any)) {
+    if (Object.values(GestureUtils.Gestures).includes(tool as any)) {
         if (GestureOverlay.Instance.InkShape === tool) {
             Doc.ActiveTool = InkTool.None;
-            GestureOverlay.Instance.InkShape = InkTool.None;
+            GestureOverlay.Instance.InkShape = undefined;
         } else {
             Doc.ActiveTool = InkTool.Pen;
-            GestureOverlay.Instance.InkShape = tool;
+            GestureOverlay.Instance.InkShape = tool as GestureUtils.Gestures;
         }
     } else if (tool) {
         // pen or eraser
         if (Doc.ActiveTool === tool && !GestureOverlay.Instance.InkShape) {
             Doc.ActiveTool = InkTool.None;
-        } else if (tool == InkTool.Write) {
-            // console.log("write mode selected - create groupDoc here!", tool)
-            Doc.ActiveTool = tool;
-            GestureOverlay.Instance.InkShape = '';
         } else {
             Doc.ActiveTool = tool as any;
-            GestureOverlay.Instance.InkShape = '';
+            GestureOverlay.Instance.InkShape = undefined;
         }
     } else {
         Doc.ActiveTool = InkTool.None;
diff --git a/src/pen-gestures/GestureUtils.ts b/src/pen-gestures/GestureUtils.ts
index 2d3b1fdb8..41917aac9 100644
--- a/src/pen-gestures/GestureUtils.ts
+++ b/src/pen-gestures/GestureUtils.ts
@@ -19,8 +19,6 @@ export namespace GestureUtils {
 
     export enum Gestures {
         Line = 'line',
-        StartBracket = 'startbracket',
-        EndBracket = 'endbracket',
         Stroke = 'stroke',
         Scribble = 'scribble',
         Text = 'text',
diff --git a/src/pen-gestures/ndollar.ts b/src/pen-gestures/ndollar.ts
index b10a9da17..3ee9506cb 100644
--- a/src/pen-gestures/ndollar.ts
+++ b/src/pen-gestures/ndollar.ts
@@ -145,7 +145,7 @@ export class Result {
 //
 // NDollarRecognizer constants
 //
-const NumMultistrokes = 6;
+let NumMultistrokes = 0;
 const NumPoints = 96;
 const SquareSize = 250.0;
 const OneDThreshold = 0.25; // customize to desired gesture set (usually 0.20 - 0.35)
@@ -162,73 +162,59 @@ const AngleSimilarityThreshold = Deg2Rad(30.0);
 // NDollarRecognizer class
 //
 export class NDollarRecognizer {
-    public Multistrokes: Multistroke[];
+    public Multistrokes: Multistroke[] = [];
 
-    /**
-     * @IMPORTANT - IF YOU'RE ADDING A NEW GESTURE, BE SURE TO INCREMENT THE NumMultiStrokes CONST RIGHT ABOVE THIS CLASS.
-     */
     constructor(
         useBoundedRotationInvariance: boolean // constructor
     ) {
         //
         // one predefined multistroke for each multistroke type
         //
-        this.Multistrokes = new Array(NumMultistrokes);
-        this.Multistrokes[0] = new Multistroke(
-            GestureUtils.Gestures.Rectangle,
-            useBoundedRotationInvariance,
-            new Array(
+        this.Multistrokes.push(
+            new Multistroke(
+                GestureUtils.Gestures.Rectangle,
+                useBoundedRotationInvariance,
                 new Array(
-                    new Point(30, 146), //new Point(29, 160), new Point(30, 180), new Point(31, 200),
-                    new Point(30, 222), //new Point(50, 219), new Point(70, 225), new Point(90, 230),
-                    new Point(106, 225), //new Point(100, 200), new Point(106, 180), new Point(110, 160),
-                    new Point(106, 146), //new Point(80, 150), new Point(50, 146),
-                    new Point(30, 143)
+                    new Array(
+                        new Point(30, 146), //new Point(29, 160), new Point(30, 180), new Point(31, 200),
+                        new Point(30, 222), //new Point(50, 219), new Point(70, 225), new Point(90, 230),
+                        new Point(106, 225), //new Point(100, 200), new Point(106, 180), new Point(110, 160),
+                        new Point(106, 146), //new Point(80, 150), new Point(50, 146),
+                        new Point(30, 143)
+                    )
                 )
             )
         );
-        this.Multistrokes[1] = new Multistroke(GestureUtils.Gestures.Line, useBoundedRotationInvariance, new Array(new Array(new Point(12, 347), new Point(119, 347))));
-        this.Multistrokes[2] = new Multistroke(
-            GestureUtils.Gestures.StartBracket,
-            useBoundedRotationInvariance,
-            new Array(
-                // new Array(new Point(145, 20), new Point(30, 21), new Point(34, 150))
-                new Array(new Point(31, 25), new Point(145, 20), new Point(31, 25), new Point(34, 150))
+        this.Multistrokes.push(new Multistroke(GestureUtils.Gestures.Line, useBoundedRotationInvariance, new Array(new Array(new Point(12, 347), new Point(119, 347)))));
+        this.Multistrokes.push(
+            new Multistroke(
+                GestureUtils.Gestures.Triangle, // equilateral
+                useBoundedRotationInvariance,
+                new Array(new Array(new Point(40, 100), new Point(100, 200), new Point(140, 102), new Point(42, 100)))
             )
         );
-        this.Multistrokes[3] = new Multistroke(
-            GestureUtils.Gestures.EndBracket,
-            useBoundedRotationInvariance,
-            new Array(
-                // new Array(new Point(150, 21), new Point(149, 150), new Point(26, 152))
-                // new Array(new Point(150, 150), new Point(150, 0), new Point(150, 150), new Point(0, 150))
-                new Array(new Point(10, 100), new Point(100, 100), new Point(150, 12), new Point(200, 103), new Point(300, 100))
-            )
-        );
-        this.Multistrokes[4] = new Multistroke(
-            GestureUtils.Gestures.Triangle, // equilateral
-            useBoundedRotationInvariance,
-            new Array(new Array(new Point(40, 100), new Point(100, 200), new Point(140, 102), new Point(42, 100)))
-        );
-        this.Multistrokes[5] = new Multistroke(
-            GestureUtils.Gestures.Circle,
-            useBoundedRotationInvariance,
-            new Array(
+        this.Multistrokes.push(
+            new Multistroke(
+                GestureUtils.Gestures.Circle,
+                useBoundedRotationInvariance,
                 new Array(
-                    new Point(200, 250),
-                    new Point(240, 230),
-                    new Point(248, 210),
-                    new Point(248, 190),
-                    new Point(240, 170),
-                    new Point(200, 150),
-                    new Point(160, 170),
-                    new Point(151, 190),
-                    new Point(151, 210),
-                    new Point(160, 230),
-                    new Point(201, 250)
+                    new Array(
+                        new Point(200, 250),
+                        new Point(240, 230),
+                        new Point(248, 210),
+                        new Point(248, 190),
+                        new Point(240, 170),
+                        new Point(200, 150),
+                        new Point(160, 170),
+                        new Point(151, 190),
+                        new Point(151, 210),
+                        new Point(160, 230),
+                        new Point(201, 250)
+                    )
                 )
             )
         );
+        NumMultistrokes = this.Multistrokes.length; // NumMultistrokes flags the end of the non user-defined gstures strokes
         //
         // PREDEFINED STROKES
         //
-- 
cgit v1.2.3-70-g09d2


From 5df8e9041e7a0e8ac98f0c911a2b603c0d8e89d3 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 20 Oct 2022 11:07:04 -0400
Subject: added double-tap to keep ink primitive mode.  cleaned up circle
 drawing and some other gesture code.

---
 src/client/util/CurrentUserUtils.ts                | 14 ++---
 src/client/util/InteractionUtils.tsx               |  6 +-
 src/client/views/GestureOverlay.tsx                | 69 +++++++---------------
 src/client/views/collections/CollectionMenu.tsx    |  7 ++-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  3 +-
 src/client/views/nodes/DocumentView.tsx            |  2 +-
 src/client/views/nodes/button/FontIconBox.tsx      | 51 +++++++++-------
 7 files changed, 68 insertions(+), 84 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index bfa868dbc..2bc464127 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -46,7 +46,7 @@ interface Button {
     buttonText?: string;
 
     // fields that do not correspond to DocumentOption fields
-    scripts?: { script?: string; onClick?: string; }
+    scripts?: { script?: string; onClick?: string; onDoubleClick?: string }
     funcs?: { [key:string]: string };
     subMenu?: Button[];
 }
@@ -628,13 +628,13 @@ export class CurrentUserUtils {
 
     static inkTools():Button[] {
         return [
-            { title: "Pen",    toolTip: "Pen (Ctrl+P)",          btnType: ButtonType.ToggleButton, icon: "pen-nib",                     scripts: {onClick:'{ return setActiveTool("pen", _readOnly_);}' }},
-            { title: "Write",  toolTip: "Write (Ctrl+Shift+P)",  btnType: ButtonType.ToggleButton, icon: "pen",                         scripts: {onClick:'{ return setActiveTool("write", _readOnly_);}'} },
-            { title: "Eraser", toolTip: "Eraser (Ctrl+E)",       btnType: ButtonType.ToggleButton, icon: "eraser",                      scripts: {onClick:'{ return setActiveTool("eraser", _readOnly_);}' }},
+            { title: "Pen",    toolTip: "Pen (Ctrl+P)",          btnType: ButtonType.ToggleButton, icon: "pen-nib",                     scripts: {onClick:'{ return setActiveTool("pen", false, _readOnly_);}' }},
+            { title: "Write",  toolTip: "Write (Ctrl+Shift+P)",  btnType: ButtonType.ToggleButton, icon: "pen",                         scripts: {onClick:'{ return setActiveTool("write", false, _readOnly_);}'} },
+            { title: "Eraser", toolTip: "Eraser (Ctrl+E)",       btnType: ButtonType.ToggleButton, icon: "eraser",                      scripts: {onClick:'{ return setActiveTool("eraser", false, _readOnly_);}' }},
             // { title: "Highlighter", toolTip: "Highlighter (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter", scripts:{onClick: 'setActiveTool("highlighter")'} },
-            { title: "Circle", toolTip: "Circle (Ctrl+Shift+C)", btnType: ButtonType.ToggleButton, icon: "circle",                      scripts: {onClick:`{ return setActiveTool("${GestureUtils.Gestures.Circle}", _readOnly_);}`} },
-            { title: "Square", toolTip: "Square (Ctrl+Shift+S)", btnType: ButtonType.ToggleButton, icon: "square",                      scripts: {onClick:`{ return setActiveTool("${GestureUtils.Gestures.Rectangle}", _readOnly_);}`} },
-            { title: "Line",   toolTip: "Line (Ctrl+Shift+L)",   btnType: ButtonType.ToggleButton, icon: "minus",                       scripts: {onClick:`{ return setActiveTool("${GestureUtils.Gestures.Line}", _readOnly_);}`} },
+            { title: "Circle", toolTip: "Circle (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "circle",                      scripts: {onClick:`{ return setActiveTool("${GestureUtils.Gestures.Circle}", false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool("${GestureUtils.Gestures.Circle}", true, _readOnly_);}`} },
+            { title: "Square", toolTip: "Square (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "square",                      scripts: {onClick:`{ return setActiveTool("${GestureUtils.Gestures.Rectangle}", false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool("${GestureUtils.Gestures.Rectangle}", true, _readOnly_);}`} },
+            { title: "Line",   toolTip: "Line (double tap to lock mode)",   btnType: ButtonType.ToggleButton, icon: "minus",                       scripts: {onClick:`{ return setActiveTool("${GestureUtils.Gestures.Line}", false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool("${GestureUtils.Gestures.Line}", true, _readOnly_);}`} },
             { title: "Mask",   toolTip: "Mask",                  btnType: ButtonType.ToggleButton, icon: "user-circle",                 scripts: {onClick:'{ return setIsInkMask(_readOnly_);}'} },
             { title: "Fill",   toolTip: "Fill color",            btnType: ButtonType.ColorButton,  icon: "fill-drip",ignoreClick: true, scripts: {script: '{ return setFillColor(value, _readOnly_);}'} },
             { title: "Width",  toolTip: "Stroke width",          btnType: ButtonType.NumberButton,                   ignoreClick: true, scripts: {script: '{ return setStrokeWidth(value, _readOnly_);}'}, numBtnType: NumButtonType.Slider, numBtnMin: 1},
diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx
index 6622b498d..3cdf4dbd2 100644
--- a/src/client/util/InteractionUtils.tsx
+++ b/src/client/util/InteractionUtils.tsx
@@ -242,16 +242,16 @@ export namespace InteractionUtils {
                 const centerX = (Math.max(left, right) + Math.min(left, right)) / 2;
                 const centerY = (Math.max(top, bottom) + Math.min(top, bottom)) / 2;
                 const radius = Math.max(centerX - Math.min(left, right), centerY - Math.min(top, bottom));
-                for (var x = Math.min(left, right); x < Math.max(left, right); x++) {
+                for (var x = centerX - radius; x < centerX + radius; x++) {
                     const y = Math.sqrt(Math.pow(radius, 2) - Math.pow(x - centerX, 2)) + centerY;
                     points.push({ X: x, Y: y });
                 }
-                for (var x = Math.max(left, right); x > Math.min(left, right); x--) {
+                for (var x = centerX + radius; x > centerX - radius; x--) {
                     const y = Math.sqrt(Math.pow(radius, 2) - Math.pow(x - centerX, 2)) + centerY;
                     const newY = centerY - (y - centerY);
                     points.push({ X: x, Y: newY });
                 }
-                points.push({ X: Math.min(left, right), Y: Math.sqrt(Math.pow(radius, 2) - Math.pow(Math.min(left, right) - centerX, 2)) + centerY });
+                points.push({ X: centerX - radius, Y: Math.sqrt(Math.pow(radius, 2) - Math.pow(-radius, 2)) + centerY });
                 break;
 
             case GestureUtils.Gestures.Line:
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 362aa3c86..a29073f14 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -16,7 +16,6 @@ import { InteractionUtils } from '../util/InteractionUtils';
 import { ScriptingGlobals } from '../util/ScriptingGlobals';
 import { SelectionManager } from '../util/SelectionManager';
 import { Transform } from '../util/Transform';
-import { CollectionFreeFormViewChrome } from './collections/CollectionMenu';
 import './GestureOverlay.scss';
 import {
     ActiveArrowEnd,
@@ -53,6 +52,7 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
     @observable public SavedColor?: string;
     @observable public SavedWidth?: number;
     @observable public Tool: ToolglassTools = ToolglassTools.None;
+    @observable public KeepPrimitiveMode = false; // for whether primitive selection enters a one-shot or persistent mode
 
     @observable private _thumbX?: number;
     @observable private _thumbY?: number;
@@ -616,29 +616,16 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
         return false;
     };
 
-    handleLineGesture = (): boolean => {
-        const actionPerformed = false;
-        const B = this.svgBounds;
-
-        // get the two targets at the ends of the line
-        const ep1 = this._points[0];
-        const ep2 = this._points.lastElement();
-        const target1 = document.elementFromPoint(ep1.X, ep1.Y);
-        const target2 = document.elementFromPoint(ep2.X, ep2.Y);
-
-        const ge = new CustomEvent<GestureUtils.GestureEvent>('dashOnGesture', {
-            bubbles: true,
-            detail: {
-                points: this._points.slice(),
-                gesture: GestureUtils.Gestures.Line,
-                bounds: B,
-            },
-        });
-        target1?.dispatchEvent(ge);
-        target2?.dispatchEvent(ge);
-        return actionPerformed;
-    };
-
+    @action primCreated() {
+        if (!this.KeepPrimitiveMode) {
+            this.InkShape = undefined;
+            //get out of ink mode after each stroke=
+            //if (Doc.ActiveTool === InkTool.Highlighter && GestureOverlay.Instance.SavedColor) SetActiveInkColor(GestureOverlay.Instance.SavedColor);
+            Doc.ActiveTool = InkTool.None;
+            // SetActiveArrowStart('none');
+            // SetActiveArrowEnd('none');
+        }
+    }
     @action
     onPointerUp = (e: PointerEvent) => {
         if (this._points.length > 1) {
@@ -654,7 +641,6 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
                 switch (this.Tool) {
                     case ToolglassTools.InkToText:
                         this._strokes.push(this._points.slice());
-                        this._points.length = 0;
                         CognitiveServices.Inking.Appliers.InterpretStrokes(this._strokes).then(results => {
                             const wordResults = results.filter((r: any) => r.category === 'line');
                             const possibilities: string[] = [];
@@ -676,7 +662,6 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
                         break;
                     case ToolglassTools.IgnoreGesture:
                         this.dispatchGesture(GestureUtils.Gestures.Stroke);
-                        this._points.length = 0;
                         break;
                 }
             }
@@ -684,11 +669,7 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
             else if (this.InkShape) {
                 this.makeBezierPolygon(this.InkShape, false);
                 this.dispatchGesture(this.InkShape);
-                this._points.length = 0;
-                if (!CollectionFreeFormViewChrome.Instance?._keepPrimitiveMode) {
-                    this.InkShape = undefined;
-                    Doc.ActiveTool = InkTool.None;
-                }
+                this.primCreated();
             }
             // if we're not drawing in a toolglass try to recognize as gesture
             else {
@@ -697,18 +678,13 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
                 let actionPerformed = false;
                 if (Doc.UserDoc().recognizeGestures && result && result.Score > 0.7) {
                     switch (result.Name) {
+                        case GestureUtils.Gestures.Line:
                         case GestureUtils.Gestures.Triangle:
                         case GestureUtils.Gestures.Rectangle:
                         case GestureUtils.Gestures.Circle:
                             this.makeBezierPolygon(result.Name, true);
                             actionPerformed = this.dispatchGesture(result.Name);
                             break;
-                        case GestureUtils.Gestures.Line:
-                            if (!(actionPerformed = this.handleLineGesture())) {
-                                this.makeBezierPolygon(result.Name, true);
-                                actionPerformed = this.dispatchGesture(GestureUtils.Gestures.Stroke);
-                            }
-                            break;
                         case GestureUtils.Gestures.Scribble:
                             console.log('scribble');
                             break;
@@ -741,12 +717,9 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
                     // TODO: nda - check inks to group here
                     checkInksToGroup();
                 }
-                this._points.length = 0;
             }
-        } else {
-            this._points.length = 0;
         }
-        CollectionFreeFormViewChrome.Instance?.primCreated();
+        this._points.length = 0;
     };
 
     makeBezierPolygon = (shape: string, gesture: boolean) => {
@@ -901,17 +874,17 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> {
         return false;
     };
 
-    dispatchGesture = (gesture: GestureUtils.Gestures, stroke?: InkData, data?: any) => {
-        const target = document.elementFromPoint((stroke ?? this._points)[0].X, (stroke ?? this._points)[0].Y);
+    dispatchGesture = (gesture: GestureUtils.Gestures, stroke?: InkData, text?: any) => {
+        const points = (stroke ?? this._points).slice();
         return (
-            target?.dispatchEvent(
+            document.elementFromPoint(points[0].X, points[0].Y)?.dispatchEvent(
                 new CustomEvent<GestureUtils.GestureEvent>('dashOnGesture', {
                     bubbles: true,
                     detail: {
-                        points: stroke ?? this._points.slice(),
-                        gesture: gesture as any,
-                        bounds: this.getBounds(stroke ?? this._points),
-                        text: data,
+                        points,
+                        gesture,
+                        bounds: this.getBounds(points),
+                        text,
                     },
                 })
             ) || false
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 46e8494ab..db81f28f6 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -40,6 +40,7 @@ import { CollectionLinearView } from './collectionLinear';
 import './CollectionMenu.scss';
 import { COLLECTION_BORDER_WIDTH } from './CollectionView';
 import { TabDocView } from './TabDocView';
+import { GestureUtils } from '../../../pen-gestures/GestureUtils';
 
 interface CollectionMenuProps {
     panelHeight: () => number;
@@ -767,7 +768,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionView
     private _draw = ['∿', '=', '⎯', '→', '↔︎', 'ロ', 'O'];
     private _head = ['', '', '', '', 'arrow', '', ''];
     private _end = ['', '', '', 'arrow', 'arrow', '', ''];
-    private _shapePrims = ['', '', 'line', 'line', 'line', 'rectangle', 'circle'];
+    private _shapePrims = ['', '', 'line', 'line', 'line', 'rectangle', 'circle'] as GestureUtils.Gestures[];
     private _title = ['pen', 'highlighter', 'line', 'line with arrow', 'line with double arrows', 'square', 'circle'];
     private _faName = ['pen-fancy', 'highlighter', 'minus', 'long-arrow-alt-right', 'arrows-alt-h', 'square', 'circle'];
     @observable _selectedPrimitive = this._shapePrims.length;
@@ -848,13 +849,13 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionView
                 SetActiveArrowEnd(this._end[i]);
                 SetActiveBezierApprox('300');
 
-                GestureOverlay.Instance.InkShape = this._shapePrims[i];
+                if (GestureOverlay.Instance) GestureOverlay.Instance.InkShape = this._shapePrims[i];
             } else {
                 this._selectedPrimitive = this._shapePrims.length;
                 Doc.ActiveTool = InkTool.None;
                 SetActiveArrowStart('');
                 SetActiveArrowEnd('');
-                GestureOverlay.Instance.InkShape = '';
+                if (GestureOverlay.Instance) GestureOverlay.Instance.InkShape = undefined;
                 SetActiveBezierApprox('0');
             }
             e.stopPropagation();
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 983cf4f9b..7b93408c3 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -568,9 +568,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     @undoBatch
     onGesture = (e: Event, ge: GestureUtils.GestureEvent) => {
         switch (ge.gesture) {
-            case GestureUtils.Gestures.Line:
-                break;
             default:
+            case GestureUtils.Gestures.Line:
             case GestureUtils.Gestures.Circle:
             case GestureUtils.Gestures.Rectangle:
             case GestureUtils.Gestures.Triangle:
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 040e03150..16b5809fa 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -655,7 +655,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         }
         this._downX = e.clientX;
         this._downY = e.clientY;
-        if (Doc.ActiveTool === InkTool.None && !(this.props.Document.rootDocument && !(e.ctrlKey || e.button > 0))) {
+        if ((Doc.ActiveTool === InkTool.None || this.props.addDocTab === returnFalse) && !(this.props.Document.rootDocument && !(e.ctrlKey || e.button > 0))) {
             // if this is part of a template, let the event go up to the tempalte root unless right/ctrl clicking
             if (
                 (this.props.isDocumentActive?.() || this.layoutDoc.onDragStart) &&
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index fd0c0d141..883c4460b 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -771,31 +771,42 @@ export function createInkGroup(inksToGroup?: Doc[], isSubGroup?: boolean) {
     CollectionFreeFormView.collectionsWithUnprocessedInk.clear();
 }
 
-ScriptingGlobals.add(function setActiveTool(tool: InkTool | GestureUtils.Gestures, checkResult?: boolean) {
+function setActiveTool(tool: InkTool | GestureUtils.Gestures, keepPrim: boolean, checkResult?: boolean) {
     InkTranscription.Instance?.createInkGroup();
     if (checkResult) {
-        return (Doc.ActiveTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool ? Colors.MEDIUM_BLUE : 'transparent';
-    }
-    if (Object.values(GestureUtils.Gestures).includes(tool as any)) {
-        if (GestureOverlay.Instance.InkShape === tool) {
-            Doc.ActiveTool = InkTool.None;
-            GestureOverlay.Instance.InkShape = undefined;
-        } else {
-            Doc.ActiveTool = InkTool.Pen;
-            GestureOverlay.Instance.InkShape = tool as GestureUtils.Gestures;
+        return (Doc.ActiveTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool
+            ? GestureOverlay.Instance?.KeepPrimitiveMode || ![GestureUtils.Gestures.Circle, GestureUtils.Gestures.Line, GestureUtils.Gestures.Rectangle].includes(tool as GestureUtils.Gestures)
+                ? Colors.MEDIUM_BLUE
+                : Colors.MEDIUM_BLUE_ALT
+            : 'transparent';
+    }
+    runInAction(() => {
+        if (GestureOverlay.Instance) {
+            GestureOverlay.Instance.KeepPrimitiveMode = keepPrim;
         }
-    } else if (tool) {
-        // pen or eraser
-        if (Doc.ActiveTool === tool && !GestureOverlay.Instance.InkShape) {
-            Doc.ActiveTool = InkTool.None;
+        if (Object.values(GestureUtils.Gestures).includes(tool as any)) {
+            if (GestureOverlay.Instance.InkShape === tool) {
+                Doc.ActiveTool = InkTool.None;
+                GestureOverlay.Instance.InkShape = undefined;
+            } else {
+                Doc.ActiveTool = InkTool.Pen;
+                GestureOverlay.Instance.InkShape = tool as GestureUtils.Gestures;
+            }
+        } else if (tool) {
+            // pen or eraser
+            if (Doc.ActiveTool === tool && !GestureOverlay.Instance.InkShape) {
+                Doc.ActiveTool = InkTool.None;
+            } else {
+                Doc.ActiveTool = tool as any;
+                GestureOverlay.Instance.InkShape = undefined;
+            }
         } else {
-            Doc.ActiveTool = tool as any;
-            GestureOverlay.Instance.InkShape = undefined;
+            Doc.ActiveTool = InkTool.None;
         }
-    } else {
-        Doc.ActiveTool = InkTool.None;
-    }
-});
+    });
+}
+
+ScriptingGlobals.add(setActiveTool, 'sets the active ink tool mode');
 
 // toggle: Set overlay status of selected document
 ScriptingGlobals.add(function setIsInkMask(checkResult?: boolean) {
-- 
cgit v1.2.3-70-g09d2


From 68ab5eb3dfa981d16ccb632a8dff015866ca13e2 Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Mon, 24 Oct 2022 14:55:44 -0400
Subject: added first draft version of scrolling up and scrolling sideways

---
 src/client/util/SettingsManager.tsx                | 18 ++++++++
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 50 ++++++++++++++++++----
 2 files changed, 60 insertions(+), 8 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index 92032a8f9..5c1c836f7 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -26,6 +26,11 @@ export enum ColorScheme {
     System = '-MatchSystem',
 }
 
+export enum freeformScrollMode {
+    Pan = 'pan',
+    Zoom = 'zoom'
+}
+
 @observer
 export class SettingsManager extends React.Component<{}> {
     public static Instance: SettingsManager;
@@ -302,6 +307,12 @@ export class SettingsManager extends React.Component<{}> {
         );
     }
 
+
+
+    setFreeformScrollMode = (mode: freeformScrollMode) => {
+        Doc.UserDoc().freeformScrollMode = mode;
+    }
+
     @computed get modesContent() {
         return (
             <div className="tab-content modes-content">
@@ -323,6 +334,13 @@ export class SettingsManager extends React.Component<{}> {
                             <div className="playground-text">Playground Mode</div>
                         </div>
                     </div>
+                    <div className="tab-column-title">Freeform scroll mode</div>
+                    <div>
+                        <button onClick={() => this.setFreeformScrollMode(freeformScrollMode.Pan)}>Scroll to pan</button>
+                        <div>Scrolling pans around the freeform, holding shift and scrolling zooms in and out.</div>
+                        <button onClick={() => this.setFreeformScrollMode(freeformScrollMode.Zoom)}>Scroll to zoom</button>
+                        <div>Scrolling zooms in and out of canvas</div>
+                    </div>
                 </div>
                 <div className="tab-column">
                     <div className="tab-column-title">Permissions</div>
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 7b93408c3..50ccc77cb 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -26,7 +26,7 @@ import { InteractionUtils } from '../../../util/InteractionUtils';
 import { ReplayMovements } from '../../../util/ReplayMovements';
 import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
 import { SelectionManager } from '../../../util/SelectionManager';
-import { ColorScheme } from '../../../util/SettingsManager';
+import { ColorScheme, freeformScrollMode } from '../../../util/SettingsManager';
 import { SnappingManager } from '../../../util/SnappingManager';
 import { Transform } from '../../../util/Transform';
 import { undoBatch, UndoManager } from '../../../util/UndoManager';
@@ -700,6 +700,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         }
     };
 
+    @action
+    scrollPan = (e: WheelEvent | { deltaX: number; deltaY: number }): void => {
+        const dx = e.deltaX;
+        const dy = e.deltaY;
+        console.log("2: ", dx, dy);
+        this.setPan(NumCast(this.Document._panX) - dx, NumCast(this.Document._panY) - dy, 0, true);
+    };
+
     @action
     pan = (e: PointerEvent | React.Touch | { clientX: number; clientY: number }): void => {
         const [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
@@ -999,13 +1007,39 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     @action
     onPointerWheel = (e: React.WheelEvent): void => {
         if (this.layoutDoc._Transform || DocListCast(Doc.MyOverlayDocs?.data).includes(this.props.Document) || this.props.Document.treeViewOutlineMode === TreeViewType.outline) return;
-        if (!e.ctrlKey && this.props.Document.scrollHeight !== undefined) {
-            // things that can scroll vertically should do that instead of zooming
-            e.stopPropagation();
-        } else if (this.props.isContentActive(true) && !this.Document._isGroup) {
-            e.stopPropagation();
-            e.preventDefault();
-            !this.props.isAnnotationOverlayScrollable && this.zoom(e.clientX, e.clientY, e.deltaY); // if (!this.props.isAnnotationOverlay) // bcz: do we want to zoom in on images/videos/etc?
+        e.stopPropagation();
+        e.preventDefault();
+        switch (Doc.UserDoc().freeformScrollMode) {
+            case freeformScrollMode.Pan:
+                // if shift is selected then zoom
+                if(e.ctrlKey) {
+                    if (!e.ctrlKey && this.props.Document.scrollHeight !== undefined) {
+                        // things that can scroll vertically should do that instead of zooming
+                    } else if (this.props.isContentActive(true) && !this.Document._isGroup) {
+                        !this.props.isAnnotationOverlayScrollable && this.zoom(e.clientX, e.clientY, e.deltaY); // if (!this.props.isAnnotationOverlay) // bcz: do we want to zoom in on images/videos/etc?
+                    }
+                // otherwise pan
+                } else if (!e.ctrlKey && this.props.Document.scrollHeight !== undefined) {
+                    // things that can scroll vertically should do that instead of zooming
+                } else if (this.props.isContentActive(true) && !this.Document._isGroup) {
+                    const dx = e.deltaX;
+                    const dy = e.deltaY;
+                    console.log("1: ", dx, dy);
+                    if (e.shiftKey) {
+                        !this.props.isAnnotationOverlayScrollable && this.scrollPan({ deltaX: dy, deltaY: 0 }); 
+                    } else {
+                        !this.props.isAnnotationOverlayScrollable && this.scrollPan({ deltaX: dx, deltaY: dy }); 
+                    }
+                }
+                break;
+            default:
+            case freeformScrollMode.Zoom:
+                if (!e.ctrlKey && this.props.Document.scrollHeight !== undefined) {
+                    // things that can scroll vertically should do that instead of zooming
+                } else if (this.props.isContentActive(true) && !this.Document._isGroup) {
+                    !this.props.isAnnotationOverlayScrollable && this.zoom(e.clientX, e.clientY, e.deltaY); // if (!this.props.isAnnotationOverlay) // bcz: do we want to zoom in on images/videos/etc?
+                }
+                break;
         }
     };
 
-- 
cgit v1.2.3-70-g09d2


From c06e87b8128acb9ed2570536fc500a2bb670abf4 Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Mon, 24 Oct 2022 14:58:03 -0400
Subject: removed print lines

---
 .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx     | 2 --
 1 file changed, 2 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 50ccc77cb..88422cbd4 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -704,7 +704,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     scrollPan = (e: WheelEvent | { deltaX: number; deltaY: number }): void => {
         const dx = e.deltaX;
         const dy = e.deltaY;
-        console.log("2: ", dx, dy);
         this.setPan(NumCast(this.Document._panX) - dx, NumCast(this.Document._panY) - dy, 0, true);
     };
 
@@ -1024,7 +1023,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 } else if (this.props.isContentActive(true) && !this.Document._isGroup) {
                     const dx = e.deltaX;
                     const dy = e.deltaY;
-                    console.log("1: ", dx, dy);
                     if (e.shiftKey) {
                         !this.props.isAnnotationOverlayScrollable && this.scrollPan({ deltaX: dy, deltaY: 0 }); 
                     } else {
-- 
cgit v1.2.3-70-g09d2


From ba73479fe6c0594ebe37eed6cf295e5adc49c8e1 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 25 Oct 2022 11:10:12 -0400
Subject: various tweaks: show border highlights in tree views, uniform
 treatment of embedding using title bar, even for free form views, choose
 bestAlias when dragging from files menu,  text boxes honor document moves,
 show title for timeline annotations, fix dragoffset for stacks with
 buttons/description headers,

---
 src/Utils.ts                                       |   6 +-
 src/client/util/DocumentManager.ts                 |   4 +-
 src/client/util/DragManager.ts                     |  18 ++-
 src/client/views/DocumentDecorations.tsx           |   7 +-
 src/client/views/StyleProvider.tsx                 |  17 ++-
 src/client/views/collections/CollectionSubView.tsx |   7 +-
 .../views/collections/CollectionTreeView.tsx       |   7 +-
 src/client/views/collections/TreeView.tsx          |  19 +--
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  32 +++--
 src/client/views/nodes/DocumentView.tsx            | 136 ++++++++++-----------
 .../views/nodes/formattedText/FormattedTextBox.tsx |   3 +
 src/fields/Doc.ts                                  |   5 +
 12 files changed, 133 insertions(+), 128 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/Utils.ts b/src/Utils.ts
index bf1f72774..5e0514bc6 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -728,10 +728,10 @@ export function getWordAtPoint(elem: any, x: number, y: number): string | undefi
     return undefined;
 }
 
-export function hasDescendantTarget(x: number, y: number, target: HTMLDivElement | null) {
+export function isTargetChildOf(ele: HTMLDivElement | null, target: Element | null) {
     let entered = false;
-    for (let child = document.elementFromPoint(x, y); !entered && child; child = child.parentElement) {
-        entered = entered || child === target;
+    for (let child = target; !entered && child; child = child.parentElement) {
+        entered = child === ele;
     }
     return entered;
 }
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 9a46d20de..b046d950f 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -335,9 +335,7 @@ export function DocFocusOrOpen(doc: Doc, collectionDoc?: Doc) {
     } else {
         const context = doc.context !== Doc.MyFilesystem && Cast(doc.context, Doc, null);
         const showDoc = context || doc;
-        const bestAlias = showDoc === Doc.GetProto(showDoc) ? DocListCast(showDoc.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail) : showDoc;
-
-        CollectionDockingView.AddSplit(bestAlias ? bestAlias : Doc.MakeAlias(showDoc), 'right') && context && setTimeout(() => DocumentManager.Instance.getDocumentView(Doc.GetProto(doc))?.focus(doc, {}));
+        CollectionDockingView.AddSplit(Doc.BestAlias(showDoc), 'right') && context && setTimeout(() => DocumentManager.Instance.getDocumentView(Doc.GetProto(doc))?.focus(doc, {}));
     }
 }
 ScriptingGlobals.add(DocFocusOrOpen);
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 160aba294..899764866 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -206,7 +206,7 @@ export namespace DragManager {
                         !dragData.isDocDecorationMove && !dragData.userDropAction && ScriptCast(d.onDragStart)
                             ? addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result)
                             : docDragData.dropAction === 'alias'
-                            ? Doc.MakeAlias(d)
+                            ? Doc.BestAlias(d)
                             : docDragData.dropAction === 'proto'
                             ? Doc.GetProto(d)
                             : docDragData.dropAction === 'copy'
@@ -260,10 +260,6 @@ export namespace DragManager {
         StartDrag([ele], dragData, downX, downY, options);
     }
 
-    export function StartImgDrag(ele: HTMLElement, downX: number, downY: number) {
-        StartDrag([ele], {}, downX, downY);
-    }
-
     export function SetSnapLines(horizLines: number[], vertLines: number[]) {
         SnappingManager.setSnapLines(horizLines, vertLines);
     }
@@ -325,7 +321,7 @@ export namespace DragManager {
     export let DocDragData: DocumentDragData | undefined;
     export function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: DragCompleteEvent) => void) {
         if (dragData.dropAction === 'none') return;
-        DocDragData = dragData instanceof DocumentDragData ? dragData : undefined;
+        DocDragData = dragData as DocumentDragData;
         const batch = UndoManager.StartBatch('dragging');
         eles = eles.filter(e => e);
         CanEmbed = dragData.canEmbed || false;
@@ -357,15 +353,15 @@ export namespace DragManager {
         let rot = 0;
         const docsToDrag = dragData instanceof DocumentDragData ? dragData.draggedDocuments : dragData instanceof AnchorAnnoDragData ? [dragData.dragDocument] : [];
         const dragElements = eles.map(ele => {
-            let useDim = false;
+            // bcz: very hacky -- if dragged element is a freeForm view with a rotation, then extract the rotation in order to apply it to the dragged element
+            let useDim = false; // if doc is rotated by freeformview, then the dragged elements width and height won't reflect the unrotated dimensions, so we need to rely on the element knowing its own width/height.  \
+            // if the parent isn't a freeform view, then the element's width and height are presumed to match the acutal doc's dimensions (eg, dragging from import sidebar menu)
             if (ele?.parentElement?.parentElement?.parentElement?.className === 'collectionFreeFormDocumentView-container') {
                 ele = ele.parentElement.parentElement.parentElement;
-                const rotStr = ele.style.transform.replace(/.*rotate\(([-0-9.e]*)deg\).*/, '$1');
-                if (rotStr) rot = Number(rotStr);
+                rot = Number(ele.style.transform.replace(/.*rotate\(([-0-9.e]*)deg\).*/, '$1') || 0);
             } else {
                 useDim = true;
             }
-            if (rot < 0) rot += 360;
             if (!ele.parentNode) dragDiv.appendChild(ele);
             const dragElement = ele.parentNode === dragDiv ? ele : (ele.cloneNode(true) as HTMLElement);
             const children = Array.from(dragElement.children);
@@ -387,7 +383,7 @@ export namespace DragManager {
             const rect = ele.getBoundingClientRect();
             const w = ele.offsetWidth || rect.width;
             const h = ele.offsetHeight || rect.height;
-            const rotR = -(rot / 180) * Math.PI;
+            const rotR = -((rot < 0 ? rot + 360 : rot) / 180) * Math.PI;
             const tl = [0, 0];
             const tr = [Math.cos(rotR) * w, Math.sin(-rotR) * w];
             const bl = [Math.sin(rotR) * h, Math.cos(-rotR) * h];
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 6cf7df357..10517d829 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -177,6 +177,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         );
         dragData.offset = dragDocView.props.ScreenToLocalTransform().transformDirection(e.x - left, e.y - top);
         dragData.moveDocument = dragDocView.props.moveDocument;
+        dragData.removeDocument = dragDocView.props.removeDocument;
         dragData.isDocDecorationMove = true;
         dragData.canEmbed = dragTitle;
         this._hidden = this.Interacting = true;
@@ -250,8 +251,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         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');
+                CollectionDockingView.AddSplit(Doc.BestAlias(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);
@@ -766,6 +766,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                 onBlur={e => !hideTitle && this.titleBlur()}
                 onChange={action(e => !hideTitle && (this._accumulatedTitle = e.target.value))}
                 onKeyDown={hideTitle ? emptyFunction : this.titleEntered}
+                onPointerDown={e => e.stopPropagation()}
             />
         ) : (
             <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown}>
@@ -825,7 +826,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                             <div className="documentDecorations-topbar" onPointerDown={this.onContainerDown}>
                                 {hideDeleteButton ? <div /> : topBtn('close', 'times', undefined, e => this.onCloseClick(true), 'Close')}
                                 {hideResizers || hideDeleteButton ? <div /> : topBtn('minimize', 'window-maximize', undefined, e => this.onCloseClick(undefined), 'Minimize')}
-                                {hideResizers ? <div /> : titleArea}
+                                {titleArea}
                                 {hideOpenButton ? <div /> : topBtn('open', 'external-link-alt', this.onMaximizeDown, undefined, 'Open in Lightbox (ctrl: as alias, shift: in new collection)')}
                             </div>
                             {hideResizers ? null : (
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index a5a886f42..2eb3dd532 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -3,8 +3,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, runInAction } from 'mobx';
 import { extname } from 'path';
 import { Doc, Opt } from '../../fields/Doc';
-import { BoolCast, Cast, ImageCast, NumCast, StrCast } from '../../fields/Types';
-import { DashColor, lightOrDark } from '../../Utils';
+import { BoolCast, Cast, DocCast, ImageCast, NumCast, StrCast } from '../../fields/Types';
+import { DashColor, emptyFunction, lightOrDark } from '../../Utils';
 import { CollectionViewType, DocumentType } from '../documents/DocumentTypes';
 import { DocFocusOrOpen } from '../util/DocumentManager';
 import { ColorScheme } from '../util/SettingsManager';
@@ -42,6 +42,7 @@ export enum StyleProp {
     FontSize = 'fontSize', // size of text font
     FontFamily = 'fontFamily', // font family of text
     FontWeight = 'fontWeight', // font weight of text
+    Highlighting = 'highlighting', // border highlighting
 }
 
 function darkScheme() {
@@ -107,6 +108,18 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             if (doc?._viewType === CollectionViewType.Freeform) allSorts[TreeSort.Zindex] = { color: 'green', label: 'z' };
             allSorts[TreeSort.None] = { color: 'darkgray', label: '\u00A0\u00A0\u00A0' };
             return allSorts;
+        case StyleProp.Highlighting:
+            if (doc) {
+                const highlightIndex = Doc.isBrushedHighlightedDegree(doc);
+                const highlightColor = ['transparent', 'rgb(68, 118, 247)', 'rgb(68, 118, 247)', 'orange', 'lightBlue'][highlightIndex];
+                const highlightStyle = ['solid', 'dashed', 'solid', 'solid', 'solid'][highlightIndex];
+                const excludeTypes = !props?.treeViewDoc ? [DocumentType.FONTICON, DocumentType.INK] : [DocumentType.FONTICON];
+                let highlighting = !props?.disableDocBrushing && highlightIndex && !excludeTypes.includes(doc.type as any) && doc._viewType !== CollectionViewType.Linear; // bcz: hack to turn off highlighting onsidebar panel documents.  need to flag a document as not highlightable in a more direct way
+                if (highlighting && props?.focus !== emptyFunction && StrCast(doc.title) !== '[pres element template]') {
+                    return { highlightStyle, highlightColor, highlightIndex };
+                }
+            }
+            return undefined;
         case StyleProp.DocContents:
             return undefined;
         case StyleProp.WidgetColor:
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 30759b766..7bc273d7d 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -218,12 +218,7 @@ export function CollectionSubView<X>(moreProps?: X) {
                     const movedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] === d);
                     const addedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] !== d);
                     if (movedDocs.length) {
-                        const canAdd =
-                            this.props.Document._viewType === CollectionViewType.Pile ||
-                            de.embedKey ||
-                            !this.props.isAnnotationOverlay ||
-                            this.props.Document.allowOverlayDrop ||
-                            Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.props.Document);
+                        const canAdd = this.props.Document._viewType === CollectionViewType.Pile || de.embedKey || this.props.Document.allowOverlayDrop || Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.props.Document);
                         added = docDragData.moveDocument(movedDocs, this.props.Document, canAdd ? this.addDocument : returnFalse);
                     } else {
                         ScriptCast(this.props.Document.dropConverter)?.script.run({ dragData: docDragData });
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index fe5dc17f5..1169f692a 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -147,6 +147,8 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         }
     };
 
+    screenToLocalTransform = () => this.props.ScreenToLocalTransform().translate(0, -this._headerHeight);
+
     @action
     remove = (doc: Doc | Doc[]): boolean => {
         const docs = doc instanceof Doc ? [doc] : doc;
@@ -275,7 +277,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
             dropAction,
             this.props.addDocTab,
             this.props.styleProvider,
-            this.props.ScreenToLocalTransform,
+            this.screenToLocalTransform,
             this.isContentActive,
             this.panelWidth,
             this.props.renderDepth,
@@ -377,6 +379,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
     moveAnnotationDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[], annotationKey?: string) => boolean) =>
         this.props.CollectionView?.moveDocument(doc, targetCollection, addDocument, `${this.props.fieldKey}-annotations`) || false;
 
+    @observable _headerHeight = 0;
     contentFunc = () => {
         const background = () => this.props.styleProvider?.(this.doc, this.props, StyleProp.BackgroundColor);
         const pointerEvents = () => (!this.props.isContentActive() && !SnappingManager.GetIsDragging() ? 'none' : undefined);
@@ -384,7 +387,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         return [
             <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
                 {!this.buttonMenu && !this.noviceExplainer ? null : (
-                    <div className="documentButtonMenu">
+                    <div className="documentButtonMenu" ref={action((r: HTMLDivElement | null) => r && (this._headerHeight = Number(getComputedStyle(r).height.replace(/px/, ''))))}>
                         {this.buttonMenu}
                         {this.noviceExplainer}
                     </div>
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 409b615f4..b9f86fa6b 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -10,11 +10,12 @@ import { listSpec } from '../../../fields/Schema';
 import { ComputedField, ScriptField } from '../../../fields/ScriptField';
 import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { TraceMobx } from '../../../fields/util';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnOne, returnTrue, simulateMouseClick, Utils } from '../../../Utils';
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, simulateMouseClick, Utils } from '../../../Utils';
 import { Docs, DocUtils } from '../../documents/Documents';
 import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
 import { DocumentManager } from '../../util/DocumentManager';
 import { DragManager, dropActionType } from '../../util/DragManager';
+import { ScriptingGlobals } from '../../util/ScriptingGlobals';
 import { SelectionManager } from '../../util/SelectionManager';
 import { SnappingManager } from '../../util/SnappingManager';
 import { Transform } from '../../util/Transform';
@@ -31,7 +32,6 @@ import { CollectionTreeView, TreeViewType } from './CollectionTreeView';
 import { CollectionView } from './CollectionView';
 import './TreeView.scss';
 import React = require('react');
-import { ScriptingGlobals } from '../../util/ScriptingGlobals';
 
 export interface TreeViewProps {
     treeView: CollectionTreeView;
@@ -792,12 +792,14 @@ export class TreeView extends React.Component<TreeViewProps> {
     titleStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string): any => {
         if (!doc || doc !== this.doc) return this.props?.treeView?.props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
 
+        // prettier-ignore
         switch (property.split(':')[0]) {
-            case StyleProp.Opacity:
-                return this.props.treeView.outlineMode ? undefined : 1;
-            case StyleProp.BackgroundColor:
-                return this.selected ? '#7089bb' : StrCast(doc._backgroundColor, StrCast(doc.backgroundColor));
+            case StyleProp.Opacity:         return this.props.treeView.outlineMode ? undefined : 1;
+            case StyleProp.BackgroundColor: return this.selected ? '#7089bb' : StrCast(doc._backgroundColor, StrCast(doc.backgroundColor));
+            case StyleProp.Highlighting:    if (this.props.treeView.outlineMode) return undefined;
             case StyleProp.DocContents:
+                const highlightIndex = this.props.treeView.outlineMode ? Doc.DocBrushStatus.unbrushed : Doc.isBrushedHighlightedDegree(doc);
+                const highlightColor = ['transparent', 'rgb(68, 118, 247)', 'rgb(68, 118, 247)', 'orange', 'lightBlue'][highlightIndex];
                 return this.props.treeView.outlineMode ? null : (
                     <div
                         className="treeView-label"
@@ -805,13 +807,13 @@ export class TreeView extends React.Component<TreeViewProps> {
                             // just render a title for a tree view label (identified by treeViewDoc being set in 'props')
                             maxWidth: props?.PanelWidth() || undefined,
                             background: props?.styleProvider?.(doc, props, StyleProp.BackgroundColor),
+                            outline: `solid ${highlightColor} ${highlightIndex}px`,
                         }}>
                         {StrCast(doc?.title)}
                     </div>
                 );
-            default:
-                return this.props?.treeView?.props.styleProvider?.(doc, props, property);
         }
+        return this.props?.treeView?.props.styleProvider?.(doc, props, property);
     };
     embeddedStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string): any => {
         if (property.startsWith(StyleProp.Decorations)) return null;
@@ -1011,6 +1013,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 pinToPres={this.props.treeView.props.pinToPres}
                 disableDocBrushing={this.props.treeView.props.disableDocBrushing}
                 bringToFront={returnFalse}
+                scriptContext={this}
             />
         );
     };
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 88422cbd4..eca95e1e0 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -113,7 +113,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     @observable _clusterSets: Doc[][] = [];
     @observable _deleteList: DocumentView[] = [];
     @observable _timelineRef = React.createRef<Timeline>();
-    @observable _marqueeRef = React.createRef<HTMLDivElement>();
+    @observable _marqueeRef: HTMLDivElement | null = null;
     @observable _marqueeViewRef = React.createRef<MarqueeView>();
     @observable ChildDrag: DocumentView | undefined; // child document view being dragged.  needed to update drop areas of groups when a group item is dragged.
     @observable _brushedView = { width: 0, height: 0, panX: 0, panY: 0, opacity: 0 }; // highlighted region of freeform canvas used by presentations to indicate a region
@@ -1011,22 +1011,22 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         switch (Doc.UserDoc().freeformScrollMode) {
             case freeformScrollMode.Pan:
                 // if shift is selected then zoom
-                if(e.ctrlKey) {
+                if (e.ctrlKey) {
                     if (!e.ctrlKey && this.props.Document.scrollHeight !== undefined) {
                         // things that can scroll vertically should do that instead of zooming
                     } else if (this.props.isContentActive(true) && !this.Document._isGroup) {
                         !this.props.isAnnotationOverlayScrollable && this.zoom(e.clientX, e.clientY, e.deltaY); // if (!this.props.isAnnotationOverlay) // bcz: do we want to zoom in on images/videos/etc?
                     }
-                // otherwise pan
+                    // otherwise pan
                 } else if (!e.ctrlKey && this.props.Document.scrollHeight !== undefined) {
                     // things that can scroll vertically should do that instead of zooming
                 } else if (this.props.isContentActive(true) && !this.Document._isGroup) {
                     const dx = e.deltaX;
                     const dy = e.deltaY;
                     if (e.shiftKey) {
-                        !this.props.isAnnotationOverlayScrollable && this.scrollPan({ deltaX: dy, deltaY: 0 }); 
+                        !this.props.isAnnotationOverlayScrollable && this.scrollPan({ deltaX: dy, deltaY: 0 });
                     } else {
-                        !this.props.isAnnotationOverlayScrollable && this.scrollPan({ deltaX: dx, deltaY: dy }); 
+                        !this.props.isAnnotationOverlayScrollable && this.scrollPan({ deltaX: dx, deltaY: dy });
                     }
                 }
                 break;
@@ -1548,9 +1548,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         setTimeout(
             action(() => {
                 this._firstRender = false;
-
-                this._marqueeRef.current?.addEventListener('dashDragAutoScroll', this.onDragAutoScroll as any);
-
                 this._disposers.groupBounds = reaction(
                     () => {
                         if (this.props.Document._isGroup && this.childDocs.length === this.childDocList?.length) {
@@ -1668,7 +1665,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     componentWillUnmount() {
         Object.values(this._disposers).forEach(disposer => disposer?.());
-        this._marqueeRef.current?.removeEventListener('dashDragAutoScroll', this.onDragAutoScroll as any);
+        this._marqueeRef?.removeEventListener('dashDragAutoScroll', this.onDragAutoScroll as any);
     }
 
     @action
@@ -1681,10 +1678,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         if ((e as any).handlePan || this.props.isAnnotationOverlay) return;
         (e as any).handlePan = true;
 
-        if (!this.layoutDoc._noAutoscroll && !this.props.renderDepth && this._marqueeRef?.current) {
+        if (!this.layoutDoc._noAutoscroll && !this.props.renderDepth && this._marqueeRef) {
             const dragX = e.detail.clientX;
             const dragY = e.detail.clientY;
-            const bounds = this._marqueeRef.current?.getBoundingClientRect();
+            const bounds = this._marqueeRef?.getBoundingClientRect();
 
             const deltaX = dragX - bounds.left < 25 ? -(25 + (bounds.left - dragX)) : bounds.right - dragX < 25 ? 25 - (bounds.right - dragX) : 0;
             const deltaY = dragY - bounds.top < 25 ? -(25 + (bounds.top - dragY)) : bounds.bottom - dragY < 25 ? 25 - (bounds.bottom - dragY) : 0;
@@ -1842,10 +1839,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         DragManager.SetSnapLines(horizLines, vertLines);
     };
 
-    onPointerOver = (e: React.PointerEvent) => {
-        e.stopPropagation();
-    };
-
     incrementalRender = action(() => {
         if (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this.props.docViewPath())) {
             const unrendered = this.childDocs.filter(doc => !this._renderCutoffData.get(doc[Id]));
@@ -1889,7 +1882,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 getContainerTransform={this.getContainerTransform}
                 getTransform={this.getTransform}
                 isAnnotationOverlay={this.isAnnotationOverlay}>
-                <div className="marqueeView-div" ref={this._marqueeRef} style={{ opacity: this.props.dontRenderDocuments ? 0.7 : undefined }}>
+                <div
+                    className="marqueeView-div"
+                    ref={r => {
+                        this._marqueeRef = r;
+                        r?.addEventListener('dashDragAutoScroll', this.onDragAutoScroll as any);
+                    }}
+                    style={{ opacity: this.props.dontRenderDocuments ? 0.7 : undefined }}>
                     {this.layoutDoc._backgroundGridShow ? (
                         <div>
                             <CollectionFreeFormBackgroundGrid // bcz : UGHH  don't know why, but if we don't wrap in a div, then PDF's don't render whenn taking snapshot of a dashboard and the background grid is on!!?
@@ -1965,7 +1964,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             <div
                 className={'collectionfreeformview-container'}
                 ref={this.createDashEventsTarget}
-                onPointerOver={this.onPointerOver}
                 onWheel={this.onPointerWheel}
                 onClick={this.onClick}
                 onPointerDown={this.onPointerDown}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index d3858c25e..fecbc2de2 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -15,7 +15,7 @@ import { BoolCast, Cast, ImageCast, NumCast, ScriptCast, StrCast } from '../../.
 import { AudioField } from '../../../fields/URLField';
 import { GetEffectiveAcl, SharingPermissions, TraceMobx } from '../../../fields/util';
 import { MobileInterface } from '../../../mobile/MobileInterface';
-import { emptyFunction, hasDescendantTarget, lightOrDark, OmitKeys, returnEmptyString, returnFalse, returnTrue, returnVal, simulateMouseClick, Utils } from '../../../Utils';
+import { emptyFunction, isTargetChildOf as isParentOf, lightOrDark, OmitKeys, returnEmptyString, returnFalse, returnTrue, returnVal, simulateMouseClick, Utils } from '../../../Utils';
 import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils';
 import { DocServer } from '../../DocServer';
 import { Docs, DocUtils } from '../../documents/Documents';
@@ -956,60 +956,58 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                 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 : [];
-            helpItems.push({ description: 'Show Metadata', event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), 'add:right'), icon: 'layer-group' });
-            !Doc.noviceMode && 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.noviceMode && helpItems.push({ description: 'Print Document in Console', event: () => console.log(this.props.Document), icon: 'hand-point-right' });
-            !Doc.noviceMode && helpItems.push({ description: 'Print DataDoc in Console', event: () => console.log(this.props.Document[DataSym]), icon: 'hand-point-right' });
-            
-            let documentationDescription: string | undefined = undefined;
-            let documentationLink: string | undefined = undefined;
-            console.log("type: ", this.props.Document.type);
-            switch(this.props.Document.type) {
-                case DocumentType.COL:
-                    documentationDescription = "See collection documentation";
-                    documentationLink = "https://brown-dash.github.io/Dash-Documentation/views/";
-                    break;
-                case DocumentType.PDF:
-                    documentationDescription = "See PDF node documentation";
-                    documentationLink = "https://brown-dash.github.io/Dash-Documentation/documents/pdf/";
-                    break;
-                case DocumentType.VID:
-                    documentationDescription = "See video node documentation";
-                    documentationLink = "https://brown-dash.github.io/Dash-Documentation/documents/tempMedia/video";
-                    break;
-                case DocumentType.AUDIO:
-                    documentationDescription = "See audio node documentation";
-                    documentationLink = "https://brown-dash.github.io/Dash-Documentation/documents/tempMedia/audio";
-                    break;
-                case DocumentType.WEB:
-                    documentationDescription = "See webpage node documentation";
-                    documentationLink = "https://brown-dash.github.io/Dash-Documentation/documents/webpage/";
-                    break;
-                case DocumentType.IMG:
-                    documentationDescription = "See image node documentation";
-                    documentationLink = "https://brown-dash.github.io/Dash-Documentation/documents/images/";
-                    break;
-                case DocumentType.RTF:
-                    documentationDescription = "See text node documentation";
-                    documentationLink = "https://brown-dash.github.io/Dash-Documentation/documents/text/";
-                    break;
-                default:
-                    break;
-            }
-
-            // Add link to help documentation
-            if (documentationDescription && documentationLink) {
-                console.log("add documentation item");
-                helpItems.push({ description: documentationDescription, event: () => {
+        }
+        const help = cm.findByDescription('Help...');
+        const helpItems: ContextMenuProps[] = help && 'subitems' in help ? help.subitems : [];
+        helpItems.push({ description: 'Show Metadata', event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), 'add:right'), icon: 'layer-group' });
+        !Doc.noviceMode && 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.noviceMode && helpItems.push({ description: 'Print Document in Console', event: () => console.log(this.props.Document), icon: 'hand-point-right' });
+        !Doc.noviceMode && helpItems.push({ description: 'Print DataDoc in Console', event: () => console.log(this.props.Document[DataSym]), icon: 'hand-point-right' });
+
+        let documentationDescription: string | undefined = undefined;
+        let documentationLink: string | undefined = undefined;
+        switch (this.props.Document.type) {
+            case DocumentType.COL:
+                documentationDescription = 'See collection documentation';
+                documentationLink = 'https://brown-dash.github.io/Dash-Documentation/views/';
+                break;
+            case DocumentType.PDF:
+                documentationDescription = 'See PDF node documentation';
+                documentationLink = 'https://brown-dash.github.io/Dash-Documentation/documents/pdf/';
+                break;
+            case DocumentType.VID:
+                documentationDescription = 'See video node documentation';
+                documentationLink = 'https://brown-dash.github.io/Dash-Documentation/documents/tempMedia/video';
+                break;
+            case DocumentType.AUDIO:
+                documentationDescription = 'See audio node documentation';
+                documentationLink = 'https://brown-dash.github.io/Dash-Documentation/documents/tempMedia/audio';
+                break;
+            case DocumentType.WEB:
+                documentationDescription = 'See webpage node documentation';
+                documentationLink = 'https://brown-dash.github.io/Dash-Documentation/documents/webpage/';
+                break;
+            case DocumentType.IMG:
+                documentationDescription = 'See image node documentation';
+                documentationLink = 'https://brown-dash.github.io/Dash-Documentation/documents/images/';
+                break;
+            case DocumentType.RTF:
+                documentationDescription = 'See text node documentation';
+                documentationLink = 'https://brown-dash.github.io/Dash-Documentation/documents/text/';
+                break;
+        }
+        // Add link to help documentation
+        if (documentationDescription && documentationLink) {
+            console.log('add documentation item');
+            helpItems.push({
+                description: documentationDescription,
+                event: () => {
                     window.open(documentationLink, '_blank');
-                }, icon: 'book' })
-            };
-
-            cm.addItem({ description: 'Help...', noexpand: true, subitems: helpItems, icon: 'question' });
+                },
+                icon: 'book',
+            });
         }
+        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);
@@ -1411,29 +1409,23 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     };
     render() {
         TraceMobx();
-        const highlightIndex = this.props.LayoutTemplateString ? (Doc.IsHighlighted(this.props.Document) ? 6 : Doc.DocBrushStatus.unbrushed) : 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 ? [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 highlighting = this.props.styleProvider?.(this.props.Document, this.props, StyleProp.Highlighting);
         const borderPath = this.props.styleProvider?.(this.props.Document, this.props, StyleProp.BorderPath) || { path: undefined };
-        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);
+        const boxShadow =
+            this.props.treeViewDoc || !highlighting
+                ? null
+                : highlighting && this.borderRounding && highlighting.highlightStyle !== 'dashed'
+                ? `0 0 0 ${highlighting.highlightIndex}px ${highlighting.highlightColor}`
+                : this.boxShadow || (this.props.Document.isTemplateForField ? 'black 0.2vw 0.2vw 0.8vw' : undefined);
         const renderDoc = this.renderDoc({
             borderRadius: this.borderRounding,
-            outline: highlighting && !this.borderRounding ? `${highlightColor} ${highlightStyle} ${highlightIndex}px` : 'solid 0px',
-            border: highlighting && this.borderRounding && highlightStyle === 'dashed' ? `${highlightStyle} ${highlightColor} ${highlightIndex}px` : undefined,
+            outline: highlighting && !this.borderRounding && highlighting ? `${highlighting.highlightColor} ${highlighting.highlightStyle} ${highlighting.highlightIndex}px` : 'solid 0px',
+            border: highlighting && this.borderRounding && highlighting && highlighting.highlightStyle === 'dashed' ? `${highlighting.highlightStyle} ${highlighting.highlightColor} ${highlighting.highlightIndex}px` : undefined,
             boxShadow,
             clipPath: borderPath.path ? `path('${borderPath.path}')` : undefined,
         });
 
         const animRenderDoc = PresBox.Instance?.isActiveItemTarget(this.layoutDoc) ? PresBox.AnimationEffect(renderDoc, PresBox.Instance.activeItem) : renderDoc;
-        // Return surrounding highlight
         return (
             <div
                 className={`${DocumentView.ROOT_DIV} docView-hack`}
@@ -1442,8 +1434,9 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                 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))}
+                onPointerEnter={e => (!SnappingManager.GetIsDragging() || DragManager.CanEmbed) && Doc.BrushDoc(this.props.Document)}
+                onPointerOver={e => (!SnappingManager.GetIsDragging() || DragManager.CanEmbed) && Doc.BrushDoc(this.props.Document)}
+                onPointerLeave={e => !isParentOf(this.ContentDiv, document.elementFromPoint(e.nativeEvent.x, e.nativeEvent.y)) && Doc.UnBrushDoc(this.props.Document)}
                 style={{
                     display: this.hidden ? 'inline' : undefined,
                     borderRadius: this.borderRounding,
@@ -1453,9 +1446,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     animRenderDoc
                 ) : (
                     <>
-                        {/* <div style={{ clipPath: `path('${borderPath.fill}')` }}>
-                        {animRenderDoc}
-                    </div> */}
                         {animRenderDoc}
                         <div key="border2" className="documentView-customBorder" style={{ pointerEvents: 'none' }}>
                             <svg style={{ overflow: 'visible' }} viewBox={`0 0 ${this.props.PanelWidth()} ${this.props.PanelHeight()}`}>
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index a94e2c96d..f5d00c2b8 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -538,6 +538,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
                     docid: target[Id],
                     float: 'unset',
                 });
+                if (!['alias', 'copy'].includes((dragData.dropAction ?? '') as any)) {
+                    dragData.removeDocument?.(dragData.draggedDocuments[0]);
+                }
                 const view = this._editorView!;
                 view.dispatch(view.state.tr.insert(view.posAtCoords({ left: de.x, top: de.y })!.pos, node));
                 e.stopPropagation();
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 0ceaff968..460dd6081 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -680,6 +680,11 @@ export namespace Doc {
         return alias;
     }
 
+    export function BestAlias(doc: Doc) {
+        const bestAlias = Doc.GetProto(doc) ? DocListCast(doc.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail) : doc;
+        return bestAlias ?? Doc.MakeAlias(doc);
+    }
+
     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])!;
-- 
cgit v1.2.3-70-g09d2


From 3b1162f58fd854091fca515dfe9af942d2220108 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 25 Oct 2022 14:34:53 -0400
Subject: fixed up dragging fields from key value pane to support numbers

---
 src/client/util/DragManager.ts                     |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  4 +-
 src/client/views/nodes/KeyValueBox.tsx             |  9 +++-
 .../views/nodes/formattedText/FormattedTextBox.tsx | 56 ++++++++++++----------
 src/fields/Doc.ts                                  |  3 ++
 5 files changed, 45 insertions(+), 29 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 899764866..36e5a65fb 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -24,7 +24,7 @@ export type dropActionType = 'alias' | 'copy' | 'move' | 'same' | 'proto' | 'non
  * @param dropAction: What to do with the document when it is dropped
  * @param dragStarted: Method to call when the drag is started
  */
-export function SetupDrag(_reference: React.RefObject<HTMLElement>, docFunc: () => Doc | Promise<Doc> | undefined, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType, dragStarted?: () => void) {
+export function SetupDrag(_reference: React.RefObject<HTMLElement>, docFunc: () => Doc | Promise<Doc | undefined> | undefined, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType, dragStarted?: () => void) {
     const onRowMove = async (e: PointerEvent) => {
         e.stopPropagation();
         e.preventDefault();
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index eca95e1e0..559951efc 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1346,8 +1346,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         const { backgroundColor, color } = curFrame === undefined ? { backgroundColor: undefined, color: undefined } : CollectionFreeFormDocumentView.getStringValues(childDoc, curFrame);
         const { x, y, opacity } = curFrame === undefined ? { x: childDoc.x, y: childDoc.y, opacity: this.props.childOpacity?.() } : CollectionFreeFormDocumentView.getValues(childDoc, curFrame);
         return {
-            x: NumCast(x),
-            y: NumCast(y),
+            x: Number.isNaN(NumCast(x)) ? 0 : NumCast(x),
+            y: Number.isNaN(NumCast(y)) ? 0 : NumCast(y),
             z: Cast(z, 'number'),
             color: Cast(color, 'string') ? StrCast(color) : this.props.styleProvider?.(childDoc, this.props, StyleProp.Color),
             backgroundColor: Cast(backgroundColor, 'string') ? StrCast(backgroundColor) : this.props.styleProvider?.(childDoc, this.props, StyleProp.BackgroundColor),
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index d9f46509e..7d04c4b64 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -209,13 +209,18 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
             }
             return parent;
         }
-        return this.createFieldView(DocCast(this.props.Document.data), rows.lastElement());
+        return rows.length ? this.createFieldView(DocCast(this.props.Document.data), rows.lastElement()) : undefined;
     };
 
     createFieldView = (templateDoc: Doc, row: KeyValuePair) => {
         const metaKey = row.props.keyName;
-        const fieldTemplate = Doc.MakeAlias(templateDoc);
+        const fieldTemplate = Doc.IsDelegateField(templateDoc, metaKey) ? Doc.MakeDelegate(templateDoc) : Doc.MakeAlias(templateDoc);
         fieldTemplate.title = metaKey;
+        fieldTemplate.fitWidth = true;
+        fieldTemplate._xMargin = 10;
+        fieldTemplate._yMargin = 10;
+        fieldTemplate._width = 100;
+        fieldTemplate._height = 40;
         fieldTemplate.layout = this.inferType(templateDoc[metaKey], metaKey);
         return fieldTemplate;
     };
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index f5d00c2b8..5470d6ba9 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -18,7 +18,7 @@ import { PrefetchProxy } from '../../../../fields/Proxy';
 import { RichTextField } from '../../../../fields/RichTextField';
 import { RichTextUtils } from '../../../../fields/RichTextUtils';
 import { ComputedField } from '../../../../fields/ScriptField';
-import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
+import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
 import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util';
 import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils';
 import { GoogleApiClientUtils, Pulls, Pushes } from '../../../apis/google_docs/GoogleApiClientUtils';
@@ -124,7 +124,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
         return this._showSidebar ? '20%' : StrCast(this.layoutDoc._sidebarWidthPercent, '0%');
     }
     @computed get sidebarColor() {
-        return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + '-backgroundColor'], '#e4e4e4'));
+        return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.fieldKey + '-backgroundColor'], '#e4e4e4'));
     }
     @computed get autoHeight() {
         return (this.props.forceAutoHeight || this.layoutDoc._autoHeight) && !this.props.ignoreAutoHeight;
@@ -281,12 +281,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
             const state = this._editorView.state.apply(tx);
             this._editorView.updateState(state);
 
+            const dataDoc = Doc.IsDelegateField(DocCast(this.layoutDoc.proto), this.fieldKey) ? DocCast(this.layoutDoc.proto) : this.dataDoc;
             const curText = state.doc.textBetween(0, state.doc.content.size, ' \n');
-            const curTemp = this.layoutDoc.resolvedDataDoc ? Cast(this.layoutDoc[this.props.fieldKey], RichTextField) : undefined; // the actual text in the text box
-            const curProto = Cast(Cast(this.dataDoc.proto, Doc, null)?.[this.fieldKey], RichTextField, null); // the default text inherited from a prototype
+            const curTemp = this.layoutDoc.resolvedDataDoc ? Cast(this.layoutDoc[this.fieldKey], RichTextField) : undefined; // the actual text in the text box
+            const curProto = Cast(Cast(dataDoc.proto, Doc, null)?.[this.fieldKey], RichTextField, null); // the default text inherited from a prototype
             const curLayout = this.rootDoc !== this.layoutDoc ? Cast(this.layoutDoc[this.fieldKey], RichTextField, null) : undefined; // the default text stored in a layout template
             const json = JSON.stringify(state.toJSON());
-            const effectiveAcl = GetEffectiveAcl(this.dataDoc);
+            const effectiveAcl = GetEffectiveAcl(dataDoc);
 
             const removeSelection = (json: string | undefined) => (json?.indexOf('"storedMarks"') === -1 ? json?.replace(/"selection":.*/, '') : json?.replace(/"selection":"\"storedMarks\""/, '"storedMarks"'));
 
@@ -297,29 +298,34 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
                         accumTags.push(node.attrs.fieldKey);
                     }
                 });
-                const curTags = Object.keys(this.dataDoc).filter(key => key.startsWith('#'));
+                const curTags = Object.keys(dataDoc).filter(key => key.startsWith('#'));
                 const added = accumTags.filter(tag => !curTags.includes(tag));
                 const removed = curTags.filter(tag => !accumTags.includes(tag));
-                removed.forEach(r => (this.dataDoc[r] = undefined));
-                added.forEach(a => (this.dataDoc[a] = a));
+                removed.forEach(r => (dataDoc[r] = undefined));
+                added.forEach(a => (dataDoc[a] = a));
 
                 let unchanged = true;
                 if (this._applyingChange !== this.fieldKey && removeSelection(json) !== removeSelection(curProto?.Data)) {
                     this._applyingChange = this.fieldKey;
-                    curText !== Cast(this.dataDoc[this.fieldKey], RichTextField)?.Text && (this.dataDoc[this.props.fieldKey + '-lastModified'] = new DateField(new Date(Date.now())));
+                    curText !== Cast(dataDoc[this.fieldKey], RichTextField)?.Text && (dataDoc[this.fieldKey + '-lastModified'] = new DateField(new Date(Date.now())));
                     if ((!curTemp && !curProto) || curText || json.includes('dash')) {
                         // if no template, or there's text that didn't come from the layout template, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended)
                         if (removeSelection(json) !== removeSelection(curLayout?.Data)) {
-                            this.dataDoc[this.props.fieldKey] = new RichTextField(json, curText);
-                            this.dataDoc[this.props.fieldKey + '-noTemplate'] = true; //(curTemp?.Text || "") !== curText; // mark the data field as being split from the template if it has been edited
+                            const numstring = NumCast(dataDoc[this.fieldKey], null);
+                            if (numstring !== undefined) {
+                                dataDoc[this.fieldKey] = Number(curText);
+                            } else {
+                                dataDoc[this.fieldKey] = new RichTextField(json, curText);
+                            }
+                            dataDoc[this.fieldKey + '-noTemplate'] = true; //(curTemp?.Text || "") !== curText; // mark the data field as being split from the template if it has been edited
                             ScriptCast(this.layoutDoc.onTextChanged, null)?.script.run({ this: this.layoutDoc, self: this.rootDoc, text: curText });
                             unchanged = false;
                         }
                     } else {
                         // if we've deleted all the text in a note driven by a template, then restore the template data
-                        this.dataDoc[this.props.fieldKey] = undefined;
+                        dataDoc[this.fieldKey] = undefined;
                         this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse((curProto || curTemp).Data)));
-                        this.dataDoc[this.props.fieldKey + '-noTemplate'] = undefined; // mark the data field as not being split from any template it might have
+                        dataDoc[this.fieldKey + '-noTemplate'] = undefined; // mark the data field as not being split from any template it might have
                         ScriptCast(this.layoutDoc.onTextChanged, null)?.script.run({ this: this.layoutDoc, self: this.rootDoc, text: curText });
                         unchanged = false;
                     }
@@ -330,7 +336,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
                     }
                 }
             } else {
-                const jsonstring = Cast(this.dataDoc[this.fieldKey], RichTextField)?.Data!;
+                const jsonstring = Cast(dataDoc[this.fieldKey], RichTextField)?.Data!;
                 if (jsonstring) {
                     const json = JSON.parse(jsonstring);
                     json.selection = state.toJSON().selection;
@@ -508,7 +514,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
         this._dropDisposer?.();
         this.ProseRef = ele;
         if (ele) {
-            this.setupEditor(this.config, this.props.fieldKey);
+            this.setupEditor(this.config, this.fieldKey);
             this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.layoutDoc);
         }
         // if (this.autoHeight) this.tryUpdateScrollHeight();
@@ -524,7 +530,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
             // replace text contents whend dragging with Alt
             if (draggedDoc && draggedDoc.type === DocumentType.RTF && !Doc.AreProtosEqual(draggedDoc, this.props.Document) && de.altKey) {
                 if (draggedDoc.data instanceof RichTextField) {
-                    Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new RichTextField(draggedDoc.data.Data, draggedDoc.data.Text);
+                    Doc.GetProto(this.dataDoc)[this.fieldKey] = new RichTextField(draggedDoc.data.Data, draggedDoc.data.Text);
                     e.stopPropagation();
                 }
                 // embed document when dragg marked as embed
@@ -678,8 +684,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
     @undoBatch
     deleteAnnotation = (anchor: Doc) => {
         LinkManager.Instance.deleteLink(DocListCast(anchor.links)[0]);
-        // const docAnnotations = DocListCast(this.props.dataDoc[this.props.fieldKey]);
-        // this.props.dataDoc[this.props.fieldKey] = new List<Doc>(docAnnotations.filter(a => a !== this.annoTextRegion));
+        // const docAnnotations = DocListCast(this.props.dataDoc[this.fieldKey]);
+        // this.props.dataDoc[this.fieldKey] = new List<Doc>(docAnnotations.filter(a => a !== this.annoTextRegion));
         // AnchorMenu.Instance.fadeOut(true);
         this.props.select(false);
     };
@@ -1034,8 +1040,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
         );
         this._disposers.editorState = reaction(
             () => {
-                const whichDoc = !this.dataDoc || !this.layoutDoc ? undefined : this.dataDoc?.[this.props.fieldKey + '-noTemplate'] || !this.layoutDoc[this.props.fieldKey] ? this.dataDoc : this.layoutDoc;
-                return !whichDoc ? undefined : { data: Cast(whichDoc[this.props.fieldKey], RichTextField, null), str: StrCast(whichDoc[this.props.fieldKey]) };
+                const dataDoc = Doc.IsDelegateField(DocCast(this.layoutDoc?.proto), this.fieldKey) ? DocCast(this.layoutDoc?.proto) : this?.dataDoc;
+                const whichDoc = !this.dataDoc || !this.layoutDoc ? undefined : dataDoc?.[this.fieldKey + '-noTemplate'] || !this.layoutDoc[this.fieldKey] ? dataDoc : this.layoutDoc;
+                return !whichDoc ? undefined : { data: Cast(whichDoc[this.fieldKey], RichTextField, null), str: Field.toString(whichDoc[this.fieldKey]) };
             },
             incomingValue => {
                 if (this._editorView && this._applyingChange !== this.fieldKey) {
@@ -1172,7 +1179,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
         let pullSuccess = false;
         if (exportState !== undefined) {
             pullSuccess = true;
-            dataDoc[this.props.fieldKey] = new RichTextField(JSON.stringify(exportState.state.toJSON()));
+            dataDoc[this.fieldKey] = new RichTextField(JSON.stringify(exportState.state.toJSON()));
             setTimeout(() => {
                 if (this._editorView) {
                     const state = this._editorView.state;
@@ -1300,8 +1307,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
     }
     _didScroll = false;
     setupEditor(config: any, fieldKey: string) {
-        const curText = Cast(this.dataDoc[this.props.fieldKey], RichTextField, null) || StrCast(this.dataDoc[this.props.fieldKey]);
-        const rtfField = Cast((!curText && this.layoutDoc[this.props.fieldKey]) || this.dataDoc[fieldKey], RichTextField);
+        const curText = Cast(this.dataDoc[this.fieldKey], RichTextField, null) || StrCast(this.dataDoc[this.fieldKey]);
+        const rtfField = Cast((!curText && this.layoutDoc[this.fieldKey]) || this.dataDoc[fieldKey], RichTextField);
         if (this.ProseRef) {
             const self = this;
             this._editorView?.destroy();
@@ -1352,7 +1359,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
             });
             const { state, dispatch } = this._editorView;
             if (!rtfField) {
-                const startupText = Field.toString(this.dataDoc[fieldKey] as Field);
+                const dataDoc = Doc.IsDelegateField(DocCast(this.layoutDoc.proto), this.fieldKey) ? DocCast(this.layoutDoc.proto) : this.dataDoc;
+                const startupText = Field.toString(dataDoc[fieldKey] as Field);
                 if (startupText) {
                     dispatch(state.tr.insertText(startupText));
                 }
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 460dd6081..466b43287 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -491,6 +491,9 @@ export namespace Doc {
     export function IsSystem(doc: Doc) {
         return GetT(doc, 'system', 'boolean', true);
     }
+    export function IsDelegateField(doc: Doc, fieldKey: string) {
+        return doc && Get(doc, fieldKey, true) !== undefined;
+    }
     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;
-- 
cgit v1.2.3-70-g09d2


From 2fc88a931cb2fc3408297b000208990633445585 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 27 Oct 2022 15:57:09 -0400
Subject: cleaned up treeViews to work across PresBox/ppt slides/collections/ -
 modified DocumentView rendering to remove pres box refs.  fixed mainView
 width.

---
 src/client/documents/Documents.ts                  |   4 +-
 src/client/util/CurrentUserUtils.ts                |   8 +-
 src/client/views/DocumentDecorations.tsx           |  18 +-
 src/client/views/LightboxView.tsx                  |  26 +--
 src/client/views/MainView.tsx                      |   1 +
 src/client/views/StyleProvider.tsx                 |   5 +-
 .../views/collections/CollectionStackingView.tsx   |   2 +
 .../views/collections/CollectionTreeView.scss      |   2 -
 .../views/collections/CollectionTreeView.tsx       |  62 ++++---
 src/client/views/collections/CollectionView.tsx    |   2 +
 src/client/views/collections/TabDocView.tsx        |   1 -
 src/client/views/collections/TreeView.scss         |   3 +-
 src/client/views/collections/TreeView.tsx          | 179 +++++++++----------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   2 +-
 .../views/nodes/CollectionFreeFormDocumentView.tsx |   6 +-
 src/client/views/nodes/DocumentView.tsx            |  37 ++--
 src/client/views/nodes/FieldView.tsx               |   2 -
 src/client/views/nodes/VideoBox.tsx                |   2 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |   8 +-
 src/client/views/nodes/trails/PresBox.tsx          |   7 +-
 src/client/views/nodes/trails/PresElementBox.scss  |  14 +-
 src/client/views/nodes/trails/PresElementBox.tsx   | 197 ++++++++++++---------
 src/fields/Doc.ts                                  |   3 +
 23 files changed, 301 insertions(+), 290 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 2d82ffdf9..bbb896d6e 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -335,7 +335,6 @@ export class DocumentOptions {
     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
     treeViewChildDoubleClick?: ScriptField; //
     // Action Button
     buttonMenu?: boolean; // whether a action button should be displayed
@@ -395,7 +394,6 @@ export namespace Docs {
                         _xMargin: 10,
                         _yMargin: 10,
                         nativeDimModifiable: true,
-                        treeViewGrowsHorizontally: true,
                         nativeHeightUnfrozen: true,
                         forceReflow: true,
                         links: '@links(self)',
@@ -570,7 +568,7 @@ export namespace Docs {
                 DocumentType.SLIDER,
                 {
                     layout: { view: SliderBox, dataField: defaultDataKey },
-                    options: { links: '@links(self)', treeViewGrowsHorizontally: true },
+                    options: { links: '@links(self)' },
                 },
             ],
             [
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 2bc464127..a2974177e 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -480,7 +480,7 @@ export class CurrentUserUtils {
         const childContextMenuIcons = ["chalkboard", "tv", "camera", "users", "times", "trash"]; // entries must be kept in synch with childContextMenuScripts, childContextMenuLabels, and childContextMenuFilters
         const reqdOpts:DocumentOptions = {
             title: "My Dashboards", childHideLinkButton: true, freezeChildren: "remove|add", treeViewHideTitle: true, boxShadow: "0 0", childDontRegisterViews: true,
-            targetDropAction: "same", treeViewType: TreeViewType.fileSystem, isFolder: true, system: true,  treeViewTruncateTitleWidth: 150, ignoreClick: true, 
+            targetDropAction: "same", treeViewType: TreeViewType.fileSystem, isFolder: true, system: true,  treeViewTruncateTitleWidth: 350, ignoreClick: true, 
             buttonMenu: true, buttonMenuDoc: newDashboardButton, childDropAction: "alias",
             _showTitle: "title", _height: 400, _gridGap: 5, _forceActive: true, _lockedPosition: true,
             contextMenuLabels:new List<string>(contextMenuLabels),
@@ -518,7 +518,7 @@ export class CurrentUserUtils {
         const reqdOpts:DocumentOptions = { _showTitle: "title", _height: 100, _gridGap: 5, _forceActive: true, _lockedPosition: true, 
             title: "My Documents", buttonMenu: true, buttonMenuDoc: newFolderButton, treeViewHideTitle: true, targetDropAction: "proto", system: true,
             isFolder: true, treeViewType: TreeViewType.fileSystem, childHideLinkButton: true, boxShadow: "0 0", childDontRegisterViews: true, 
-            treeViewTruncateTitleWidth: 150, ignoreClick: true, childDropAction: "alias",
+            treeViewTruncateTitleWidth: 350, ignoreClick: true, childDropAction: "alias",
             childContextMenuLabels: new List<string>(["Create new folder"]),
             childContextMenuIcons: new List<string>(["plus"]),
             explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard."
@@ -535,7 +535,7 @@ export class CurrentUserUtils {
     static setupRecentlyClosed(doc: Doc, field:string) {
         const reqdOpts:DocumentOptions = { _showTitle: "title", _lockedPosition: true, _gridGap: 5, _forceActive: true, 
             title: "My Recently Closed", buttonMenu: true, childHideLinkButton: true, treeViewHideTitle: true, childDropAction: "alias", system: true,
-            treeViewTruncateTitleWidth: 150, ignoreClick: true,  boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same",
+            treeViewTruncateTitleWidth: 350, ignoreClick: true,  boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same",
             contextMenuLabels: new List<string>(["Empty recently closed"]),
             contextMenuIcons:new List<string>(["trash"]),
             explainer: "Recently closed documents appear in this menu. They will only be deleted if you explicity empty this list."
@@ -561,7 +561,7 @@ export class CurrentUserUtils {
         const reqdOpts:DocumentOptions = {
             _lockedPosition: true, _gridGap: 5, _forceActive: true, title: Doc.CurrentUserEmail +"-view",
             boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", ignoreClick: true, system: true,
-            treeViewHideTitle: true, treeViewTruncateTitleWidth: 150
+            treeViewHideTitle: true, treeViewTruncateTitleWidth: 350
         };
         if (!doc[field]) DocUtils.AssignOpts(doc, {treeViewOpen: true, treeViewExpandedView: "fields" });
         return DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.TreeDocument(items??[], opts), reqdOpts, [doc]);
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 10517d829..06eb6c6d7 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -112,7 +112,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                             }
                         }
                         //@ts-ignore
-                        const titleField = +this._accumulatedTitle === this._accumulatedTitle ? +this._accumulatedTitle : this._accumulatedTitle;
+                        const titleField = +this._accumulatedTitle == this._accumulatedTitle ? +this._accumulatedTitle : this._accumulatedTitle;
                         Doc.SetInPlace(d.rootDoc, titleFieldKey, titleField, true);
 
                         if (d.rootDoc.syncLayoutFieldWithTitle) {
@@ -345,7 +345,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
     setRotateCenter = (seldocview: DocumentView, rotCenter: number[]) => {
         const newloccentern = seldocview.props.ScreenToLocalTransform().transformPoint(rotCenter[0], rotCenter[1]);
         const newlocenter = [newloccentern[0] - NumCast(seldocview.layoutDoc._width) / 2, newloccentern[1] - NumCast(seldocview.layoutDoc._height) / 2];
-        const final = Utils.rotPt(newlocenter[0], newlocenter[1], -(NumCast(seldocview.rootDoc._jitterRotation) / 180) * Math.PI);
+        const final = Utils.rotPt(newlocenter[0], newlocenter[1], -(NumCast(seldocview.rootDoc._rotation) / 180) * Math.PI);
         seldocview.rootDoc.rotateCenterX = final.x / NumCast(seldocview.layoutDoc._width);
         seldocview.rootDoc.rotateCenterY = final.y / NumCast(seldocview.layoutDoc._height);
     };
@@ -381,7 +381,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         const infos = new Map<Doc, { unrotatedDocPos: { x: number; y: number }; startRotCtr: { x: number; y: number }; accumRot: number }>();
         const seldocview = SelectionManager.Views()[0];
         SelectionManager.Views().forEach(dv => {
-            const accumRot = (NumCast(dv.rootDoc._jitterRotation) / 180) * Math.PI;
+            const accumRot = (NumCast(dv.rootDoc._rotation) / 180) * Math.PI;
             const localRotCtr = dv.props.ScreenToLocalTransform().transformPoint(rcScreen.X, rcScreen.Y);
             const localRotCtrOffset = [localRotCtr[0] - NumCast(dv.rootDoc.width) / 2, localRotCtr[1] - NumCast(dv.rootDoc.height) / 2];
             const startRotCtr = Utils.rotPt(localRotCtrOffset[0], localRotCtrOffset[1], -accumRot);
@@ -396,7 +396,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                     infos.set(dv.rootDoc, { unrotatedDocPos, startRotCtr, accumRot: isAbs ? angle : accumRot + angle });
                     dv.rootDoc.x = infos.get(dv.rootDoc)!.unrotatedDocPos.x - (endRotCtr.x - startRotCtr.x);
                     dv.rootDoc.y = infos.get(dv.rootDoc)!.unrotatedDocPos.y - (endRotCtr.y - startRotCtr.y);
-                    dv.rootDoc._jitterRotation = ((isAbs ? 0 : NumCast(dv.rootDoc._jitterRotation)) + (angle * 180) / Math.PI) % 360; // Rotation between -360 and 360
+                    dv.rootDoc._rotation = ((isAbs ? 0 : NumCast(dv.rootDoc._rotation)) + (angle * 180) / Math.PI) % 360; // Rotation between -360 and 360
                 })
             );
         };
@@ -416,7 +416,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                 return false;
             }, // moveEvent
             action(() => {
-                const oldRotation = NumCast(seldocview.rootDoc._jitterRotation);
+                const oldRotation = NumCast(seldocview.rootDoc._rotation);
                 const diff = oldRotation - Math.round(oldRotation / 45) * 45;
                 if (Math.abs(diff) < 5) {
                     if (selectedInk.length) {
@@ -611,7 +611,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                         }
                     } else {
                         const rotCtr = [NumCast(doc._width) / 2, NumCast(doc._height) / 2];
-                        const tlRotated = Utils.rotPt(-rotCtr[0], -rotCtr[1], (NumCast(doc._jitterRotation) / 180) * Math.PI);
+                        const tlRotated = Utils.rotPt(-rotCtr[0], -rotCtr[1], (NumCast(doc._rotation) / 180) * Math.PI);
 
                         const maxHeight = doc.nativHeightUnfrozen || !nheight ? 0 : Math.max(nheight, NumCast(doc.scrollHeight, NumCast(doc[docView.LayoutFieldKey + '-scrollHeight']))) * docView.NativeDimScaling();
                         dH && (doc._height = actualdH > maxHeight && maxHeight ? maxHeight : actualdH);
@@ -619,7 +619,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                         dH && (doc._autoHeight = false);
 
                         const rotCtr2 = [NumCast(doc._width) / 2, NumCast(doc._height) / 2];
-                        const tlRotated2 = Utils.rotPt(-rotCtr2[0], -rotCtr2[1], (NumCast(doc._jitterRotation) / 180) * Math.PI);
+                        const tlRotated2 = Utils.rotPt(-rotCtr2[0], -rotCtr2[1], (NumCast(doc._rotation) / 180) * Math.PI);
                         doc.x = NumCast(doc.x) + tlRotated.x + rotCtr[0] - (tlRotated2.x + rotCtr2[0]); // doc shifts by amount topleft moves because rotation is about center of doc
                         doc.y = NumCast(doc.y) + tlRotated.y + rotCtr[1] - (tlRotated2.y + rotCtr2[1]);
                     }
@@ -695,7 +695,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
             const loccenter = Utils.rotPt(
                 NumCast(seldocview.rootDoc.rotateCenterX) * NumCast(seldocview.layoutDoc._width),
                 NumCast(seldocview.rootDoc.rotateCenterY) * NumCast(seldocview.layoutDoc._height),
-                (NumCast(seldocview.rootDoc._jitterRotation) / 180) * Math.PI
+                (NumCast(seldocview.rootDoc._rotation) / 180) * Math.PI
             );
             return seldocview.props
                 .ScreenToLocalTransform()
@@ -783,7 +783,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         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 = seldocview.rootDoc.type !== DocumentType.EQUATION; // when do we want an object to not rotate?
-        const rotation = NumCast(seldocview.rootDoc._jitterRotation);
+        const rotation = NumCast(seldocview.rootDoc._rotation);
 
         const resizerScheme = colorScheme ? 'documentDecorations-resizer' + colorScheme : '';
 
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index bd6cea28a..22b0380a2 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -289,29 +289,29 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                             })}
                             Document={LightboxView.LightboxDoc}
                             DataDoc={undefined}
+                            PanelWidth={this.lightboxWidth}
+                            PanelHeight={this.lightboxHeight}
                             LayoutTemplate={LightboxView.LightboxDocTemplate}
-                            addDocument={undefined}
                             isDocumentActive={returnFalse}
                             isContentActive={returnTrue}
-                            addDocTab={this.addDocTab}
-                            pinToPres={TabDocView.PinDoc}
-                            onBrowseClick={MainView.Instance.exploreMode}
+                            styleProvider={DefaultStyleProvider}
+                            ScreenToLocalTransform={this.lightboxScreenToLocal}
+                            renderDepth={0}
                             rootSelected={returnTrue}
                             docViewPath={returnEmptyDoclist}
                             docFilters={this.docFilters}
-                            removeDocument={undefined}
-                            styleProvider={DefaultStyleProvider}
-                            ScreenToLocalTransform={this.lightboxScreenToLocal}
-                            PanelWidth={this.lightboxWidth}
-                            PanelHeight={this.lightboxHeight}
-                            focus={DocUtils.DefaultFocus}
-                            whenChildContentsActiveChanged={emptyFunction}
-                            bringToFront={emptyFunction}
                             docRangeFilters={returnEmptyFilter}
                             searchFilterDocs={returnEmptyDoclist}
                             ContainingCollectionView={undefined}
                             ContainingCollectionDoc={undefined}
-                            renderDepth={0}
+                            addDocument={undefined}
+                            removeDocument={undefined}
+                            whenChildContentsActiveChanged={emptyFunction}
+                            addDocTab={this.addDocTab}
+                            pinToPres={TabDocView.PinDoc}
+                            bringToFront={emptyFunction}
+                            onBrowseClick={MainView.Instance.exploreMode}
+                            focus={DocUtils.DefaultFocus}
                         />
                     </GestureOverlay>
                 </div>
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 03c0642ed..4dc1ebd99 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -647,6 +647,7 @@ export class MainView extends React.Component {
                         e.preventDefault();
                     }}
                     style={{
+                        width: `calc(100% - ${this._leftMenuFlyoutWidth + this.leftMenuWidth() + this.propertiesWidth()}px)`,
                         minWidth: `calc(100% - ${this._leftMenuFlyoutWidth + this.leftMenuWidth() + this.propertiesWidth()}px)`,
                         transform: LightboxView.LightboxDoc ? 'scale(0.0001)' : undefined,
                     }}>
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 2eb3dd532..bc8bd7b7f 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -85,7 +85,6 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
     const isAnnotated = property.includes(':annotated');
     const isOpen = property.includes(':open');
     const fieldKey = props?.fieldKey ? props.fieldKey + '-' : isCaption ? 'caption-' : '';
-    const comicStyle = () => doc && !Doc.IsSystem(doc) && Doc.UserDoc().renderStyle === 'comic';
     const isBackground = () => doc && BoolCast(doc._lockedPosition);
     const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor);
     const opacity = () => props?.styleProvider?.(doc, props, StyleProp.Opacity);
@@ -167,11 +166,11 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
         case StyleProp.TitleHeight:
             return 15;
         case StyleProp.BorderPath:
-            return comicStyle() && props?.renderDepth && doc?.type !== DocumentType.INK
+            return Doc.IsComicStyle(doc) && props?.renderDepth && doc?.type !== DocumentType.INK
                 ? { path: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0), fill: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0, 0.08), width: 3 }
                 : { path: undefined, width: 0 };
         case StyleProp.JitterRotation:
-            return comicStyle() ? random(-1, 1, NumCast(doc?.x), NumCast(doc?.y)) * ((props?.PanelWidth() || 0) > (props?.PanelHeight() || 0) ? 5 : 10) : 0;
+            return Doc.IsComicStyle(doc) ? random(-1, 1, NumCast(doc?.x), NumCast(doc?.y)) * ((props?.PanelWidth() || 0) > (props?.PanelHeight() || 0) ? 5 : 10) : 0;
         case StyleProp.HeaderMargin:
             return ([CollectionViewType.Stacking, CollectionViewType.NoteTaking, CollectionViewType.Masonry, CollectionViewType.Tree].includes(doc?._viewType as any) ||
                 (doc?.type === DocumentType.RTF && !showTitle()?.includes('noMargin')) ||
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index ba29b1d6f..77b47ed82 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -350,6 +350,8 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
                 searchFilterDocs={this.searchFilterDocs}
                 ContainingCollectionDoc={this.props.CollectionView?.props.Document}
                 ContainingCollectionView={this.props.CollectionView}
+                xPadding={NumCast(this.layoutDoc._childXPadding, this.props.childXPadding)}
+                yPadding={NumCast(this.layoutDoc._childYPadding, this.props.childYPadding)}
                 addDocument={this.props.addDocument}
                 moveDocument={this.props.moveDocument}
                 removeDocument={this.props.removeDocument}
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index 1aef29b2f..3785b7d61 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -13,8 +13,6 @@
     width: 100%;
     position: relative;
     top: 0;
-    padding-left: 10px;
-    padding-right: 10px;
     background: $light-gray;
     font-size: 13px;
     overflow: auto;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 1169f692a..0ff89c5a7 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -58,7 +58,6 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
     private _isDisposing = false; // notes that instance is in process of being disposed
     private refList: Set<any> = new Set(); // list of tree view items to monitor for height changes
     private observer: any; // observer for monitoring tree view items.
-    private static expandViewLabelSize = 20;
 
     @computed get doc() {
         return this.props.Document;
@@ -100,7 +99,10 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         Object.values(this._disposers).forEach(disposer => disposer?.());
     }
 
+    shrinkWrap = () => {}; // placeholder to allow setContentView to work
+
     componentDidMount() {
+        //this.props.setContentView?.(this);
         this._disposers.autoheight = reaction(
             () => this.rootDoc.autoHeight,
             auto => auto && this.computeHeight(),
@@ -197,9 +199,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
     onTreeDrop = (e: React.DragEvent, addDocs?: (docs: Doc[]) => void) => this.onExternalDrop(e, {}, addDocs);
 
     @undoBatch
-    makeTextCollection = (childDocs: Doc[]) => {
-        this.addDoc(TreeView.makeTextBullet(), childDocs.length ? childDocs[0] : undefined, true);
-    };
+    makeTextCollection = (childDocs: Doc[]) => this.addDoc(TreeView.makeTextBullet(), childDocs.length ? childDocs[0] : undefined, true);
 
     get editableTitle() {
         return (
@@ -258,6 +258,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         const icons = StrListCast(this.doc.childContextMenuIcons);
         return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label }));
     };
+    headerFields = () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields);
     @computed get treeViewElements() {
         TraceMobx();
         const dropAction = StrCast(this.doc.childDropAction) as dropActionType;
@@ -281,7 +282,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
             this.isContentActive,
             this.panelWidth,
             this.props.renderDepth,
-            () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields),
+            this.headerFields,
             [],
             this.props.onCheckedClick,
             this.onChildClick,
@@ -304,7 +305,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
                 className="collectionTreeView-titleBar"
                 ref={action((r: any) => (this._titleRef = r) && (this._titleHeight = r.getBoundingClientRect().height * this.props.ScreenToLocalTransform().Scale))}
                 key={this.doc[Id]}
-                style={!this.outlineMode ? { paddingLeft: this.marginX(), paddingTop: this.marginTop() } : {}}>
+                style={!this.outlineMode ? { marginLeft: this.marginX(), paddingTop: this.marginTop() } : {}}>
                 {this.outlineMode ? this.documentTitle : this.editableTitle}
             </div>
         );
@@ -372,7 +373,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
     documentTitleHeight = () => (this.layoutDoc?.[HeightSym]() || 0) - NumCast(this.layoutDoc.autoHeightMargins);
     truncateTitleWidth = () => this.treeViewtruncateTitleWidth;
     onChildClick = () => this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick);
-    panelWidth = () => Math.max(0, this.props.PanelWidth() - this.marginX() - CollectionTreeView.expandViewLabelSize) * (this.props.NativeDimScaling?.() || 1);
+    panelWidth = () => Math.max(0, this.props.PanelWidth() - 2 * this.marginX() * (this.props.NativeDimScaling?.() || 1));
 
     addAnnotationDocument = (doc: Doc | Doc[]) => this.props.CollectionView?.addDocument(doc, `${this.props.fieldKey}-annotations`) || false;
     remAnnotationDocument = (doc: Doc | Doc[]) => this.props.CollectionView?.removeDocument(doc, `${this.props.fieldKey}-annotations`) || false;
@@ -396,7 +397,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
                     className="collectionTreeView-contents"
                     key="tree"
                     style={{
-                        ...(!titleBar ? { paddingLeft: this.marginX(), paddingTop: this.marginTop() } : {}),
+                        ...(!titleBar ? { marginLeft: this.marginX(), paddingTop: this.marginTop() } : {}),
                         overflow: 'auto',
                         width: '100%',
                         height: '100%',
@@ -405,9 +406,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
                     <div
                         className="collectionTreeView-container"
                         style={{
-                            transform: this.outlineMode ? `scale(${this.nativeDimScaling})` : '',
-                            paddingLeft: `${this.marginX()}px`,
-                            width: this.outlineMode ? `calc(${100 / this.nativeDimScaling}%)` : '',
+                            marginLeft: `${this.marginX()}px`,
                             minHeight: `calc(100% - ${this._titleHeight}px)`,
                         }}
                         onContextMenu={this.onContextMenu}>
@@ -432,24 +431,29 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
     render() {
         TraceMobx();
 
-        return !(this.doc instanceof Doc) || !this.treeChildren ? null : this.doc.treeViewHasOverlay ? (
-            <CollectionFreeFormView
-                {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
-                isAnnotationOverlay={true}
-                isAnnotationOverlayScrollable={true}
-                childDocumentsActive={this.props.isDocumentActive}
-                fieldKey={this.props.fieldKey + '-annotations'}
-                dropAction={'move'}
-                select={emptyFunction}
-                addDocument={this.addAnnotationDocument}
-                removeDocument={this.remAnnotationDocument}
-                moveDocument={this.moveAnnotationDocument}
-                bringToFront={emptyFunction}
-                renderDepth={this.props.renderDepth + 1}>
-                {this.contentFunc}
-            </CollectionFreeFormView>
-        ) : (
-            this.contentFunc()
+        const scale = (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1) || 1;
+        return (
+            <div style={{ transform: `scale(${scale})`, transformOrigin: 'top left', width: `${100 / scale}%`, height: `${100 / scale}%` }}>
+                {!(this.doc instanceof Doc) || !this.treeChildren ? null : this.doc.treeViewHasOverlay ? (
+                    <CollectionFreeFormView
+                        {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
+                        isAnnotationOverlay={true}
+                        isAnnotationOverlayScrollable={true}
+                        childDocumentsActive={this.props.isDocumentActive}
+                        fieldKey={this.props.fieldKey + '-annotations'}
+                        dropAction={'move'}
+                        select={emptyFunction}
+                        addDocument={this.addAnnotationDocument}
+                        removeDocument={this.remAnnotationDocument}
+                        moveDocument={this.moveAnnotationDocument}
+                        bringToFront={emptyFunction}
+                        renderDepth={this.props.renderDepth + 1}>
+                        {this.contentFunc}
+                    </CollectionFreeFormView>
+                ) : (
+                    this.contentFunc()
+                )}
+            </div>
         );
     }
 }
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index dcaad5632..9f63a11aa 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -54,6 +54,8 @@ interface CollectionViewProps_ extends FieldViewProps {
     childHideDecorationTitle?: () => boolean;
     childHideResizeHandles?: () => boolean;
     childLayoutTemplate?: () => Doc | undefined; // specify a layout Doc template to use for children of the collection
+    childXPadding?: number;
+    childYPadding?: number;
     childLayoutString?: string;
     childIgnoreNativeSize?: boolean;
     childClickScript?: ScriptField;
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index a6cfbd6b2..cde5132a3 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -256,7 +256,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             pinDoc.treeViewChildrenOnRoot = true; // tree view will look for hierarchical children on the root doc, not the data doc.
             pinDoc.treeViewFieldKey = 'data'; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field
             pinDoc.treeViewExpandedView = 'data'; // in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view
-            pinDoc.treeViewGrowsHorizontally = true; // the document expands horizontally when displayed as a tree view header
             pinDoc.treeViewHideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header
             const presArray: Doc[] = PresBox.Instance?.sortArray();
             const size: number = PresBox.Instance?.selectedArray.size;
diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss
index 57bb5274d..83fee013a 100644
--- a/src/client/views/collections/TreeView.scss
+++ b/src/client/views/collections/TreeView.scss
@@ -24,6 +24,7 @@
         // width: $TREE_BULLET_WIDTH;
         width: 100%;
         height: 100%;
+        position: absolute;
 
         .treeView-expandIcon {
             display: none;
@@ -118,7 +119,7 @@
     display: flex; // needed for PresBox's treeView
     border: transparent 1px solid;
     align-items: center;
-    width: 100%;
+    width: max-content;
     border-radius: 5px;
 
     &:hover {
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index b9f86fa6b..1e97eee37 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -10,7 +10,7 @@ import { listSpec } from '../../../fields/Schema';
 import { ComputedField, ScriptField } from '../../../fields/ScriptField';
 import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { TraceMobx } from '../../../fields/util';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, simulateMouseClick, Utils } from '../../../Utils';
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, simulateMouseClick, Utils } from '../../../Utils';
 import { Docs, DocUtils } from '../../documents/Documents';
 import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
 import { DocumentManager } from '../../util/DocumentManager';
@@ -321,6 +321,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             _viewType: CollectionViewType.Tree,
             hideLinkButton: true,
             _showSidebar: true,
+            _fitWidth: true,
             treeViewType: TreeViewType.outline,
             x: 0,
             y: 0,
@@ -398,29 +399,22 @@ export class TreeView extends React.Component<TreeViewProps> {
     };
     docTransform = () => this.refTransform(this._dref?.ContentRef?.current);
     getTransform = () => this.refTransform(this._tref.current);
-    docWidth = () => {
-        const layoutDoc = this.layoutDoc;
-        const aspect = Doc.NativeAspect(layoutDoc);
-        if (layoutDoc._fitWidth) return Math.min(this.props.panelWidth() - treeBulletWidth(), layoutDoc[WidthSym]());
-        if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT * aspect, this.props.panelWidth() - treeBulletWidth()));
-        return Math.min((this.props.panelWidth() - treeBulletWidth()) / (this.props.treeView.props.NativeDimScaling?.() || 1), Doc.NativeWidth(layoutDoc) ? layoutDoc[WidthSym]() : this.layoutDoc[WidthSym]());
-    };
-    docHeight = () => {
-        const layoutDoc = this.layoutDoc;
-        return Math.max(
-            70,
-            Math.min(
-                this.MAX_EMBED_HEIGHT,
-                (() => {
-                    const aspect = Doc.NativeAspect(layoutDoc);
-                    if (aspect) return this.docWidth() / (aspect || 1);
-                    return layoutDoc._fitWidth
-                        ? !Doc.NativeHeight(this.doc)
-                            ? NumCast(this.props.containerCollection._height)
-                            : Math.min((this.docWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc))) / (Doc.NativeWidth(layoutDoc) || NumCast(this.props.containerCollection._height)))
-                        : layoutDoc[HeightSym]() || 50;
-                })()
-            )
+    embeddedPanelWidth = () => this.props.panelWidth() / (this.props.treeView.props.NativeDimScaling?.() || 1);
+    embeddedPanelHeight = () => {
+        console.log(this.props.treeView.rootDoc.title);
+        const layoutDoc = (temp => temp && Doc.expandTemplateLayout(temp, this.props.document, ''))(this.props.treeView.props.childLayoutTemplate?.()) || this.layoutDoc;
+        return Math.min(
+            layoutDoc[HeightSym](),
+            this.MAX_EMBED_HEIGHT,
+            (() => {
+                const aspect = Doc.NativeAspect(layoutDoc);
+                if (aspect) return this.embeddedPanelWidth() / (aspect || 1);
+                return layoutDoc._fitWidth
+                    ? !Doc.NativeHeight(layoutDoc)
+                        ? NumCast(layoutDoc._height) //this.props.containerCollection._height)
+                        : Math.min((this.embeddedPanelWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc))) / (Doc.NativeWidth(layoutDoc) || NumCast(this.props.containerCollection._height)))
+                    : (this.embeddedPanelWidth() * layoutDoc[HeightSym]()) / layoutDoc[WidthSym]();
+            })()
         );
     };
 
@@ -512,28 +506,6 @@ export class TreeView extends React.Component<TreeViewProps> {
         return rows;
     }
 
-    rtfWidth = () => {
-        const layout = (temp => temp && Doc.expandTemplateLayout(temp, this.props.document, ''))(this.props.treeView.props.childLayoutTemplate?.()) || this.layoutDoc;
-        return Math.min(layout[WidthSym](), this.props.panelWidth() - treeBulletWidth()) / (this.props.treeView.props.NativeDimScaling?.() || 1);
-    };
-    rtfHeight = () => {
-        const layout = (temp => temp && Doc.expandTemplateLayout(temp, this.props.document, ''))(this.props.treeView.props.childLayoutTemplate?.()) || this.layoutDoc;
-        return this.rtfWidth() <= layout[WidthSym]() ? Math.min(layout[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT;
-    };
-    rtfOutlineHeight = () => Math.max(this.layoutDoc?.[HeightSym](), treeBulletWidth());
-    expandPanelHeight = () => {
-        if (this.layoutDoc._fitWidth) return this.docHeight();
-        const aspect = this.layoutDoc[WidthSym]() / this.layoutDoc[HeightSym]();
-        const docAspect = this.docWidth() / this.docHeight();
-        return docAspect < aspect ? this.docWidth() / aspect : this.docHeight();
-    };
-    expandPanelWidth = () => {
-        if (this.layoutDoc._fitWidth) return this.docWidth();
-        const aspect = this.layoutDoc[WidthSym]() / this.layoutDoc[HeightSym]();
-        const docAspect = this.docWidth() / this.docHeight();
-        return docAspect > aspect ? this.docHeight() * aspect : this.docWidth();
-    };
-
     @computed get renderContent() {
         TraceMobx();
         const expandKey = this.treeViewExpandedView;
@@ -792,15 +764,18 @@ export class TreeView extends React.Component<TreeViewProps> {
     titleStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string): any => {
         if (!doc || doc !== this.doc) return this.props?.treeView?.props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
 
+        const treeView = this.props.treeView;
         // prettier-ignore
         switch (property.split(':')[0]) {
             case StyleProp.Opacity:         return this.props.treeView.outlineMode ? undefined : 1;
             case StyleProp.BackgroundColor: return this.selected ? '#7089bb' : StrCast(doc._backgroundColor, StrCast(doc.backgroundColor));
             case StyleProp.Highlighting:    if (this.props.treeView.outlineMode) return undefined;
+            case StyleProp.Hidden:          return false;
+            case StyleProp.BoxShadow:       return undefined;
             case StyleProp.DocContents:
                 const highlightIndex = this.props.treeView.outlineMode ? Doc.DocBrushStatus.unbrushed : Doc.isBrushedHighlightedDegree(doc);
                 const highlightColor = ['transparent', 'rgb(68, 118, 247)', 'rgb(68, 118, 247)', 'orange', 'lightBlue'][highlightIndex];
-                return this.props.treeView.outlineMode ? null : (
+                return treeView.outlineMode ? null : (
                     <div
                         className="treeView-label"
                         style={{
@@ -808,15 +783,20 @@ export class TreeView extends React.Component<TreeViewProps> {
                             maxWidth: props?.PanelWidth() || undefined,
                             background: props?.styleProvider?.(doc, props, StyleProp.BackgroundColor),
                             outline: `solid ${highlightColor} ${highlightIndex}px`,
+                            paddingLeft: NumCast(treeView.rootDoc.childXPadding, NumCast(treeView.props.childXPadding, Doc.IsComicStyle(doc)?20:0)),
+                            paddingRight: NumCast(treeView.rootDoc.childXPadding, NumCast(treeView.props.childXPadding, Doc.IsComicStyle(doc)?20:0)),
+                            paddingTop: treeView.props.childYPadding,
+                            paddingBottom: treeView.props.childYPadding,
                         }}>
                         {StrCast(doc?.title)}
                     </div>
                 );
         }
-        return this.props?.treeView?.props.styleProvider?.(doc, props, property);
+        return treeView.props.styleProvider?.(doc, props, property);
     };
     embeddedStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string): any => {
         if (property.startsWith(StyleProp.Decorations)) return null;
+        if (property.startsWith(StyleProp.Hidden)) return false;
         return this.props?.treeView?.props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
     };
     onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => {
@@ -843,7 +823,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         }
         return false;
     };
-    titleWidth = () => Math.max(20, Math.min(this.props.treeView.truncateTitleWidth(), this.props.panelWidth() - 2 * treeBulletWidth()));
+    titleWidth = () => Math.max(20, Math.min(this.props.treeView.truncateTitleWidth(), this.props.panelWidth())) / (this.props.treeView.props.NativeDimScaling?.() || 1) - 3 * treeBulletWidth();
 
     return18 = () => 18;
     /**
@@ -851,6 +831,7 @@ export class TreeView extends React.Component<TreeViewProps> {
      */
     @computed
     get renderTitle() {
+        //
         TraceMobx();
         const view = this._editTitle ? (
             <EditableView
@@ -887,6 +868,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                     }
                 })}
                 Document={this.doc}
+                fitWidth={(doc: Doc) => true}
                 DataDoc={undefined}
                 scriptContext={this}
                 hideDecorationTitle={this.props.treeView.outlineMode}
@@ -905,7 +887,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 removeDocument={this.props.removeDoc}
                 ScreenToLocalTransform={this.getTransform}
                 NativeHeight={this.return18}
-                NativeWidth={this.titleWidth}
+                NativeWidth={returnZero}
                 PanelWidth={this.titleWidth}
                 PanelHeight={this.return18}
                 contextMenuItems={this.contextMenuItems}
@@ -918,10 +900,12 @@ export class TreeView extends React.Component<TreeViewProps> {
                 disableDocBrushing={this.props.treeView.props.disableDocBrushing}
                 hideLinkButton={BoolCast(this.props.treeView.props.Document.childHideLinkButton)}
                 dontRegisterView={BoolCast(this.props.treeView.props.Document.childDontRegisterViews, this.props.dontRegisterView)}
+                xPadding={NumCast(this.props.treeView.props.Document.childXPadding, this.props.treeView.props.childXPadding)}
+                yPadding={NumCast(this.props.treeView.props.Document.childYPadding, this.props.treeView.props.childYPadding)}
                 docFilters={returnEmptyFilter}
                 docRangeFilters={returnEmptyFilter}
                 searchFilterDocs={returnEmptyDoclist}
-                ContainingCollectionView={undefined}
+                ContainingCollectionView={this.props.treeView.props.CollectionView}
                 ContainingCollectionDoc={this.props.treeView.props.Document}
             />
         );
@@ -968,53 +952,52 @@ export class TreeView extends React.Component<TreeViewProps> {
     };
 
     renderEmbeddedDocument = (asText: boolean, isActive: () => boolean | undefined) => {
-        const isExpandable = this.doc._treeViewGrowsHorizontally;
-        const panelWidth = asText || isExpandable ? this.rtfWidth : this.expandPanelWidth;
-        const panelHeight = asText ? this.rtfOutlineHeight : isExpandable ? this.rtfHeight : this.expandPanelHeight;
         return (
-            <DocumentView
-                key={this.doc[Id]}
-                ref={action((r: DocumentView | null) => (this._dref = r))}
-                Document={this.doc}
-                DataDoc={undefined}
-                PanelWidth={panelWidth}
-                PanelHeight={panelHeight}
-                NativeWidth={!asText && (this.layoutDoc.type === DocumentType.RTF || this.layoutDoc.type === DocumentType.SLIDER) ? this.rtfWidth : undefined}
-                NativeHeight={!asText && (this.layoutDoc.type === DocumentType.RTF || this.layoutDoc.type === DocumentType.SLIDER) ? this.rtfHeight : undefined}
-                LayoutTemplateString={asText ? FormattedTextBox.LayoutString('text') : undefined}
-                LayoutTemplate={this.props.treeView.props.childLayoutTemplate}
-                isContentActive={isActive}
-                isDocumentActive={isActive}
-                styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider}
-                hideTitle={asText}
-                fitContentsToBox={returnTrue}
-                hideDecorationTitle={this.props.treeView.outlineMode}
-                hideResizeHandles={this.props.treeView.outlineMode}
-                onClick={this.onChildClick}
-                focus={this.refocus}
-                onKey={this.onKeyDown}
-                hideLinkButton={BoolCast(this.props.treeView.props.Document.childHideLinkButton)}
-                dontRegisterView={BoolCast(this.props.treeView.props.Document.childDontRegisterViews, this.props.dontRegisterView)}
-                ScreenToLocalTransform={this.docTransform}
-                renderDepth={this.props.renderDepth + 1}
-                treeViewDoc={this.props.treeView?.props.Document}
-                rootSelected={returnTrue}
-                docViewPath={this.props.treeView.props.docViewPath}
-                docFilters={returnEmptyFilter}
-                docRangeFilters={returnEmptyFilter}
-                searchFilterDocs={returnEmptyDoclist}
-                ContainingCollectionDoc={this.props.containerCollection}
-                ContainingCollectionView={undefined}
-                addDocument={this.props.addDocument}
-                moveDocument={this.move}
-                removeDocument={this.props.removeDoc}
-                whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
-                addDocTab={this.props.addDocTab}
-                pinToPres={this.props.treeView.props.pinToPres}
-                disableDocBrushing={this.props.treeView.props.disableDocBrushing}
-                bringToFront={returnFalse}
-                scriptContext={this}
-            />
+            <div style={{ height: this.embeddedPanelHeight(), width: this.embeddedPanelWidth() }}>
+                <DocumentView
+                    key={this.doc[Id]}
+                    ref={action((r: DocumentView | null) => (this._dref = r))}
+                    Document={this.doc}
+                    DataDoc={undefined}
+                    PanelWidth={this.embeddedPanelWidth}
+                    PanelHeight={this.embeddedPanelHeight}
+                    LayoutTemplateString={asText ? FormattedTextBox.LayoutString('text') : undefined}
+                    LayoutTemplate={this.props.treeView.props.childLayoutTemplate}
+                    isContentActive={isActive}
+                    isDocumentActive={isActive}
+                    styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider}
+                    hideTitle={asText}
+                    //fitContentsToBox={returnTrue}
+                    hideDecorationTitle={this.props.treeView.outlineMode}
+                    hideResizeHandles={this.props.treeView.outlineMode}
+                    onClick={this.onChildClick}
+                    focus={this.refocus}
+                    onKey={this.onKeyDown}
+                    hideLinkButton={BoolCast(this.props.treeView.props.Document.childHideLinkButton)}
+                    dontRegisterView={BoolCast(this.props.treeView.props.Document.childDontRegisterViews, this.props.dontRegisterView)}
+                    ScreenToLocalTransform={this.docTransform}
+                    renderDepth={this.props.renderDepth + 1}
+                    treeViewDoc={this.props.treeView?.props.Document}
+                    rootSelected={returnTrue}
+                    docViewPath={this.props.treeView.props.docViewPath}
+                    docFilters={returnEmptyFilter}
+                    docRangeFilters={returnEmptyFilter}
+                    searchFilterDocs={returnEmptyDoclist}
+                    ContainingCollectionDoc={this.props.containerCollection}
+                    ContainingCollectionView={undefined}
+                    addDocument={this.props.addDocument}
+                    moveDocument={this.move}
+                    removeDocument={this.props.removeDoc}
+                    whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
+                    xPadding={NumCast(this.props.treeView.props.Document.childXPadding, this.props.treeView.props.childXPadding)}
+                    yPadding={NumCast(this.props.treeView.props.Document.childYPadding, this.props.treeView.props.childYPadding)}
+                    addDocTab={this.props.addDocTab}
+                    pinToPres={this.props.treeView.props.pinToPres}
+                    disableDocBrushing={this.props.treeView.props.disableDocBrushing}
+                    bringToFront={returnFalse}
+                    scriptContext={this}
+                />
+            </div>
         );
     };
 
@@ -1148,7 +1131,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         }
 
         const docs = TreeView.sortDocs(childDocs, StrCast(containerCollection.treeViewSortCriterion, TreeSort.None));
-        const rowWidth = () => panelWidth() - treeBulletWidth();
+        const rowWidth = () => panelWidth() - treeBulletWidth() * (treeView.props.NativeDimScaling?.() || 1);
         const treeViewRefs = new Map<Doc, TreeView | undefined>();
         return docs
             .filter(child => child instanceof Doc)
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 559951efc..2f246e74f 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1317,7 +1317,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 dontScaleFilter={this.props.dontScaleFilter}
                 dontRegisterView={this.props.dontRenderDocuments || this.props.dontRegisterView}
                 pointerEvents={this.pointerEvents}
-                jitterRotation={this.props.styleProvider?.(childLayout, this.props, StyleProp.JitterRotation) || 0}
+                rotation={this.props.styleProvider?.(childLayout, this.props, StyleProp.JitterRotation) || 0}
                 //fitContentsToBox={this.props.fitContentsToBox || BoolCast(this.props.freezeChildDimensions)} // bcz: check this
             />
         );
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 04c7b96e3..260c98816 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -25,7 +25,7 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
     renderCutoffProvider: (doc: Doc) => boolean;
     zIndex?: number;
     highlight?: boolean;
-    jitterRotation: number;
+    rotation: number;
     dataTransition?: string;
     replica: string;
     CollectionFreeFormView: CollectionFreeFormView;
@@ -38,7 +38,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
         { key: '_width' },
         { key: 'x' },
         { key: 'y' },
-        { key: '_jitterRotation', val: 0 },
+        { key: '_rotation', val: 0 },
         { key: '_scrollTop' },
         { key: 'opacity', val: 1 },
         { key: 'viewScale', val: 1 },
@@ -55,7 +55,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     }
 
     get transform() {
-        return `translate(${this.X}px, ${this.Y}px) rotate(${NumCast(this.Document.jitterRotation, this.props.jitterRotation)}deg)`;
+        return `translate(${this.X}px, ${this.Y}px) rotate(${NumCast(this.Document.rotation, this.props.rotation)}deg)`;
     }
     get X() {
         return this.dataProvider?.x ?? NumCast(this.Document.x);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index fecbc2de2..5b26469ed 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -53,6 +53,7 @@ import { RadialMenu } from './RadialMenu';
 import { ScriptingBox } from './ScriptingBox';
 import { PresBox } from './trails/PresBox';
 import React = require('react');
+import { CollectionTreeView } from '../collections/CollectionTreeView';
 const { Howl } = require('howler');
 
 interface Window {
@@ -147,6 +148,8 @@ export interface DocumentViewSharedProps {
     pinToPres: (document: Doc) => void;
     ScreenToLocalTransform: () => Transform;
     bringToFront: (doc: Doc, sendToBack?: boolean) => void;
+    xPadding?: number;
+    yPadding?: number;
     dropAction?: dropActionType;
     dontRegisterView?: boolean;
     hideLinkButton?: boolean;
@@ -1349,17 +1352,10 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             this.contents
         ) : (
             <div className="documentView-styleWrapper">
-                {!this.headerMargin ? (
-                    <>
-                        {' '}
-                        {this.contents} {titleView}{' '}
-                    </>
-                ) : (
-                    <>
-                        {' '}
-                        {titleView} {this.contents}{' '}
-                    </>
-                )}
+                {' '}
+                {!this.headerMargin ? this.contents : titleView}
+                {!this.headerMargin ? titleView : this.contents}
+                {' ' /* */}
                 {captionView}
             </div>
         );
@@ -1372,7 +1368,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         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;
+        if (!(this.props.Document instanceof Doc) || GetEffectiveAcl(this.props.Document[DataSym]) === AclPrivate || this.hidden) return null;
         return (
             this.docContents ?? (
                 <div
@@ -1448,7 +1444,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     <>
                         {animRenderDoc}
                         <div key="border2" className="documentView-customBorder" style={{ pointerEvents: 'none' }}>
-                            <svg style={{ overflow: 'visible' }} viewBox={`0 0 ${this.props.PanelWidth()} ${this.props.PanelHeight()}`}>
+                            <svg style={{ overflow: 'visible', height: '100%' }} viewBox={`0 0 ${this.props.PanelWidth()} ${this.props.PanelHeight()}`}>
                                 <path d={borderPath.path} style={{ stroke: 'black', fill: 'transparent', strokeWidth: borderPath.width }} />
                             </svg>
                         </div>
@@ -1552,7 +1548,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, !this.fitWidth));
     }
     @computed get shouldNotScale() {
-        return (this.fitWidth && !this.nativeWidth) || this.props.dontScaleFilter?.(this.Document) || this.props.treeViewDoc || [CollectionViewType.Docking].includes(this.Document._viewType as any);
+        return (this.fitWidth && !this.nativeWidth) || this.props.dontScaleFilter?.(this.Document) || [CollectionViewType.Docking].includes(this.Document._viewType as any);
     }
     @computed get effectiveNativeWidth() {
         return this.shouldNotScale ? 0 : this.nativeWidth || NumCast(this.layoutDoc.width);
@@ -1597,7 +1593,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     toggleNativeDimensions = () => this.docView && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.NativeDimScaling, this.props.PanelWidth(), this.props.PanelHeight());
     focus = (doc: Doc, options: DocFocusOptions) => this.docView?.focus(doc, options);
     getBounds = () => {
-        if (!this.docView || !this.docView.ContentDiv || this.props.Document.presBox || this.docView.props.treeViewDoc || Doc.AreProtosEqual(this.props.Document, Doc.UserDoc())) {
+        if (!this.docView || !this.docView.ContentDiv || this.props.Document.presBox || this.props.treeViewDoc || Doc.AreProtosEqual(this.props.Document, Doc.UserDoc())) {
             return undefined;
         }
         const xf = this.docView?.props.ScreenToLocalTransform().scale(this.nativeScaling).inverse();
@@ -1687,10 +1683,9 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     render() {
         TraceMobx();
-        const xshift = () => (Math.abs(this.Xshift) <= 0.001 ? this.props.PanelWidth() : undefined);
-        const yshift = () => (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;
+        const xshift = Math.abs(this.Xshift) <= 0.001 ? this.props.PanelWidth() : undefined;
+        const yshift = Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined;
+        const isButton = this.props.Document.type === DocumentType.FONTICON || this.props.Document._viewType === CollectionViewType.Linear;
         return (
             <div className="contentFittingDocumentView">
                 {!this.props.Document || !this.props.PanelWidth() ? null : (
@@ -1700,11 +1695,11 @@ export class DocumentView extends React.Component<DocumentViewProps> {
                         style={{
                             transition: this.props.dataTransition,
                             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()}%`,
+                            width: isButton ? '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()}%`),
+                                    : yshift ?? (this.fitWidth ? `${this.panelHeight}px` : `${(((100 * this.effectiveNativeHeight) / this.effectiveNativeWidth) * this.props.PanelWidth()) / this.props.PanelHeight()}%`),
                         }}>
                         <DocumentViewInternal
                             {...this.props}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 77aaa4441..e53422ab7 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -36,8 +36,6 @@ export interface FieldViewProps extends DocumentViewSharedProps {
     fontSize?: number;
     height?: number;
     width?: number;
-    xPadding?: number;
-    yPadding?: number;
     noSidebar?: boolean;
     dontScale?: boolean;
     dontSelectOnLoad?: boolean; // suppress selecting (e.g.,. text box) when loaded (and mark as not being associated with scrollTop document field)
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index f7f558bb4..fb47bfc07 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -935,7 +935,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
                     className="videoBox-ui"
                     style={{
                         transformOrigin: 'top left',
-                        transform: `rotate(${NumCast(this.rootDoc.jitterRotation)}deg) translate(${-(xRight - xPos) + 10}px, ${yBot - yMid - uiHeight - uiMargin}px)`,
+                        transform: `rotate(${NumCast(this.rootDoc.rotation)}deg) translate(${-(xRight - xPos) + 10}px, ${yBot - yMid - uiHeight - uiMargin}px)`,
                         left: xPos,
                         top: yMid,
                         height: uiHeight,
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 5470d6ba9..096f9a92c 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1004,11 +1004,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
             () => this.autoHeight,
             autoHeight => autoHeight && this.tryUpdateScrollHeight()
         );
+        this._disposers.width = reaction(
+            () => this.props.PanelWidth(),
+            width => this.tryUpdateScrollHeight()
+        );
         this._disposers.scrollHeight = reaction(
             () => ({ scrollHeight: this.scrollHeight, autoHeight: this.autoHeight, width: NumCast(this.layoutDoc._width) }),
-            ({ width, scrollHeight, autoHeight }) => {
-                width && autoHeight && this.resetNativeHeight(scrollHeight);
-            },
+            ({ width, scrollHeight, autoHeight }) => width && autoHeight && this.resetNativeHeight(scrollHeight),
             { fireImmediately: true }
         );
         this._disposers.componentHeights = reaction(
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 258dad39c..4e8aed8a6 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -429,7 +429,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             pinDoc.presPinLayout = true;
             pinDoc.presX = NumCast(targetDoc.x);
             pinDoc.presY = NumCast(targetDoc.y);
-            pinDoc.presRot = NumCast(targetDoc.jitterRotation);
+            pinDoc.presRot = NumCast(targetDoc.rotation);
             pinDoc.presWidth = NumCast(targetDoc.width);
             pinDoc.presHeight = NumCast(targetDoc.height);
         }
@@ -521,7 +521,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             targetDoc._dataTransition = presTransitionTime;
             targetDoc.x = NumCast(activeItem.presX, NumCast(targetDoc.x));
             targetDoc.y = NumCast(activeItem.presY, NumCast(targetDoc.y));
-            targetDoc.jitterRotation = NumCast(activeItem.presRot, NumCast(targetDoc.jitterRotation));
+            targetDoc.rotation = NumCast(activeItem.presRot, NumCast(targetDoc.rotation));
             targetDoc.width = NumCast(activeItem.presWidth, NumCast(targetDoc.width));
             targetDoc.height = NumCast(activeItem.presHeight, NumCast(targetDoc.height));
             setTimeout(() => (targetDoc._dataTransition = undefined), transTime + 10);
@@ -2652,9 +2652,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 PanelHeight={this.panelHeight}
                                 childIgnoreNativeSize={true}
                                 moveDocument={returnFalse}
-                                childFitWidth={returnTrue}
+                                //childFitWidth={returnTrue}
                                 childOpacity={returnOne}
                                 childLayoutTemplate={this.childLayoutTemplate}
+                                childXPadding={Doc.IsComicStyle(this.rootDoc) ? 20 : undefined}
                                 filterAddDocument={this.addDocumentFilter}
                                 removeDocument={returnFalse}
                                 dontRegisterView={true}
diff --git a/src/client/views/nodes/trails/PresElementBox.scss b/src/client/views/nodes/trails/PresElementBox.scss
index 8a6c2a6dc..415253af1 100644
--- a/src/client/views/nodes/trails/PresElementBox.scss
+++ b/src/client/views/nodes/trails/PresElementBox.scss
@@ -42,10 +42,7 @@ $slide-active: #5b9fdd;
     width: 100%;
     border-bottom: 0.5px solid grey;
     display: flex;
-    justify-content: space-between;
     align-items: center;
-    grid-template-rows: 16px 10px auto;
-    grid-template-columns: max-content max-content max-content max-content auto;
 
     .presItem-name {
         display: flex;
@@ -102,13 +99,7 @@ $slide-active: #5b9fdd;
         grid-row: 3;
         grid-column: 1/8;
         position: relative;
-        display: flex;
-        width: auto;
-        justify-content: center;
-        margin: auto;
-        margin-bottom: 2px;
-        border-bottom-left-radius: 5px;
-        border-bottom-right-radius: 5px;
+        display: inline-block;
     }
 
     .presItem-embeddedMask {
@@ -124,8 +115,7 @@ $slide-active: #5b9fdd;
 
     .presItem-slideButtons {
         display: flex;
-        grid-column: 7;
-        grid-row: 1/3;
+        position: absolute;
         width: max-content;
         justify-self: right;
         justify-content: flex-end;
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index f4ab845f3..5d14a0e9a 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -4,7 +4,9 @@ import { action, computed, IReactionDisposer, observable, reaction } from 'mobx'
 import { observer } from 'mobx-react';
 import { Doc, DocListCast, HeightSym, Opt, WidthSym } from '../../../../fields/Doc';
 import { Copy, Id } from '../../../../fields/FieldSymbols';
+import { InkField } from '../../../../fields/InkField';
 import { List } from '../../../../fields/List';
+import { RichTextField } from '../../../../fields/RichTextField';
 import { Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
 import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils';
 import { Docs, DocUtils } from '../../../documents/Documents';
@@ -14,6 +16,7 @@ import { DragManager } from '../../../util/DragManager';
 import { SettingsManager } from '../../../util/SettingsManager';
 import { Transform } from '../../../util/Transform';
 import { undoBatch } from '../../../util/UndoManager';
+import { MarqueeView } from '../../collections/collectionFreeForm';
 import { ViewBoxBaseComponent } from '../../DocComponent';
 import { EditableView } from '../../EditableView';
 import { Colors } from '../../global/globalEnums';
@@ -24,9 +27,6 @@ import { PresBox } from './PresBox';
 import './PresElementBox.scss';
 import { PresMovement } from './PresEnums';
 import React = require('react');
-import { InkField } from '../../../../fields/InkField';
-import { RichTextField } from '../../../../fields/RichTextField';
-import { MarqueeView } from '../../collections/collectionFreeForm';
 /**
  * This class models the view a document added to presentation will have in the presentation.
  * It involves some functionality for its buttons and options.
@@ -44,8 +44,11 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @computed get indexInPres() {
         return DocListCast(this.presBox[StrCast(this.presBox.presFieldKey, 'data')]).indexOf(this.rootDoc);
     } // 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 expandViewHeight() {
+        return 100;
+    }
     @computed get collapsedHeight() {
-        return [CollectionViewType.Tree, CollectionViewType.Stacking].includes(this.presBox._viewType as any) ? 35 : 31;
+        return 35;
     } // 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 this.presBox.presStatus;
@@ -58,7 +61,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
         return vpath.length > 1 ? (vpath[vpath.length - 2].ComponentView as PresBox) : undefined;
     }
     @computed get presBox() {
-        return (this.props.DocumentView?.().props.treeViewDoc ?? this.props.ContainingCollectionDoc)!;
+        return this.props.ContainingCollectionDoc!;
     }
     @computed get targetDoc() {
         return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc;
@@ -67,8 +70,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
     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)),
+            () => ({ expand: this.rootDoc.presExpandInlineButton, height: this.collapsedHeight }),
+            ({ expand, height }) => (this.layoutDoc._height = height + (expand ? this.expandViewHeight : 0)),
             { fireImmediately: true }
         );
     }
@@ -84,10 +87,10 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @action
     presExpandDocumentClick = () => (this.rootDoc.presExpandInlineButton = !this.rootDoc.presExpandInlineButton);
 
-    embedHeight = (): number => 97;
+    embedHeight = (): number => this.collapsedHeight + this.expandViewHeight;
     // embedWidth = () => this.props.PanelWidth();
     // embedHeight = () => Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - this.collapsedHeight);
-    embedWidth = (): number => this.props.PanelWidth() - 35;
+    embedWidth = (): number => this.props.PanelWidth() / 2;
     styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string): any => {
         if (property === StyleProp.Opacity) return 1;
         return this.props.styleProvider?.(doc, props, property);
@@ -98,35 +101,35 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
      */
     @computed get renderEmbeddedInline() {
         return !this.rootDoc.presExpandInlineButton || !this.targetDoc ? null : (
-            <div className="presItem-embedded" style={{ height: this.embedHeight(), width: this.embedWidth() }}>
+            <div className="presItem-embedded" style={{ height: this.embedHeight(), width: '50%' }}>
                 <DocumentView
                     Document={this.rootDoc}
                     DataDoc={undefined} //this.targetDoc[DataSym] !== this.targetDoc && this.targetDoc[DataSym]}
+                    PanelWidth={this.embedWidth}
+                    PanelHeight={this.embedHeight}
+                    isContentActive={this.props.isContentActive}
                     styleProvider={this.styleProvider}
+                    hideLinkButton={true}
+                    ScreenToLocalTransform={Transform.Identity}
+                    renderDepth={this.props.renderDepth + 1}
                     docViewPath={returnEmptyDoclist}
+                    docFilters={this.props.docFilters}
+                    docRangeFilters={this.props.docRangeFilters}
+                    searchFilterDocs={this.props.searchFilterDocs}
+                    ContainingCollectionView={undefined}
+                    ContainingCollectionDoc={undefined}
                     rootSelected={returnTrue}
                     addDocument={returnFalse}
                     removeDocument={returnFalse}
-                    isContentActive={this.props.isContentActive}
-                    addDocTab={returnFalse}
-                    pinToPres={returnFalse}
                     fitContentsToBox={returnTrue}
-                    PanelWidth={this.embedWidth}
-                    PanelHeight={this.embedHeight}
-                    ScreenToLocalTransform={Transform.Identity}
                     moveDocument={this.props.moveDocument!}
-                    renderDepth={this.props.renderDepth + 1}
                     focus={DocUtils.DefaultFocus}
                     whenChildContentsActiveChanged={returnFalse}
+                    addDocTab={returnFalse}
+                    pinToPres={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 className="presItem-embeddedMask" /> */}
             </div>
         );
     }
@@ -206,8 +209,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
         const dragData = new DragManager.DocumentDragData(this.presBoxView?.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;
+        dragData.treeViewDoc = this.presBox._viewType === CollectionViewType.Tree ? this.props.ContainingCollectionDoc : undefined; // this.props.DocumentView?.()?.props.treeViewDoc;
+        dragData.moveDocument = this.props.moveDocument;
         const dragItem: HTMLElement[] = [];
         if (dragArray.length === 1) {
             const doc = this._itemRef.current || dragArray[0];
@@ -307,7 +310,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
     updateCapturedContainerLayout = (targetDoc: Doc, activeItem: Doc) => {
         activeItem.presX = NumCast(targetDoc.x);
         activeItem.presY = NumCast(targetDoc.y);
-        activeItem.presRot = NumCast(targetDoc.jitterRotation);
+        activeItem.presRot = NumCast(targetDoc.rotation);
         activeItem.presWidth = NumCast(targetDoc.width);
         activeItem.presHeight = NumCast(targetDoc.height);
     };
@@ -464,16 +467,90 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
         return width;
     }
 
+    @computed get presButtons() {
+        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;
+
+        const items: JSX.Element[] = [];
+        if (activeItem.presPinLayout) {
+            items.push(
+                <Tooltip key="slide" title={<div className="dash-tooltip">Update captured doc layout</div>}>
+                    <div className="slideButton" onClick={() => this.updateCapturedContainerLayout(targetDoc, activeItem)} style={{ fontWeight: 700, display: 'flex' }}>
+                        L
+                    </div>
+                </Tooltip>
+            );
+        }
+        if (activeItem.presPinData || activeItem.presPinView) {
+            items.push(
+                <Tooltip key="flex" title={<div className="dash-tooltip">Update captured doc content</div>}>
+                    <div className="slideButton" onClick={() => this.updateCapturedViewContents(targetDoc, activeItem)} style={{ fontWeight: 700, display: 'flex' }}>
+                        C
+                    </div>
+                </Tooltip>
+            );
+        }
+        if (!Doc.noviceMode) {
+            items.push(
+                <Tooltip key="slash" title={<div className="dash-tooltip">{this.recordingIsInOverlay ? 'Hide Recording' : `${PresElementBox.videoIsRecorded(activeItem) ? 'Show' : 'Start'} recording`}</div>}>
+                    <div className="slideButton" onClick={e => (this.recordingIsInOverlay ? this.hideRecording(e, true) : this.startRecording(e, activeItem))} style={{ fontWeight: 700 }}>
+                        <FontAwesomeIcon icon={`video${this.recordingIsInOverlay ? '-slash' : ''}`} onPointerDown={e => e.stopPropagation()} />
+                    </div>
+                </Tooltip>
+            );
+        }
+        if (this.indexInPres === 0) {
+            items.push(
+                <Tooltip key="arrow" 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>
+            );
+        }
+        items.push(
+            <Tooltip key="eye" 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>
+        );
+        items.push(
+            <Tooltip key="trash" title={<div className="dash-tooltip">Remove from presentation</div>}>
+                <div className={'slideButton'} onClick={this.removeItem}>
+                    <FontAwesomeIcon icon={'trash'} onPointerDown={e => e.stopPropagation()} />
+                </div>
+            </Tooltip>
+        );
+        return items;
+    }
+
     @computed get mainItem() {
         const isSelected: boolean = this.selectedArray?.has(this.rootDoc) ? true : false;
         const isCurrent: boolean = this.presBox._itemIndex === this.indexInPres;
-        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 (
@@ -484,6 +561,10 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 style={{
                     backgroundColor: presColorBool ? (isSelected ? 'rgba(250,250,250,0.3)' : 'transparent') : isSelected ? Colors.LIGHT_BLUE : 'transparent',
                     opacity: this._dragging ? 0.3 : 1,
+                    paddingLeft: NumCast(this.layoutDoc._xPadding, this.props.xPadding),
+                    paddingRight: NumCast(this.layoutDoc._xPadding, this.props.xPadding),
+                    paddingTop: NumCast(this.layoutDoc._yPadding, this.props.yPadding),
+                    paddingBottom: NumCast(this.layoutDoc._yPadding, this.props.yPadding),
                 }}
                 onClick={e => {
                     e.stopPropagation();
@@ -507,6 +588,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         ref={this._dragRef}
                         className={`presItem-slide ${isCurrent ? 'active' : ''}`}
                         style={{
+                            display: 'infline-block',
                             backgroundColor: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor),
                             //boxShadow: presBoxColor && presBoxColor !== 'white' && presBoxColor !== 'transparent' ? (isCurrent ? '0 0 0px 1.5px' + presBoxColor : undefined) : undefined,
                             border: presBoxColor && presBoxColor !== 'white' && presBoxColor !== 'transparent' ? (isCurrent ? presBoxColor + ' solid 2.5px' : undefined) : undefined,
@@ -514,8 +596,9 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         <div
                             className="presItem-name"
                             style={{
+                                display: 'inline-flex',
                                 pointerEvents: isSelected ? undefined : 'none',
-                                maxWidth: showMore ? toolbarWidth - 195 : toolbarWidth - 105,
+                                width: `calc(100% ${this.rootDoc.presExpandInlineButton ? '- 50%' : ''} - ${this.presButtons.length * 22}px`,
                                 cursor: isSelected ? 'text' : 'grab',
                             }}>
                             <div>{`${this.indexInPres + 1}.  `}</div>
@@ -523,56 +606,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         </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 captured doc layout</div>}>
-                                <div className="slideButton" onClick={() => this.updateCapturedContainerLayout(targetDoc, activeItem)} style={{ fontWeight: 700, display: activeItem.presPinLayout ? 'flex' : 'none' }}>
-                                    L
-                                </div>
-                            </Tooltip>
-                            <Tooltip title={<div className="dash-tooltip">Update captured doc content</div>}>
-                                <div className="slideButton" onClick={() => this.updateCapturedViewContents(targetDoc, activeItem)} style={{ fontWeight: 700, display: activeItem.presPinData || activeItem.presPinView ? 'flex' : 'none' }}>
-                                    C
-                                </div>
-                            </Tooltip>
-                            {!Doc.noviceMode && (
-                                <Tooltip title={<div className="dash-tooltip">{this.recordingIsInOverlay ? 'Hide Recording' : `${PresElementBox.videoIsRecorded(activeItem) ? 'Show' : 'Start'} recording`}</div>}>
-                                    <div className="slideButton" onClick={e => (this.recordingIsInOverlay ? this.hideRecording(e, true) : this.startRecording(e, activeItem))} style={{ fontWeight: 700 }}>
-                                        <FontAwesomeIcon icon={`video${this.recordingIsInOverlay ? '-slash' : ''}`} onPointerDown={e => e.stopPropagation()} />
-                                    </div>
-                                </Tooltip>
-                            )}
-                            <Tooltip title={<div className="dash-tooltip">{activeItem.groupWithUp ? 'Ungroup' : 'Group with up'}</div>}>
-                                <div
-                                    className="slideButton"
-                                    onClick={() => (activeItem.groupWithUp = !activeItem.groupWithUp)}
-                                    style={{
-                                        display: this.indexInPres === 0 ? 'none' : '',
-                                        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 className="presItem-slideButtons" style={{ position: 'absolute', right: 0 }}>
+                            {...this.presButtons}
                         </div>
                         {this.renderEmbeddedInline}
                     </div>
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 466b43287..fc43325fe 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -238,6 +238,9 @@ export class Doc extends RefField {
         Doc.UserDoc().activePage = val;
         DocServer.UPDATE_SERVER_CACHE();
     }
+    public static IsComicStyle(doc?: Doc) {
+        return doc && Doc.ActiveDashboard && !Doc.IsSystem(doc) && Doc.UserDoc().renderStyle === 'comic';
+    }
     public static get ActiveDashboard() {
         return DocCast(Doc.UserDoc().activeDashboard);
     }
-- 
cgit v1.2.3-70-g09d2

