From 643ea3f46a80b3b288de4fb9bbf775bc22a48c63 Mon Sep 17 00:00:00 2001 From: Anders Rune Jensen Date: Sun, 5 Apr 2020 01:22:50 +0200 Subject: [PATCH 1/9] Basic markdown collaboration --- browser.html | 4 +- css/chat.css | 25 -- css/prose.css | 362 +++++++++++++++++++++ npm-shrinkwrap.json | 761 +++++++++++++++++++++++++++++++++++++++++++- package.json | 15 +- ui/browser.js | 4 +- ui/chat.js | 72 ----- ui/prose.js | 196 ++++++++++++ 8 files changed, 1331 insertions(+), 108 deletions(-) delete mode 100644 css/chat.css create mode 100644 css/prose.css delete mode 100644 ui/chat.js create mode 100644 ui/prose.js diff --git a/browser.html b/browser.html index 377a656..d7c8941 100644 --- a/browser.html +++ b/browser.html @@ -7,7 +7,7 @@ - + @@ -22,7 +22,7 @@

SSB browser demo

Public | Private | Notifications | - Chat | + Collab | Profile | Invites | Settings diff --git a/css/chat.css b/css/chat.css deleted file mode 100644 index 1c00957..0000000 --- a/css/chat.css +++ /dev/null @@ -1,25 +0,0 @@ -#chat > #myId { - padding: 10px -} - -#chat > #acceptConnections { - margin-right: 1rem; -} - -#chat > #tunnelConnect { - padding: 5px; - width: 24rem; - margin-bottom: 12px; - margin-left: 1rem; -} - -#chat > #chatMessage { - padding: 5px; - width: 40rem; -} - -#chat > #chatDescription { - font-size: smaller; - margin-bottom: 10px; - margin-top: -10px; -} diff --git a/css/prose.css b/css/prose.css new file mode 100644 index 0000000..9326896 --- /dev/null +++ b/css/prose.css @@ -0,0 +1,362 @@ +#prose > #myId { + padding: 10px +} + +#prose > #acceptConnections { + margin-right: 1rem; +} + +#prose > #tunnelConnect { + padding: 5px; + width: 25rem; + margin-bottom: 12px; + margin-left: 1rem; +} + +#prose > div > #chatMessage { + padding: 5px; + width: 45rem; +} + +#prose > #description { + font-size: smaller; + margin-bottom: 10px; + margin-top: -10px; +} + +#prose > div > #markdown > textarea { + width: 100%; + height: 10rem; +} + +/* from example */ + +.ProseMirror { + position: relative; +} + +.ProseMirror { + word-wrap: break-word; + white-space: pre-wrap; + -webkit-font-variant-ligatures: none; + font-variant-ligatures: none; +} + +.ProseMirror pre { + white-space: pre-wrap; +} + +.ProseMirror li { + position: relative; +} + +.ProseMirror-hideselection *::selection { background: transparent; } +.ProseMirror-hideselection *::-moz-selection { background: transparent; } +.ProseMirror-hideselection { caret-color: transparent; } + +.ProseMirror-selectednode { + outline: 2px solid #8cf; +} + +/* Make sure li selections wrap around markers */ + +li.ProseMirror-selectednode { + outline: none; +} + +li.ProseMirror-selectednode:after { + content: ""; + position: absolute; + left: -32px; + right: -2px; top: -2px; bottom: -2px; + border: 2px solid #8cf; + pointer-events: none; +} +.ProseMirror-textblock-dropdown { + min-width: 3em; +} + +.ProseMirror-menu { + margin: 0 -4px; + line-height: 1; +} + +.ProseMirror-tooltip .ProseMirror-menu { + width: -webkit-fit-content; + width: fit-content; + white-space: pre; +} + +.ProseMirror-menuitem { + margin-right: 3px; + display: inline-block; +} + +.ProseMirror-menuseparator { + border-right: 1px solid #ddd; + margin-right: 3px; +} + +.ProseMirror-menu-dropdown, .ProseMirror-menu-dropdown-menu { + font-size: 90%; + white-space: nowrap; +} + +.ProseMirror-menu-dropdown { + vertical-align: 1px; + cursor: pointer; + position: relative; + padding-right: 15px; +} + +.ProseMirror-menu-dropdown-wrap { + padding: 1px 0 1px 4px; + display: inline-block; + position: relative; +} + +.ProseMirror-menu-dropdown:after { + content: ""; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid currentColor; + opacity: .6; + position: absolute; + right: 4px; + top: calc(50% - 2px); +} + +.ProseMirror-menu-dropdown-menu, .ProseMirror-menu-submenu { + position: absolute; + background: white; + color: #666; + border: 1px solid #aaa; + padding: 2px; +} + +.ProseMirror-menu-dropdown-menu { + z-index: 15; + min-width: 6em; +} + +.ProseMirror-menu-dropdown-item { + cursor: pointer; + padding: 2px 8px 2px 4px; +} + +.ProseMirror-menu-dropdown-item:hover { + background: #f2f2f2; +} + +.ProseMirror-menu-submenu-wrap { + position: relative; + margin-right: -4px; +} + +.ProseMirror-menu-submenu-label:after { + content: ""; + border-top: 4px solid transparent; + border-bottom: 4px solid transparent; + border-left: 4px solid currentColor; + opacity: .6; + position: absolute; + right: 4px; + top: calc(50% - 4px); +} + +.ProseMirror-menu-submenu { + display: none; + min-width: 4em; + left: 100%; + top: -3px; +} + +.ProseMirror-menu-active { + background: #eee; + border-radius: 4px; +} + +.ProseMirror-menu-active { + background: #eee; + border-radius: 4px; +} + +.ProseMirror-menu-disabled { + opacity: .3; +} + +.ProseMirror-menu-submenu-wrap:hover .ProseMirror-menu-submenu, .ProseMirror-menu-submenu-wrap-active .ProseMirror-menu-submenu { + display: block; +} + +.ProseMirror-menubar { + border-top-left-radius: inherit; + border-top-right-radius: inherit; + position: relative; + min-height: 1em; + color: #666; + padding: 1px 6px; + top: 0; left: 0; right: 0; + border-bottom: 1px solid silver; + background: white; + z-index: 10; + -moz-box-sizing: border-box; + box-sizing: border-box; + overflow: visible; +} + +.ProseMirror-icon { + display: inline-block; + line-height: .8; + vertical-align: -2px; /* Compensate for padding */ + padding: 2px 8px; + cursor: pointer; +} + +.ProseMirror-menu-disabled.ProseMirror-icon { + cursor: default; +} + +.ProseMirror-icon svg { + fill: currentColor; + height: 1em; +} + +.ProseMirror-icon span { + vertical-align: text-top; +} +.ProseMirror-gapcursor { + display: none; + pointer-events: none; + position: absolute; +} + +.ProseMirror-gapcursor:after { + content: ""; + display: block; + position: absolute; + top: -2px; + width: 20px; + border-top: 1px solid black; + animation: ProseMirror-cursor-blink 1.1s steps(2, start) infinite; +} + +@keyframes ProseMirror-cursor-blink { + to { + visibility: hidden; + } +} + +.ProseMirror-focused .ProseMirror-gapcursor { + display: block; +} +/* Add space around the hr to make clicking it easier */ + +.ProseMirror-example-setup-style hr { + padding: 2px 10px; + border: none; + margin: 1em 0; +} + +.ProseMirror-example-setup-style hr:after { + content: ""; + display: block; + height: 1px; + background-color: silver; + line-height: 2px; +} + +.ProseMirror ul, .ProseMirror ol { + padding-left: 30px; +} + +.ProseMirror blockquote { + padding-left: 1em; + border-left: 3px solid #eee; + margin-left: 0; margin-right: 0; +} + +.ProseMirror-example-setup-style img { + cursor: default; +} + +.ProseMirror-prompt { + background: white; + padding: 5px 10px 5px 15px; + border: 1px solid silver; + position: fixed; + border-radius: 3px; + z-index: 11; + box-shadow: -.5px 2px 5px rgba(0, 0, 0, .2); +} + +.ProseMirror-prompt h5 { + margin: 0; + font-weight: normal; + font-size: 100%; + color: #444; +} + +.ProseMirror-prompt input[type="text"], +.ProseMirror-prompt textarea { + background: #eee; + border: none; + outline: none; +} + +.ProseMirror-prompt input[type="text"] { + padding: 0 4px; +} + +.ProseMirror-prompt-close { + position: absolute; + left: 2px; top: 1px; + color: #666; + border: none; background: transparent; padding: 0; +} + +.ProseMirror-prompt-close:after { + content: "✕"; + font-size: 12px; +} + +.ProseMirror-invalid { + background: #ffc; + border: 1px solid #cc7; + border-radius: 4px; + padding: 5px 10px; + position: absolute; + min-width: 10em; +} + +.ProseMirror-prompt-buttons { + margin-top: 5px; + display: none; +} +#editor, .editor { + background: white; + color: black; + background-clip: padding-box; + border-radius: 4px; + border: 2px solid rgba(0, 0, 0, 0.2); + padding: 5px 0; + margin-bottom: 23px; +} + +.ProseMirror p:first-child, +.ProseMirror h1:first-child, +.ProseMirror h2:first-child, +.ProseMirror h3:first-child, +.ProseMirror h4:first-child, +.ProseMirror h5:first-child, +.ProseMirror h6:first-child { + margin-top: 10px; +} + +.ProseMirror { + padding: 4px 8px 4px 14px; + line-height: 1.2; + outline: none; +} + +.ProseMirror p { margin-bottom: 1em } diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index a33c836..db23db9 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -4,6 +4,270 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/core": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", + "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.9.0", + "@babel/helper-module-transforms": "^7.9.0", + "@babel/helpers": "^7.9.0", + "@babel/parser": "^7.9.0", + "@babel/template": "^7.8.6", + "@babel/traverse": "^7.9.0", + "@babel/types": "^7.9.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.4.tgz", + "integrity": "sha512-rjP8ahaDy/ouhrvCoU1E5mqaitWrxwuNGU+dy1EpaoK48jZay4MdkskKGIMHLZNewg8sAsqpGSREJwP0zH3YQA==", + "dev": true, + "requires": { + "@babel/types": "^7.9.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", + "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-module-imports": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz", + "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-module-transforms": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz", + "integrity": "sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.6", + "@babel/helper-simple-access": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/template": "^7.8.6", + "@babel/types": "^7.9.0", + "lodash": "^4.17.13" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", + "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + }, + "@babel/helper-replace-supers": { + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz", + "integrity": "sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/traverse": "^7.8.6", + "@babel/types": "^7.8.6" + } + }, + "@babel/helper-simple-access": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz", + "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==", + "dev": true, + "requires": { + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz", + "integrity": "sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.2.tgz", + "integrity": "sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==", + "dev": true, + "requires": { + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.9.0", + "@babel/types": "^7.9.0" + } + }, + "@babel/highlight": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", + "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.9.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", + "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==", + "dev": true + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz", + "integrity": "sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.9.0", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-simple-access": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, "@babel/runtime": { "version": "7.6.2", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.2.tgz", @@ -12,6 +276,45 @@ "regenerator-runtime": "^0.13.2" } }, + "@babel/template": { + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", + "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.6", + "@babel/types": "^7.8.6" + } + }, + "@babel/traverse": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.0.tgz", + "integrity": "sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.9.0", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.9.0", + "@babel/types": "^7.9.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.0.tgz", + "integrity": "sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.9.0", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, "@goto-bus-stop/common-shake": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@goto-bus-stop/common-shake/-/common-shake-2.3.0.tgz", @@ -207,6 +510,12 @@ } } }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "optional": true + }, "async-single": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/async-single/-/async-single-1.0.5.tgz", @@ -221,6 +530,25 @@ "idb-kv-store": "^4.4.0" } }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + } + } + }, "babel-extract-comments": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/babel-extract-comments/-/babel-extract-comments-1.0.0.tgz", @@ -229,6 +557,33 @@ "babylon": "^6.18.0" } }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", + "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-import-to-require": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-import-to-require/-/babel-plugin-import-to-require-1.0.0.tgz", + "integrity": "sha512-dc843CwrFivjO8AVgxcHvxl0cb7J7Ed8ZGFP8+PjH3X1CnyzYtAU1WL1349m9Wc/+oqk4ETx2+cIEO2jlp3XyQ==", + "dev": true, + "requires": { + "babel-template": "^6.26.0" + } + }, "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", @@ -259,6 +614,79 @@ } } }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + }, + "dependencies": { + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + } + } + }, "babylon": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", @@ -595,6 +1023,21 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, "combine-source-map": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", @@ -812,6 +1255,11 @@ } } }, + "crelt": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.4.tgz", + "integrity": "sha512-l1cwMUOssGLEj5zgbut4lxJq95ZabOXVZnDybNqQRUtXh1lvUK7e7kJNm8SfvTQzYpE3AVJhIVUJKf382lMA7A==" + }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -1269,6 +1717,24 @@ "estraverse": "^4.1.1" } }, + "esmify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/esmify/-/esmify-2.1.1.tgz", + "integrity": "sha512-GyOVgjG7sNyYB5Mbo15Ll4aGrcXZzZ3LI22rbLOjCI7L/wYelzQpBHRZkZkqbPNZ/QIRilcaHqzgNCLcEsi1lQ==", + "dev": true, + "requires": { + "@babel/core": "^7.2.2", + "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.2.0", + "babel-plugin-import-to-require": "^1.0.0", + "cached-path-relative": "^1.0.2", + "concat-stream": "^1.6.2", + "duplexer2": "^0.1.4", + "through2": "^2.0.5" + } + }, "esprima": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", @@ -1486,6 +1952,12 @@ "is-property": "^1.0.0" } }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "dev": true + }, "get-assigned-identifiers": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", @@ -1509,6 +1981,12 @@ "path-is-absolute": "^1.0.0" } }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, "gossip-query": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/gossip-query/-/gossip-query-2.0.2.tgz", @@ -1540,6 +2018,12 @@ "ansi-regex": "^2.0.0" } }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", @@ -1698,6 +2182,15 @@ } } }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, "ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", @@ -1802,6 +2295,23 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "isomorphic.js": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.1.3.tgz", + "integrity": "sha512-pabBRLDwYefSsNS+qCazJ97o7P5xDTrNoxSYFTM09JlZTxPrOEPGKekwqUy3/Np4C4PHnVUXHYsZPOix0jELsA==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, "json-buffer": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-2.0.11.tgz", @@ -1816,6 +2326,23 @@ "jsonify": "~0.0.0" } }, + "json5": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.2.tgz", + "integrity": "sha512-MoUOQ4WdiN3yxhm7NEVJSJrieAo5hNSLQ5sj05OTRHPL9HOBy8u4Bu88jsC1jvqAdN+E1bJmsUcZH+1HQxliqQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + } + } + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -2021,6 +2548,14 @@ "type-check": "~0.3.2" } }, + "lib0": { + "version": "0.2.22", + "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.22.tgz", + "integrity": "sha512-SFzX7/SGgrOK6VABQugczhAwaaZLW1VcrE9xG+cVG1+AMQWmcu/7SZaJq0KORnfHr1xK4P6JUBWfoxSCwBcgLA==", + "requires": { + "isomorphic.js": "^0.1.3" + } + }, "libnested": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/libnested/-/libnested-1.5.0.tgz", @@ -2047,6 +2582,12 @@ "uc.micro": "^1.0.1" } }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, "lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", @@ -2100,6 +2641,15 @@ "resolved": "https://registry.npmjs.org/looper/-/looper-4.0.0.tgz", "integrity": "sha1-dwat7VmpntygbmtUu4bI7BnJUVU=" }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, "lossy-store": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lossy-store/-/lossy-store-1.2.4.tgz", @@ -2498,6 +3048,11 @@ "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" }, + "orderedmap": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-1.1.1.tgz", + "integrity": "sha512-3Ux8um0zXbVacKUkcytc0u3HgC0b0bBLT+I60r2J/En72cI0nZffqrA7Xtf2Hqs27j1g82llR5Mhbd0Z1XW4AQ==" + }, "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -2651,6 +3206,145 @@ "resolved": "https://registry.npmjs.org/promisize/-/promisize-1.1.2.tgz", "integrity": "sha1-m0fiyyrkl+seutwsQZHWTRXJSdE=" }, + "prosemirror-commands": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.1.3.tgz", + "integrity": "sha512-YVbKwTR4likoyhuwIUC9egbzHvnFrFUNbiesB0DB/HZ8hBcopQ42Tb4KGlYrS3n+pNDTFObN73CLFY6mYLN2IQ==", + "requires": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "prosemirror-dropcursor": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.3.2.tgz", + "integrity": "sha512-4c94OUGyobGnwcQI70OXyMhE/9T4aTgjU+CHxkd5c7D+jH/J0mKM/lk+jneFVKt7+E4/M0D9HzRPifu8U28Thw==", + "requires": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0", + "prosemirror-view": "^1.1.0" + } + }, + "prosemirror-example-setup": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prosemirror-example-setup/-/prosemirror-example-setup-1.1.2.tgz", + "integrity": "sha512-MTpIMyqk08jFnzxeRMCinCEMtVSTUtxKgQBGxfCbVe9C6zIOqp9qZZJz5Ojaad1GETySyuj8+OIHHvQsIaaaGQ==", + "requires": { + "prosemirror-commands": "^1.0.0", + "prosemirror-dropcursor": "^1.0.0", + "prosemirror-gapcursor": "^1.0.0", + "prosemirror-history": "^1.0.0", + "prosemirror-inputrules": "^1.0.0", + "prosemirror-keymap": "^1.0.0", + "prosemirror-menu": "^1.0.0", + "prosemirror-schema-list": "^1.0.0", + "prosemirror-state": "^1.0.0" + } + }, + "prosemirror-gapcursor": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.1.4.tgz", + "integrity": "sha512-6WJRDcd5jeKDZfzM6nD8aLtA9y54aPgUzVD0rudNrirq8qWgugiN29BfvIVdiDzV0Q+/cwr2yNs5/ssSAvZ0Kw==", + "requires": { + "prosemirror-keymap": "^1.0.0", + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-view": "^1.0.0" + } + }, + "prosemirror-history": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.1.3.tgz", + "integrity": "sha512-zGDotijea+vnfnyyUGyiy1wfOQhf0B/b6zYcCouBV8yo6JmrE9X23M5q7Nf/nATywEZbgRLG70R4DmfSTC+gfg==", + "requires": { + "prosemirror-state": "^1.2.2", + "prosemirror-transform": "^1.0.0", + "rope-sequence": "^1.3.0" + } + }, + "prosemirror-inputrules": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.1.2.tgz", + "integrity": "sha512-Ja5Z3BWestlHYGvtSGqyvxMeB8QEuBjlHM8YnKtLGUXMDp965qdDV4goV8lJb17kIWHk7e7JNj6Catuoa3302g==", + "requires": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "prosemirror-keymap": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.1.3.tgz", + "integrity": "sha512-PRA4NzkUMzV/NFf5pyQ6tmlIHiW/qjQ1kGWUlV2rF/dvlOxtpGpTEjIMhWgLuMf+HiDEFnUEP7uhYXu+t+491g==", + "requires": { + "prosemirror-state": "^1.0.0", + "w3c-keyname": "^2.2.0" + } + }, + "prosemirror-markdown": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.4.4.tgz", + "integrity": "sha512-qh6d9WKjahLSlV4V7PZNJifp+fLKrOFV/ZqajQ15Labqh49Zs/TGGk10SkT6n+ROTNIHHU/P5oBi5ei7BvwmuA==", + "requires": { + "markdown-it": "^10.0.0", + "prosemirror-model": "^1.0.0" + } + }, + "prosemirror-menu": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.1.4.tgz", + "integrity": "sha512-2ROsji/X9ciDnVSRvSTqFygI34GEdHfQSsK4zBKjPxSEroeiHHcdRMS1ofNIf2zM0Vpp5/YqfpxynElymQkqzg==", + "requires": { + "crelt": "^1.0.0", + "prosemirror-commands": "^1.0.0", + "prosemirror-history": "^1.0.0", + "prosemirror-state": "^1.0.0" + } + }, + "prosemirror-model": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.9.1.tgz", + "integrity": "sha512-Qblh8pm1c7Ll64sYLauwwzjimo/tFg1zW3Q3IWhKRhvfOEgRKqa6dC5pRrAa+XHOIjBFEYrqbi52J5bqA2dV8Q==", + "requires": { + "orderedmap": "^1.1.0" + } + }, + "prosemirror-schema-list": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.1.2.tgz", + "integrity": "sha512-dgM9PwtM4twa5WsgSYMB+J8bwjnR43DAD3L9MsR9rKm/nZR5Y85xcjB7gusVMSsbQ2NomMZF03RE6No6mTnclQ==", + "requires": { + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "prosemirror-state": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.3.3.tgz", + "integrity": "sha512-PLXh2VJsIgvlgSTH6I2Yg6vk1CzPDp21DFreVpQtDMY2S6WaMmrQgDTLRcsrD8X38v8Yc873H7+ogdGzyIPn+w==", + "requires": { + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "prosemirror-transform": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.2.4.tgz", + "integrity": "sha512-0A668uf0EN89L9O9brE05kHcqp7FHmT5YN7Tom58Kj926QqOBs7iNRHDLWxrSaQB5MNZtzDOD9T3EyJ88YDcBg==", + "requires": { + "prosemirror-model": "^1.0.0" + } + }, + "prosemirror-view": { + "version": "1.14.6", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.14.6.tgz", + "integrity": "sha512-0qNSFWVBHPrdQaZtIO3aou/NRsxMGER3IuI3cePHYbk5pf9wSsbMIWWaeHtXqblL+rqtgkLfcw0D2na6+WBgpA==", + "requires": { + "prosemirror-model": "^1.1.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0" + } + }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -3171,6 +3865,11 @@ "resolved": "https://registry.npmjs.org/rng/-/rng-0.2.2.tgz", "integrity": "sha1-30PoDZvIKtRDC8/vA/SccX6LLow=" }, + "rope-sequence": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.2.tgz", + "integrity": "sha512-ku6MFrwEVSVmXLvy3dYph3LAMNS0890K7fabn+0YIRQ2T96T9F4gkFf0vf0WW0JUraNWwGRtInEpH7yO4tbQZg==" + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -4080,6 +4779,12 @@ "to-space-case": "^1.0.0" } }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, "to-no-case": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz", @@ -4299,9 +5004,14 @@ "integrity": "sha512-GYhn2ynaZlysZMkFE5oCHRUTqE8BWs/a9YbKpNLi0i7xD6KG1EzDqpHQmv1F5gXjr8kL5iIVS8EOtRaVUEXTqA==" }, "vue-select": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/vue-select/-/vue-select-3.4.0.tgz", - "integrity": "sha512-UHd0fiUjPgRmHIGhI6yUKtnJsHOdvzD00QUGUtD+FaxWWZRWF2AAb7KPZRj0j/egVfZQvey6M6woHn78GbTogA==" + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/vue-select/-/vue-select-3.9.5.tgz", + "integrity": "sha512-r392oaLYepNxY+uY1EN7r05VPOqSWGEfZ3LtJ3NqhrRbWCpWQ5EPSMN3QL80HdN3H+o1ueQA9P58K1vgGZ5P3Q==" + }, + "w3c-keyname": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz", + "integrity": "sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw==" }, "word-wrap": { "version": "1.2.3", @@ -4471,6 +5181,51 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y-prosemirror": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/y-prosemirror/-/y-prosemirror-0.3.3.tgz", + "integrity": "sha512-+vgwV+Up90rIEhwfxiHCoB7arChUuNaS+O0cUDpVhObJ1BNkVoEGYRu/c6BQC8S+Wpsl9AnAGnKKsyCxaatQfQ==", + "requires": { + "lib0": "^0.2.15" + } + }, + "y-protocols": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-0.2.3.tgz", + "integrity": "sha512-mJ838iW7XgMQqlv+9DtH7QyLqflZoy/VvaUWRIpwawee4mQiFJcEXazCmSYUHEbXIUuVNNc70FnuNSMWDC5vKQ==", + "requires": { + "lib0": "^0.2.20" + } + }, + "y-websocket": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/y-websocket/-/y-websocket-1.2.5.tgz", + "integrity": "sha512-Q8dcUrP7tZvfODPP/6cZ90lE+U3ucAUIBfPHwLtUov2WynDAqm/fc9fiARd5URYRk55m+edNkAhmwhkFNhbhFQ==", + "requires": { + "lib0": "^0.2.22", + "ws": "^6.2.1", + "y-protocols": "^0.2.3" + }, + "dependencies": { + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "optional": true, + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "yjs": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.0.5.tgz", + "integrity": "sha512-xBqT+iFmRKkhxYXCa+8sgxISugEfi3toQnEcT2ahgC4uEmSekKuUb2nvqJyFLWXzL4CmZ6My7HgWcnRIRDkIhA==", + "requires": { + "lib0": "^0.2.22" + } } } } diff --git a/package.json b/package.json index f070a63..ee84680 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,10 @@ "human-time": "0.0.2", "lodash.throttle": "^4.1.1", "node-emoji": "^1.10.0", + "prosemirror-example-setup": "^1.1.2", + "prosemirror-markdown": "^1.4.4", + "prosemirror-state": "^1.3.3", + "prosemirror-view": "^1.14.6", "pull-abortable": "^4.1.1", "pull-stream": "^3.6.14", "rimraf": "^3.0.0", @@ -22,19 +26,22 @@ "ssb-ref": "^2.13.3", "vue": "^2.6.11", "vue-router": "^3.1.6", - "vue-select": "^3.4.0", - "workbox-build": "^4.3.1" + "vue-select": "^3.9.5", + "workbox-build": "^4.3.1", + "y-prosemirror": "^0.3.3", + "yjs": "^13.0.5" }, "devDependencies": { "browserify": "^16.5.1", "common-shakeify": "^0.6.2", "deep-object-diff": "^1.1.0", + "esmify": "^2.1.1", "ssb-client": "^4.7.9", "uglifyify": "^5.0.2" }, "scripts": { - "build": "mkdir -p build && browserify --full-paths ui/browser.js > build/bundle-ui.js && node write-dist.js", - "release": "mkdir -p build && browserify -g uglifyify -p common-shakeify ui/browser.js > build/bundle-ui.js && node write-dist.js" + "build": "mkdir -p build && browserify -p esmify --full-paths ui/browser.js > build/bundle-ui.js && node write-dist.js", + "release": "mkdir -p build && browserify -g uglifyify -p esmify -p common-shakeify ui/browser.js > build/bundle-ui.js && node write-dist.js" }, "author": "arj", "license": "beerware" diff --git a/ui/browser.js b/ui/browser.js index fef7afb..fd99dec 100644 --- a/ui/browser.js +++ b/ui/browser.js @@ -14,7 +14,7 @@ const Channel = require('./channel')() const Thread = require('./thread')() const Private = require('./private')(componentsState) - const Chat = require('./chat')() + const Prose = require('./prose')() const Invites = require('./invites')() const Settings = require('./settings')() @@ -36,7 +36,7 @@ { name: 'profile', path: '/profile/:feedId', component: Profile, props: true }, { name: 'notifications', path: '/notifications', component: Notifications }, { path: '/private', component: Private }, - { path: '/chat', component: Chat }, + { path: '/collab', component: Prose }, { path: '/invites', component: Invites }, { path: '/settings', component: Settings }, { path: '/', redirect: 'public' }, diff --git a/ui/chat.js b/ui/chat.js deleted file mode 100644 index 9d2b7c4..0000000 --- a/ui/chat.js +++ /dev/null @@ -1,72 +0,0 @@ -const pull = require('pull-stream') -const pullAbort = require('pull-abortable') - -module.exports = function () { - var abortablePullStream = null - - return { - template: `
-
Your id: {{ SSB.net.id }}
- or - - -

Off-chain messages

-
Off-chain messages are messages sent - encrypted between you and the other end through the magic of - tunnels. These messages are ephemeral and will be gone forever - when you change view!
-
-
`, - - data: function() { - return { - remoteId: "", - chatText: "" - } - }, - - methods: { - acceptMessages: function() { - SSB.net.tunnelMessage.acceptMessages((remoteId) => { - return confirm("Allow connection from: " + remoteId + "?") - }) - }, - - connect: function() { - SSB.net.tunnelMessage.connect(this.remoteId) - }, - - onChatSend: function() { - SSB.net.tunnelMessage.sendMessage("chat", this.chatText) - this.chatText = '' - } - }, - - created: function() { - abortablePullStream = pullAbort() - pull( - SSB.net.tunnelMessage.messages(), - abortablePullStream, - pull.drain((msg) => { - var user = msg.user - if (msg.type == "chat") - user = user.substr(0, 10) - - if (SSB.profiles[msg.user]) - user = SSB.profiles[msg.user].name - else if (msg.user == SSB.net.id) - user = "me" - document.getElementById("messages").innerHTML += `${user}> ${msg.data}
` - }) - ) - }, - - beforeRouteLeave: function(from, to, next) { - if (abortablePullStream != null) { - abortablePullStream.abort() - abortablePullStream = null - } - next() - } - } -} diff --git a/ui/prose.js b/ui/prose.js new file mode 100644 index 0000000..d7d739a --- /dev/null +++ b/ui/prose.js @@ -0,0 +1,196 @@ +const pull = require('pull-stream') +const pullAbort = require('pull-abortable') + +const Y = require('yjs') +const { ySyncPlugin, yUndoPlugin, undo, redo } = require('y-prosemirror') +const { EditorState } = require('prosemirror-state') +const { EditorView } = require('prosemirror-view') +const { schema, defaultMarkdownParser, defaultMarkdownSerializer } = require('prosemirror-markdown') +const { exampleSetup, buildMenuItems } = require('prosemirror-example-setup') +const { keymap } = require('prosemirror-keymap') + +module.exports = function () { + var abortablePullStream = null + const ydoc = new Y.Doc() + var connected = 0 + + function uint8ArrayToStrBase64(a) { + return btoa(String.fromCharCode.apply(null, a)) + } + + function strBase64ToUint8Array(s) { + return Uint8Array.from([].map.call(atob(s), c => c.charCodeAt(0))) + } + + function createProseMirrorView(content) { + const type = ydoc.getXmlFragment('prosemirror') + const editor = document.getElementById('editor') + + const mi = buildMenuItems(schema) + + return new EditorView(editor, { + state: EditorState.create({ + doc: defaultMarkdownParser.parse(content), + schema, + plugins: [ + ySyncPlugin(type), + yUndoPlugin(), + keymap({ + 'Mod-z': undo, + 'Mod-y': redo, + 'Mod-Shift-z': redo + }) + ].concat(exampleSetup({ + schema, + menuContent: [ + [mi.toggleStrong, mi.toggleEm, mi.makeHead1, mi.makeHead2, + mi.wrapBulletList, mi.wrapOrderedList, mi.wrapBlockQuote] + ] + })) + }) + }) + } + + return { + template: ` +
+
Your id: {{ SSB.net.id }}
+ or + + +

Shared document

+ +
+ The state of the shared document is synchronized using + off-chain messages sent encrypted between you and the + other end through the magic of tunnels and CRDTs. +
+ +
+
+ +
+
+ +
+ +
+
+ +
+ +

Messages

+ +
+ +
+
+
`, + + data: function() { + return { + remoteId: "", + documentText: "", + chatText: "", + isMarkdown: false, + proseMirrorView: undefined + } + }, + + methods: { + onViewChange: function() { + var self = this + if (!self.isMarkdown) + { + self.documentText = defaultMarkdownSerializer.serialize(self.proseMirrorView.state.doc) + self.proseMirrorView.destroy() + self.isMarkdown = !self.isMarkdown + } + else + { + self.isMarkdown = !self.isMarkdown + self.$nextTick(() => self.proseMirrorView = createProseMirrorView(self.documentText)) + } + }, + + acceptMessages: function() { + SSB.net.tunnelMessage.acceptMessages((remoteId) => { + return confirm("Allow connection from: " + remoteId + "?") + }) + }, + + connect: function() { + SSB.net.tunnelMessage.connect(this.remoteId) + }, + + onChatSend: function() { + SSB.net.tunnelMessage.sendMessage("chat", this.chatText) + this.chatText = '' + } + }, + + created: function() { + abortablePullStream = pullAbort() + pull( + SSB.net.tunnelMessage.messages(), + abortablePullStream, + pull.drain((msg) => { + var user = msg.user + if (msg.type == "chat") + user = user.substr(0, 10) + + if (SSB.profiles[msg.user]) + user = SSB.profiles[msg.user].name + else if (msg.user == SSB.net.id) + user = "me" + + if (msg.type == 'info' && msg.data == "connected") { + connected++ + document.getElementById("status").innerHTML += `${user} connected
` + + // FIXME: maybe save their state and only send them updates based on that + const state = uint8ArrayToStrBase64(Y.encodeStateAsUpdate(ydoc)) + SSB.net.tunnelMessage.sendMessage("prose-current-state", state) + } + else if (msg.type == 'info' && msg.data == "disconnected") { + connected-- + document.getElementById("status").innerHTML += `${user} disconnected
` + } + else if (msg.type == 'info' && msg.date == "waiting for accept") { + document.getElementById("status").innerHTML += `waiting for ${user} accept
` + } + else if (user != "me" && (msg.type == "prose-current-state" || msg.type == "prose-state-update")) + { + Y.applyUpdate(ydoc, strBase64ToUint8Array(msg.data)) + } + else if (msg.type == 'chat') { + document.getElementById("status").innerHTML += `${user}> ${msg.data}
` + } + else + console.log("got unknown msg", msg) + }) + ) + }, + + mounted: function() { + ydoc.on('update', update => { + if (connected > 0) { + const state = uint8ArrayToStrBase64(update) + SSB.net.tunnelMessage.sendMessage("prose-state-update", state) + } + }) + + this.proseMirrorView = createProseMirrorView("") + }, + + beforeRouteLeave: function(from, to, next) { + if (abortablePullStream != null) { + abortablePullStream.abort() + abortablePullStream = null + } + next() + } + } +} From ef287d8f23e3ad6fdbd6d5214454f8f7f7a8c0b5 Mon Sep 17 00:00:00 2001 From: Anders Rune Jensen Date: Sun, 5 Apr 2020 02:18:42 +0200 Subject: [PATCH 2/9] Remove the markdown raw format, was not working with ydoc changes --- ui/prose.js | 39 +++++++++------------------------------ 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/ui/prose.js b/ui/prose.js index d7d739a..f895107 100644 --- a/ui/prose.js +++ b/ui/prose.js @@ -27,7 +27,7 @@ module.exports = function () { const editor = document.getElementById('editor') const mi = buildMenuItems(schema) - + return new EditorView(editor, { state: EditorState.create({ doc: defaultMarkdownParser.parse(content), @@ -43,8 +43,9 @@ module.exports = function () { ].concat(exampleSetup({ schema, menuContent: [ - [mi.toggleStrong, mi.toggleEm, mi.makeHead1, mi.makeHead2, - mi.wrapBulletList, mi.wrapOrderedList, mi.wrapBlockQuote] + [mi.toggleStrong, mi.toggleEm], + [mi.makeHead1, mi.makeHead2], + [mi.wrapBulletList, mi.wrapOrderedList, mi.wrapBlockQuote] ] })) }) @@ -67,16 +68,7 @@ module.exports = function () {
-
- -
-
- -
- -
+

@@ -94,27 +86,11 @@ module.exports = function () { remoteId: "", documentText: "", chatText: "", - isMarkdown: false, - proseMirrorView: undefined + proseMirrorView: null } }, methods: { - onViewChange: function() { - var self = this - if (!self.isMarkdown) - { - self.documentText = defaultMarkdownSerializer.serialize(self.proseMirrorView.state.doc) - self.proseMirrorView.destroy() - self.isMarkdown = !self.isMarkdown - } - else - { - self.isMarkdown = !self.isMarkdown - self.$nextTick(() => self.proseMirrorView = createProseMirrorView(self.documentText)) - } - }, - acceptMessages: function() { SSB.net.tunnelMessage.acceptMessages((remoteId) => { return confirm("Allow connection from: " + remoteId + "?") @@ -183,6 +159,9 @@ module.exports = function () { }) this.proseMirrorView = createProseMirrorView("") + + // for exporting: + // defaultMarkdownSerializer.serialize(this.proseMirrorView.state.doc) }, beforeRouteLeave: function(from, to, next) { From 88224f10f2c9a583816c913727833b1617e0ad70 Mon Sep 17 00:00:00 2001 From: Anders Rune Jensen Date: Sun, 5 Apr 2020 13:21:42 +0200 Subject: [PATCH 3/9] Add export as markdown button --- ui/prose.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ui/prose.js b/ui/prose.js index f895107..5cbc1d9 100644 --- a/ui/prose.js +++ b/ui/prose.js @@ -69,6 +69,7 @@ module.exports = function () {
+

@@ -104,6 +105,12 @@ module.exports = function () { onChatSend: function() { SSB.net.tunnelMessage.sendMessage("chat", this.chatText) this.chatText = '' + }, + + exportMarkdown: function() { + const md = defaultMarkdownSerializer.serialize(this.proseMirrorView.state.doc) + navigator.clipboard.writeText(md) + alert("Exported markdown text to clipboard") } }, @@ -159,9 +166,6 @@ module.exports = function () { }) this.proseMirrorView = createProseMirrorView("") - - // for exporting: - // defaultMarkdownSerializer.serialize(this.proseMirrorView.state.doc) }, beforeRouteLeave: function(from, to, next) { From 272c5d00233e58428da861389fae7954f519b72f Mon Sep 17 00:00:00 2001 From: Anders Rune Jensen Date: Mon, 6 Apr 2020 10:03:17 +0200 Subject: [PATCH 4/9] Fix race condition on load --- ui/browser.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ui/browser.js b/ui/browser.js index fd99dec..7b9a50e 100644 --- a/ui/browser.js +++ b/ui/browser.js @@ -7,7 +7,8 @@ }) } - SSB.events.on('SSB: loaded', function() { + function ssbLoaded() { + console.log("ssb loaded") const Public = require('./public')(componentsState) const Profile = require('./profile')() const Notifications = require('./notifications')() @@ -68,5 +69,10 @@ } }).$mount('#app') - }) + } + + if (SSB.events._events["SSB: loaded"]) + ssbLoaded() + else + SSB.events.once('SSB: loaded', ssbLoaded) })() From d006ddd314d2956a035b685b15528f1e19f57191 Mon Sep 17 00:00:00 2001 From: Anders Rune Jensen Date: Mon, 6 Apr 2020 22:07:18 +0200 Subject: [PATCH 5/9] Allow disconnect & minor tweaks --- css/prose.css | 3 ++- ui/connected.js | 6 +++--- ui/prose.js | 26 ++++++++++++++++++++------ 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/css/prose.css b/css/prose.css index 9326896..cfe118d 100644 --- a/css/prose.css +++ b/css/prose.css @@ -8,9 +8,10 @@ #prose > #tunnelConnect { padding: 5px; - width: 25rem; + width: 19rem; margin-bottom: 12px; margin-left: 1rem; + margin-right: 1rem; } #prose > div > #chatMessage { diff --git a/ui/connected.js b/ui/connected.js index 75e5ad1..128e912 100644 --- a/ui/connected.js +++ b/ui/connected.js @@ -1,8 +1,8 @@ Vue.component('connected', { template: ` - - 🦄 - `, + + 🦄 + `, data: function() { return { diff --git a/ui/prose.js b/ui/prose.js index 5cbc1d9..85ba5d6 100644 --- a/ui/prose.js +++ b/ui/prose.js @@ -56,8 +56,8 @@ module.exports = function () { template: `
Your id: {{ SSB.net.id }}
- or - + or +

Shared document

@@ -84,6 +84,7 @@ module.exports = function () { data: function() { return { + connectText: "Connect to host", remoteId: "", documentText: "", chatText: "", @@ -98,8 +99,14 @@ module.exports = function () { }) }, - connect: function() { - SSB.net.tunnelMessage.connect(this.remoteId) + connectDisconnect: function() { + if (this.connectText == "Connect to host") { + SSB.net.tunnelMessage.connect(this.remoteId) + this.connectText = "Disconnect from host" + } else { + SSB.net.tunnelMessage.disconnect() + this.connectText = "Connect to host" + } }, onChatSend: function() { @@ -135,19 +142,26 @@ module.exports = function () { // FIXME: maybe save their state and only send them updates based on that const state = uint8ArrayToStrBase64(Y.encodeStateAsUpdate(ydoc)) + //console.log("sending initial state", state) SSB.net.tunnelMessage.sendMessage("prose-current-state", state) } else if (msg.type == 'info' && msg.data == "disconnected") { connected-- document.getElementById("status").innerHTML += `${user} disconnected
` } - else if (msg.type == 'info' && msg.date == "waiting for accept") { - document.getElementById("status").innerHTML += `waiting for ${user} accept
` + else if (msg.type == 'info' && msg.data == "waiting for accept") { + document.getElementById("status").innerHTML += `waiting for ${user} to accept
` } else if (user != "me" && (msg.type == "prose-current-state" || msg.type == "prose-state-update")) { + //console.log("got update", user) + //console.log("got update msg", msg.data) Y.applyUpdate(ydoc, strBase64ToUint8Array(msg.data)) } + else if (user == "me" && (msg.type == "prose-current-state" || msg.type == "prose-state-update")) + { + // skip own state updates + } else if (msg.type == 'chat') { document.getElementById("status").innerHTML += `${user}> ${msg.data}
` } From 0da0f20a92d04f597ca9cae5d4adf4176b34f4fc Mon Sep 17 00:00:00 2001 From: Anders Rune Jensen Date: Mon, 6 Apr 2020 23:42:16 +0200 Subject: [PATCH 6/9] Minor state fix --- ui/prose.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/prose.js b/ui/prose.js index 85ba5d6..d76b50e 100644 --- a/ui/prose.js +++ b/ui/prose.js @@ -148,6 +148,7 @@ module.exports = function () { else if (msg.type == 'info' && msg.data == "disconnected") { connected-- document.getElementById("status").innerHTML += `${user} disconnected
` + this.connectText = "Connect to host" } else if (msg.type == 'info' && msg.data == "waiting for accept") { document.getElementById("status").innerHTML += `waiting for ${user} to accept
` From 4316b9ad16e4ebb1123b5138c457e7b9c7008311 Mon Sep 17 00:00:00 2001 From: Anders Rune Jensen Date: Tue, 7 Apr 2020 09:38:01 +0200 Subject: [PATCH 7/9] Fix race conditions in sending state on connect --- ui/prose.js | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/ui/prose.js b/ui/prose.js index d76b50e..08f148f 100644 --- a/ui/prose.js +++ b/ui/prose.js @@ -51,7 +51,25 @@ module.exports = function () { }) }) } + + function sendInitialState() { + // FIXME: maybe save their state and only send them updates based on that + const state = uint8ArrayToStrBase64(Y.encodeStateAsUpdate(ydoc)) + //console.log("sending initial state", state) + SSB.net.tunnelMessage.sendMessage("prose-current-state", state) + } + function sendInitialStateOnConnect() { + SSB.net.once('rpc:connect', function (rpc, isClient) { + if (rpc.id == '@' + SSB.remoteAddress.split(':')[3]) { + sendInitialStateOnConnect() // a tunnel is multiple connects + return + } + + sendInitialState() + }) + } + return { template: `
@@ -95,13 +113,14 @@ module.exports = function () { methods: { acceptMessages: function() { SSB.net.tunnelMessage.acceptMessages((remoteId) => { + sendInitialStateOnConnect() return confirm("Allow connection from: " + remoteId + "?") }) }, connectDisconnect: function() { if (this.connectText == "Connect to host") { - SSB.net.tunnelMessage.connect(this.remoteId) + SSB.net.tunnelMessage.connect(this.remoteId, sendInitialState) this.connectText = "Disconnect from host" } else { SSB.net.tunnelMessage.disconnect() @@ -139,11 +158,6 @@ module.exports = function () { if (msg.type == 'info' && msg.data == "connected") { connected++ document.getElementById("status").innerHTML += `${user} connected
` - - // FIXME: maybe save their state and only send them updates based on that - const state = uint8ArrayToStrBase64(Y.encodeStateAsUpdate(ydoc)) - //console.log("sending initial state", state) - SSB.net.tunnelMessage.sendMessage("prose-current-state", state) } else if (msg.type == 'info' && msg.data == "disconnected") { connected-- @@ -155,7 +169,6 @@ module.exports = function () { } else if (user != "me" && (msg.type == "prose-current-state" || msg.type == "prose-state-update")) { - //console.log("got update", user) //console.log("got update msg", msg.data) Y.applyUpdate(ydoc, strBase64ToUint8Array(msg.data)) } From 2e05e7dd8bb4cdbbd2526b128bf92e2ab04c918d Mon Sep 17 00:00:00 2001 From: Anders Rune Jensen Date: Tue, 7 Apr 2020 17:52:33 +0200 Subject: [PATCH 8/9] Update ssb-browser-core --- npm-shrinkwrap.json | 41 +++-------------------------------------- package.json | 2 +- 2 files changed, 4 insertions(+), 39 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index db23db9..4261c14 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -510,12 +510,6 @@ } } }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "optional": true - }, "async-single": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/async-single/-/async-single-1.0.5.tgz", @@ -4127,9 +4121,9 @@ } }, "ssb-browser-core": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ssb-browser-core/-/ssb-browser-core-3.0.0.tgz", - "integrity": "sha512-mkhx/cWScD6XRbB+eKQE6TKzmf+tdAKuySiju6X3voqV0iu1IP7oSK6j2l/HOAren6N+f1tG53BJopaNwH4VoQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ssb-browser-core/-/ssb-browser-core-3.1.0.tgz", + "integrity": "sha512-UBBrBcoviL5IIU7Z5IIsziKd5CuQtU79PlJlb5OWraD+tAQoE1KZYvgH6SK7q/5e8Zr8EyRhvC8LUSxTw9/mTA==", "requires": { "flumecodec": "0.0.1", "flumedb": "^2.1.1", @@ -5190,35 +5184,6 @@ "lib0": "^0.2.15" } }, - "y-protocols": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-0.2.3.tgz", - "integrity": "sha512-mJ838iW7XgMQqlv+9DtH7QyLqflZoy/VvaUWRIpwawee4mQiFJcEXazCmSYUHEbXIUuVNNc70FnuNSMWDC5vKQ==", - "requires": { - "lib0": "^0.2.20" - } - }, - "y-websocket": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/y-websocket/-/y-websocket-1.2.5.tgz", - "integrity": "sha512-Q8dcUrP7tZvfODPP/6cZ90lE+U3ucAUIBfPHwLtUov2WynDAqm/fc9fiARd5URYRk55m+edNkAhmwhkFNhbhFQ==", - "requires": { - "lib0": "^0.2.22", - "ws": "^6.2.1", - "y-protocols": "^0.2.3" - }, - "dependencies": { - "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "optional": true, - "requires": { - "async-limiter": "~1.0.0" - } - } - } - }, "yjs": { "version": "13.0.5", "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.0.5.tgz", diff --git a/package.json b/package.json index ee84680..15cf5dd 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "pull-abortable": "^4.1.1", "pull-stream": "^3.6.14", "rimraf": "^3.0.0", - "ssb-browser-core": "^3.0.0", + "ssb-browser-core": "^3.1.0", "ssb-contact-msg": "^1.1.0", "ssb-keys-mnemonic": "^0.2.0", "ssb-markdown": "^6.0.7", From fb6969e31c94b55ed645a11ef0c7247630c4e586 Mon Sep 17 00:00:00 2001 From: Anders Rune Jensen Date: Wed, 8 Apr 2020 22:15:37 +0200 Subject: [PATCH 9/9] Remove console.log --- ui/browser.js | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/browser.js b/ui/browser.js index 7b9a50e..773c9e8 100644 --- a/ui/browser.js +++ b/ui/browser.js @@ -8,7 +8,6 @@ } function ssbLoaded() { - console.log("ssb loaded") const Public = require('./public')(componentsState) const Profile = require('./profile')() const Notifications = require('./notifications')()