Commit 5a59ba682d902073cf69ba77bd1b7d0503920283
re-add viewer plugin
Ev Bogue committed on 8/31/2017, 7:33:29 PMParent: 4b72a4b3c3518eee46dfeef8be64a1ac1ac287af
Files changed
decent.js | changed |
package.json | changed |
plugins/viewer/README.md | added |
plugins/viewer/bin.js | added |
plugins/viewer/example.html | added |
plugins/viewer/index.js | added |
plugins/viewer/lib/about.js | added |
plugins/viewer/static/base.css | added |
plugins/viewer/static/nicer.css | added |
plugins/viewer/yarn.lock | added |
yarn.lock | changed |
decent.js | ||
---|---|---|
@@ -43,8 +43,9 @@ | ||
43 | 43 … | .use(require('ssb-query')) |
44 | 44 … | .use(require('ssb-links')) |
45 | 45 … | .use(require('ssb-ws')) |
46 | 46 … | .use(require('ssb-ebt')) |
47 … | + .use(require('./plugins/viewer')) | |
47 | 48 … | |
48 | 49 … | // add third-party plugins |
49 | 50 … | require('./plugins/plugins').loadUserPlugins(createSbot, config) |
50 | 51 … |
package.json | ||
---|---|---|
@@ -8,8 +8,9 @@ | ||
8 | 8 … | }, |
9 | 9 … | "author": "Ev Bogue", |
10 | 10 … | "license": "MIT", |
11 | 11 … | "dependencies": { |
12 … | + "asyncmemo": "^1.0.0", | |
12 | 13 … | "atomic-file": "0.0.1", |
13 | 14 … | "bash-color": "~0.0.3", |
14 | 15 … | "broadcast-stream": "~0.0.0", |
15 | 16 … | "cont": "~1.0.3", |
@@ -18,8 +19,9 @@ | ||
18 | 19 … | "deep-extend": "^0.5.0", |
19 | 20 … | "depject": "^3.0.0", |
20 | 21 … | "ecstatic": "^2.1.0", |
21 | 22 … | "emoji-named-characters": "^1.0.2", |
23 … | + "emoji-server": "^1.0.0", | |
22 | 24 … | "explain-error": "~1.0.1", |
23 | 25 … | "has-network": "0.0.0", |
24 | 26 … | "human-time": "0.0.1", |
25 | 27 … | "hypercombo": "0.1.0", |
@@ -31,8 +33,9 @@ | ||
31 | 33 … | "hypertabs-vertical": "^3.0.0", |
32 | 34 … | "ip": "^0.3.3", |
33 | 35 … | "is-visible": "^2.1.1", |
34 | 36 … | "kvgraph": "^0.1.0", |
37 … | + "lrucache": "^1.0.3", | |
35 | 38 … | "map-filter-reduce": "^3.0.1", |
36 | 39 … | "mdmanifest": "^1.0.4", |
37 | 40 … | "minimist": "^1.1.3", |
38 | 41 … | "mkdirp": "~0.5.0", |
@@ -78,11 +81,13 @@ | ||
78 | 81 … | "ssb-git": "^0.5.0", |
79 | 82 … | "ssb-keys": "^7.0.10", |
80 | 83 … | "ssb-links": "^2.0.0", |
81 | 84 … | "ssb-markdown": "^3.3.0", |
85 … | + "ssb-marked": "^0.7.2", | |
82 | 86 … | "ssb-mentions": "^0.4.0", |
83 | 87 … | "ssb-query": "^1.0.0", |
84 | 88 … | "ssb-ref": "^2.7.1", |
89 … | + "ssb-sort": "^1.0.0", | |
85 | 90 … | "ssb-ws": "^1.0.3", |
86 | 91 … | "statistics": "3.0.0", |
87 | 92 … | "stream-to-pull-stream": "^1.6.10", |
88 | 93 … | "suggest-box": "^2.2.1", |
plugins/viewer/README.md | ||
---|---|---|
@@ -1,0 +1,108 @@ | ||
1 … | +# ssb-viewer | |
2 … | + | |
3 … | +HTTP server for read-only views of SSB content. Serves content as web pages or as scripts for embedding in other web pages. | |
4 … | + | |
5 … | +## Install & Run | |
6 … | + | |
7 … | +As a sbot plugin: | |
8 … | +```sh | |
9 … | +mkdir -p ~/.ssb/node_modules | |
10 … | +cd ~/.ssb/node_modules | |
11 … | +git clone ssb://%MeCTQrz9uszf9EZoTnKCeFeIedhnKWuB3JHW2l1g9NA=.sha256 ssb-viewer && cd ssb-viewer | |
12 … | +npm install | |
13 … | +sbot plugins.enable ssb-viewer | |
14 … | +# restart sbot | |
15 … | +``` | |
16 … | + | |
17 … | +Or standalone: | |
18 … | +```sh | |
19 … | +git clone ssb://%MeCTQrz9uszf9EZoTnKCeFeIedhnKWuB3JHW2l1g9NA=.sha256 ssb-viewer && cd ssb-viewer | |
20 … | +npm install | |
21 … | +./bin.js | |
22 … | +``` | |
23 … | + | |
24 … | +## Usage | |
25 … | + | |
26 … | +To view a thread as a web page, navigate to a url like `http://localhost:8807/%MSGID`. | |
27 … | + | |
28 … | +To embed a thread into another web page, load it as follows: | |
29 … | + | |
30 … | +```html | |
31 … | +<script src="http://localhost:8807/%MSGID.js"></script> | |
32 … | +``` | |
33 … | + | |
34 … | +To add more than the base styles, you can also load `http://localhost:8807/static/nicer.css`. | |
35 … | + | |
36 … | +## Routes | |
37 … | + | |
38 … | +- `/%msgid`: web page showing a message thread | |
39 … | +- `/%msgid.js`: script to embed a message thread | |
40 … | +- `/%msgid.json`: message thread as JSON | |
41 … | +- `/&feedid`: web page showing a complete feed | |
42 … | +- `/user-feed/&feedid`: web page showing messages from followed users and channels of a feed | |
43 … | +- `/channel/#channel`: web page showing messages in a specific channel | |
44 … | + | |
45 … | +### Query options | |
46 … | + | |
47 … | +- `noroot`: don't include the root message in the thread | |
48 … | +- `base=...`: base url for links that ssb-viewer can handle | |
49 … | +- `msg_base=...`: base url for links to messages | |
50 … | +- `feed_base=...`: base url for links to feeds | |
51 … | +- `blob_base=...`: base url for links to blobs | |
52 … | +- `img_base=...`: base url for embedded blobs (images) | |
53 … | +- `emoji_base=...`: base url for emoji images | |
54 … | + | |
55 … | +The `*_base` query options overwrite the defaults set in the config. | |
56 … | +The `base` option is a fallback instead of specifying the URLs separately. | |
57 … | +The base options are mostly useful for embedding, where the script is embedded | |
58 … | +on a different origin than where ssb-viewer is running. However, you may not | |
59 … | +need them, as the ssb-viewer embed script will detect the base where it is | |
60 … | +included from. | |
61 … | + | |
62 … | +## Config | |
63 … | + | |
64 … | +To change `ssb-viewer`'s default options, edit your `~/.ssb/config`, to have | |
65 … | +properties like the following: | |
66 … | +```json | |
67 … | +{ | |
68 … | + "viewer": { | |
69 … | + "port": 8807, | |
70 … | + "host": "::" | |
71 … | + } | |
72 … | +} | |
73 … | +``` | |
74 … | +You can also pass these as command-line options to `./bin.js` or `sbot` as, | |
75 … | +e.g. `--viewer.port 8807`. | |
76 … | + | |
77 … | +- `viewer.port`: port for the server to listen on. default: `8807` | |
78 … | +- `viewer.host`: host address for the server to listen on. default: `::` | |
79 … | +- `viewer.base`: default base url for links that ssb-viewer can handle | |
80 … | +- `viewer.msg_base`: base url for links to ssb messages | |
81 … | +- `viewer.feed_base`: base url for links to ssb feeds | |
82 … | +- `viewer.blob_base`: base url for links to ssb blobs | |
83 … | +- `viewer.img_base`: base url for embedded blobs (images) | |
84 … | +- `viewer.emoji_base`: base url for emoji images | |
85 … | + | |
86 … | +## References | |
87 … | + | |
88 … | +- Concept: [ssb-porthole][] | |
89 … | +- UI ideas: [sdash][], [patchbay][] | |
90 … | +- Server techniques: [ssb-web-server][], [ssb-ws][], [git-ssb-web][] | |
91 … | + | |
92 … | + | |
93 … | +[ssb-porthole]: %cgkDJXsh6pO5m458B3ngEro+U0qUMGTY1TRGTZOP6lQ=.sha256 | |
94 … | +[patchbay]: %s9mSFATE4RGyJx9wgH22lBrvD4CgUQW4yeguSWWjtqc=.sha256 | |
95 … | +[sdash]: %qrU04j9vfUJKfq1rGZrQ5ihtSfA4ilfY3wLy7xFv0xk=.sha256 | |
96 … | +[git-ssb-web]: %q5d5Du+9WkaSdjc8aJPZm+jMrqgo0tmfR+RcX5ZZ6H4=.sha256 | |
97 … | +[ssb-web-server]: %gYctTCrA06BhAGGvQ6PJ0H2eCCQLj1iEsmfn8SD5+nk=.sha256 | |
98 … | +[ssb-ws]: %tFjo5SoD+Y0SaB5vqZYppmoPmv9LKB5wMPl96qtu4qk=.sha256 | |
99 … | + | |
100 … | +## License | |
101 … | + | |
102 … | +Copyright (c) 2016-2017 Secure Scuttlebutt Consortium | |
103 … | + | |
104 … | +Usage of the works is permitted provided that this instrument is | |
105 … | +retained with the works, so that any entity that uses the works is | |
106 … | +notified of this instrument. | |
107 … | + | |
108 … | +DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY. |
plugins/viewer/bin.js | ||
---|---|---|
@@ -1,0 +1,6 @@ | ||
1 … | +#!/usr/bin/env node | |
2 … | + | |
3 … | +require('../ssb-client')(function (err, sbot, config) { | |
4 … | + if (err) throw err | |
5 … | + require('.').init(sbot, config) | |
6 … | +}) |
plugins/viewer/example.html | ||
---|---|---|
@@ -1,0 +1,28 @@ | ||
1 … | + | |
2 … | +<html> | |
3 … | +<head> | |
4 … | +<meta charset=utf-8> | |
5 … | +<title>ssb-viewer</title> | |
6 … | +<meta name=viewport content="width=device-width,initial-scale=1"> | |
7 … | +<link rel="stylesheet" href="static/nicer.css"> | |
8 … | +<style> | |
9 … | +body { | |
10 … | + background-color: #f3f3f3; | |
11 … | +} | |
12 … | +#demo .ssb-thread { | |
13 … | + background-color: white; | |
14 … | + padding: 1ex 2em; | |
15 … | +} | |
16 … | +</style> | |
17 … | +</head> | |
18 … | +<body id="demo"> | |
19 … | + <center> | |
20 … | + <h1>Embed Example</h1> | |
21 … | + </center> | |
22 … | + <script src="http://localhost:8807/%fU0K0uC4orV6258+dGuAcA95TSfc9PrTtKIG9uL3rWI=.sha256.js"></script> | |
23 … | + <center> | |
24 … | + <p>the end</p> | |
25 … | + </center> | |
26 … | +</div> | |
27 … | +</body> | |
28 … | +</html> |
plugins/viewer/index.js | ||
---|---|---|
@@ -1,0 +1,636 @@ | ||
1 … | +var fs = require('fs') | |
2 … | +var http = require('http') | |
3 … | +var qs = require('querystring') | |
4 … | +var path = require('path') | |
5 … | +var crypto = require('crypto') | |
6 … | +var cat = require('pull-cat') | |
7 … | +var pull = require('pull-stream') | |
8 … | +var paramap = require('pull-paramap') | |
9 … | +var marked = require('ssb-marked') | |
10 … | +var sort = require('ssb-sort') | |
11 … | +var toPull = require('stream-to-pull-stream') | |
12 … | +var memo = require('asyncmemo') | |
13 … | +var lru = require('lrucache') | |
14 … | +var htime = require('human-time') | |
15 … | +var emojis = require('emoji-named-characters') | |
16 … | +var serveEmoji = require('emoji-server')() | |
17 … | + | |
18 … | +var emojiDir = path.join(require.resolve('emoji-named-characters'), '../pngs') | |
19 … | +var appHash = hash([fs.readFileSync(__filename)]) | |
20 … | + | |
21 … | +var urlIdRegex = /^(?:\/(([%&@]|%25|%26|%40)(?:[A-Za-z0-9\/+]|%2[Ff]|%2[Bb]){43}(?:=|%3[Dd])\.(?:sha256|ed25519))(?:\.([^?]*))?|(\/.*?))(?:\?(.*))?$/ | |
22 … | + | |
23 … | +function MdRenderer(opts) { | |
24 … | + marked.Renderer.call(this, {}) | |
25 … | + this.opts = opts | |
26 … | +} | |
27 … | +MdRenderer.prototype = new marked.Renderer() | |
28 … | + | |
29 … | +MdRenderer.prototype.urltransform = function (href) { | |
30 … | + if (!href) return false | |
31 … | + switch (href[0]) { | |
32 … | + case '#': return '/channel/' + href.slice(1) | |
33 … | + case '%': return this.opts.msg_base + encodeURIComponent(href) | |
34 … | + case '@': return this.opts.feed_base + encodeURIComponent(href) | |
35 … | + case '&': return this.opts.blob_base + encodeURIComponent(href) | |
36 … | + } | |
37 … | + if (href.indexOf('javascript:') === 0) return false | |
38 … | + return href | |
39 … | +} | |
40 … | + | |
41 … | +MdRenderer.prototype.image = function (href, title, text) { | |
42 … | + return '<img src="' + this.opts.img_base + escape(href) + '"' | |
43 … | + + ' alt="' + text + '"' | |
44 … | + + (title ? ' title="' + title + '"' : '') | |
45 … | + + (this.options.xhtml ? '/>' : '>') | |
46 … | +} | |
47 … | + | |
48 … | +function renderEmoji(emoji) { | |
49 … | + var opts = this.renderer.opts | |
50 … | + return emoji in emojis ? | |
51 … | + '<img src="' + opts.emoji_base + escape(emoji) + '.png"' | |
52 … | + + ' alt=":' + escape(emoji) + ':"' | |
53 … | + + ' title=":' + escape(emoji) + ':"' | |
54 … | + + ' class="ssb-emoji" height="16" width="16">' | |
55 … | + : ':' + emoji + ':' | |
56 … | +} | |
57 … | + | |
58 … | +exports.name = 'viewer' | |
59 … | +exports.manifest = {} | |
60 … | +exports.version = '0.0.0' | |
61 … | + | |
62 … | +exports.init = function (sbot, config) { | |
63 … | + var conf = config.viewer || {} | |
64 … | + var port = conf.port || 3307 | |
65 … | + var host = conf.host || config.host || '::' | |
66 … | + | |
67 … | + var base = conf.base || '/' | |
68 … | + var defaultOpts = { | |
69 … | + msg_base: conf.msg_base || base, | |
70 … | + feed_base: conf.feed_base || base, | |
71 … | + blob_base: conf.blob_base || base, | |
72 … | + img_base: conf.img_base || base, | |
73 … | + emoji_base: conf.emoji_base || (base + 'emoji/'), | |
74 … | + } | |
75 … | + | |
76 … | + var getMsg = memo({cache: lru(100)}, getMsgWithValue, sbot) | |
77 … | + var getAbout = memo({cache: lru(100)}, require('./lib/about'), sbot) | |
78 … | + | |
79 … | + http.createServer(serve).listen(port, host, function () { | |
80 … | + console.log('[viewer] Listening on http://' + host + ':' + port) | |
81 … | + }) | |
82 … | + | |
83 … | + function serve(req, res) { | |
84 … | + if (req.method !== 'GET' && req.method !== 'HEAD') { | |
85 … | + return respond(res, 405, 'Method must be GET or HEAD') | |
86 … | + } | |
87 … | + | |
88 … | + var m = urlIdRegex.exec(req.url) | |
89 … | + | |
90 … | + if (req.url.startsWith('/user-feed/')) return serveUserFeed(req, res, m[4]) | |
91 … | + else if (req.url.startsWith('/channel/')) return serveChannel(req, res, m[4]) | |
92 … | + | |
93 … | + if (m[2] && m[2].length === 3) { | |
94 … | + m[1] = decodeURIComponent(m[1]) | |
95 … | + m[2] = m[1][0] | |
96 … | + } | |
97 … | + switch (m[2]) { | |
98 … | + case '%': return serveId(req, res, m[1], m[3], m[5]) | |
99 … | + case '@': return serveFeed(req, res, m[1], m[3], m[5]) | |
100 … | + case '&': return serveBlob(req, res, sbot, m[1]) | |
101 … | + default: return servePath(req, res, m[4]) | |
102 … | + } | |
103 … | + } | |
104 … | + | |
105 … | + function serveFeed(req, res, feedId) { | |
106 … | + console.log("serving feed: " + feedId) | |
107 … | + | |
108 … | + var opts = defaultOpts | |
109 … | + | |
110 … | + opts.marked = { | |
111 … | + gfm: true, | |
112 … | + mentions: true, | |
113 … | + tables: true, | |
114 … | + breaks: true, | |
115 … | + pedantic: false, | |
116 … | + sanitize: true, | |
117 … | + smartLists: true, | |
118 … | + smartypants: false, | |
119 … | + emoji: renderEmoji, | |
120 … | + renderer: new MdRenderer(opts) | |
121 … | + } | |
122 … | + | |
123 … | + getAbout(feedId, function (err, about) { | |
124 … | + if (err) return cb(err) | |
125 … | + | |
126 … | + pull( | |
127 … | + sbot.createUserStream({ id: feedId, reverse: true, limit: 100 }), | |
128 … | + // sbot.createUserStream({ id: feedId, reverse: true }), | |
129 … | + pull.collect(function (err, logs) { | |
130 … | + if (err) return respond(res, 500, err.stack || err) | |
131 … | + res.writeHead(200, { | |
132 … | + 'Content-Type': ctype("html") | |
133 … | + }) | |
134 … | + pull( | |
135 … | + pull.values(logs), | |
136 … | + paramap(addAuthorAbout, 8), | |
137 … | + paramap(addFollowAbout, 8), | |
138 … | + paramap(addVoteMessage, 8), | |
139 … | + pull(renderThread(opts), wrapPage(about.name)), | |
140 … | + toPull(res, function (err) { | |
141 … | + if (err) console.error('[viewer]', err) | |
142 … | + }) | |
143 … | + ) | |
144 … | + }) | |
145 … | + ) | |
146 … | + }) | |
147 … | + } | |
148 … | + | |
149 … | + function serveUserFeed(req, res, url) { | |
150 … | + var feedId = url.substring(url.lastIndexOf('user-feed/')+10, 100) | |
151 … | + console.log("serving user feed: " + feedId) | |
152 … | + | |
153 … | + var following = [] | |
154 … | + var channelSubscriptions = [] | |
155 … | + | |
156 … | + getAbout(feedId, function (err, about) { | |
157 … | + pull( | |
158 … | + sbot.createUserStream({ id: feedId }), | |
159 … | + pull.filter((msg) => { | |
160 … | + return !msg.value || | |
161 … | + msg.value.content.type == 'contact' | |
162 … | + }), | |
163 … | + pull.collect(function (err, msgs) { | |
164 … | + msgs.forEach((msg) => { | |
165 … | + if (msg.value.content.type == 'contact') | |
166 … | + { | |
167 … | + if (msg.value.content.following) | |
168 … | + following[msg.value.content.contact] = 1 | |
169 … | + else | |
170 … | + delete following[msg.value.content.contact] | |
171 … | + } | |
172 … | + }) | |
173 … | + | |
174 … | + serveFeeds(req, res, following, channelSubscriptions, feedId, 'user feed ' + about.name) | |
175 … | + }) | |
176 … | + ) | |
177 … | + }) | |
178 … | + } | |
179 … | + | |
180 … | + function serveFeeds(req, res, following, channelSubscriptions, feedId, name) { | |
181 … | + var opts = defaultOpts | |
182 … | + | |
183 … | + opts.marked = { | |
184 … | + gfm: true, | |
185 … | + mentions: true, | |
186 … | + tables: true, | |
187 … | + breaks: true, | |
188 … | + pedantic: false, | |
189 … | + sanitize: true, | |
190 … | + smartLists: true, | |
191 … | + smartypants: false, | |
192 … | + emoji: renderEmoji, | |
193 … | + renderer: new MdRenderer(opts) | |
194 … | + } | |
195 … | + | |
196 … | + pull( | |
197 … | + sbot.createLogStream({ reverse: true, limit: 2500 }), | |
198 … | + pull.filter((msg) => { | |
199 … | + return !msg.value || | |
200 … | + (msg.value.author in following || | |
201 … | + msg.value.content.channel in channelSubscriptions) | |
202 … | + }), | |
203 … | + pull.take(100), | |
204 … | + pull.collect(function (err, logs) { | |
205 … | + if (err) return respond(res, 500, err.stack || err) | |
206 … | + res.writeHead(200, { | |
207 … | + 'Content-Type': ctype("html") | |
208 … | + }) | |
209 … | + pull( | |
210 … | + pull.values(logs), | |
211 … | + paramap(addAuthorAbout, 8), | |
212 … | + paramap(addFollowAbout, 8), | |
213 … | + paramap(addVoteMessage, 8), | |
214 … | + pull(renderThread(opts), wrapPage(name)), | |
215 … | + toPull(res, function (err) { | |
216 … | + if (err) console.error('[viewer]', err) | |
217 … | + }) | |
218 … | + ) | |
219 … | + }) | |
220 … | + ) | |
221 … | + } | |
222 … | + | |
223 … | + function serveChannel(req, res, url) { | |
224 … | + var channelId = url.substring(url.lastIndexOf('channel/')+8, 100) | |
225 … | + console.log("serving channel: " + channelId) | |
226 … | + | |
227 … | + var opts = defaultOpts | |
228 … | + | |
229 … | + opts.marked = { | |
230 … | + gfm: true, | |
231 … | + mentions: true, | |
232 … | + tables: true, | |
233 … | + breaks: true, | |
234 … | + pedantic: false, | |
235 … | + sanitize: true, | |
236 … | + smartLists: true, | |
237 … | + smartypants: false, | |
238 … | + emoji: renderEmoji, | |
239 … | + renderer: new MdRenderer(opts) | |
240 … | + } | |
241 … | + | |
242 … | + pull( | |
243 … | + sbot.query.read({ limit: 500, reverse: true, query: [{$filter: { value: { content: { channel: channelId }}}}]}), | |
244 … | + pull.collect(function (err, logs) { | |
245 … | + if (err) return respond(res, 500, err.stack || err) | |
246 … | + res.writeHead(200, { | |
247 … | + 'Content-Type': ctype("html") | |
248 … | + }) | |
249 … | + pull( | |
250 … | + pull.values(logs), | |
251 … | + paramap(addAuthorAbout, 8), | |
252 … | + paramap(addVoteMessage, 8), | |
253 … | + pull(renderThread(opts), wrapPage('#' + channelId)), | |
254 … | + toPull(res, function (err) { | |
255 … | + if (err) console.error('[viewer]', err) | |
256 … | + }) | |
257 … | + ) | |
258 … | + }) | |
259 … | + ) | |
260 … | + } | |
261 … | + | |
262 … | + function addFollowAbout(msg, cb) { | |
263 … | + if (msg.value.content.contact) | |
264 … | + getAbout(msg.value.content.contact, function (err, about) { | |
265 … | + if (err) return cb(err) | |
266 … | + msg.value.content.contactAbout = about | |
267 … | + cb(null, msg) | |
268 … | + }) | |
269 … | + else | |
270 … | + cb(null, msg) | |
271 … | + } | |
272 … | + | |
273 … | + function addVoteMessage(msg, cb) { | |
274 … | + if (msg.value.content.type == 'vote' && msg.value.content.vote.link[0] == '%') | |
275 … | + getMsg(msg.value.content.vote.link, function (err, linkedMsg) { | |
276 … | + if (linkedMsg) | |
277 … | + msg.value.content.vote.linkedText = linkedMsg.value.content.text | |
278 … | + cb(null, msg) | |
279 … | + }) | |
280 … | + else | |
281 … | + cb(null, msg) | |
282 … | + } | |
283 … | + | |
284 … | + function serveId(req, res, id, ext, query) { | |
285 … | + var q = query ? qs.parse(query) : {} | |
286 … | + var includeRoot = !('noroot' in q) | |
287 … | + var base = q.base || conf.base | |
288 … | + var baseToken | |
289 … | + if (!base) { | |
290 … | + if (ext === 'js') base = baseToken = '__BASE_' + Math.random() + '_' | |
291 … | + else base = '/' | |
292 … | + } | |
293 … | + var opts = { | |
294 … | + base: base, | |
295 … | + base_token: baseToken, | |
296 … | + msg_base: q.msg_base || conf.msg_base || base, | |
297 … | + feed_base: q.feed_base || conf.feed_base || base, | |
298 … | + blob_base: q.blob_base || conf.blob_base || base, | |
299 … | + img_base: q.img_base || conf.img_base || base, | |
300 … | + emoji_base: q.emoji_base || conf.emoji_base || (base + 'emoji/'), | |
301 … | + } | |
302 … | + opts.marked = { | |
303 … | + gfm: true, | |
304 … | + mentions: true, | |
305 … | + tables: true, | |
306 … | + breaks: true, | |
307 … | + pedantic: false, | |
308 … | + sanitize: true, | |
309 … | + smartLists: true, | |
310 … | + smartypants: false, | |
311 … | + emoji: renderEmoji, | |
312 … | + renderer: new MdRenderer(opts) | |
313 … | + } | |
314 … | + | |
315 … | + var format = formatMsgs(id, ext, opts) | |
316 … | + if (format === null) return respond(res, 415, 'Invalid format') | |
317 … | + | |
318 … | + pull( | |
319 … | + sbot.links({dest: id, values: true, rel: 'root'}), | |
320 … | + includeRoot && prepend(getMsg, id), | |
321 … | + pull.unique('key'), | |
322 … | + pull.collect(function (err, links) { | |
323 … | + if (err) return respond(res, 500, err.stack || err) | |
324 … | + var etag = hash(sort.heads(links).concat(appHash, ext, qs)) | |
325 … | + if (req.headers['if-none-match'] === etag) return respond(res, 304) | |
326 … | + res.writeHead(200, { | |
327 … | + 'Content-Type': ctype(ext), | |
328 … | + 'etag': etag | |
329 … | + }) | |
330 … | + pull( | |
331 … | + pull.values(sort(links)), | |
332 … | + paramap(addAuthorAbout, 8), | |
333 … | + format, | |
334 … | + toPull(res, function (err) { | |
335 … | + if (err) console.error('[viewer]', err) | |
336 … | + }) | |
337 … | + ) | |
338 … | + }) | |
339 … | + ) | |
340 … | + } | |
341 … | + | |
342 … | + function addAuthorAbout(msg, cb) { | |
343 … | + getAbout(msg.value.author, function (err, about) { | |
344 … | + if (err) return cb(err) | |
345 … | + msg.author = about | |
346 … | + cb(null, msg) | |
347 … | + }) | |
348 … | + } | |
349 … | +} | |
350 … | + | |
351 … | +function serveBlob(req, res, sbot, id) { | |
352 … | + if (req.headers['if-none-match'] === id) return respond(res, 304) | |
353 … | + sbot.blobs.has(id, function (err, has) { | |
354 … | + if (err) { | |
355 … | + if (/^invalid/.test(err.message)) return respond(res, 400, err.message) | |
356 … | + else return respond(res, 500, err.message || err) | |
357 … | + } | |
358 … | + if (!has) return respond(res, 404, 'Not found') | |
359 … | + res.writeHead(200, { | |
360 … | + 'Cache-Control': 'public, max-age=315360000', | |
361 … | + 'etag': id | |
362 … | + }) | |
363 … | + pull( | |
364 … | + sbot.blobs.get(id), | |
365 … | + toPull(res, function (err) { | |
366 … | + if (err) console.error('[viewer]', err) | |
367 … | + }) | |
368 … | + ) | |
369 … | + }) | |
370 … | +} | |
371 … | + | |
372 … | +function getMsgWithValue(sbot, id, cb) { | |
373 … | + sbot.get(id, function (err, value) { | |
374 … | + if (err) return cb(err) | |
375 … | + cb(null, {key: id, value: value}) | |
376 … | + }) | |
377 … | +} | |
378 … | + | |
379 … | +function escape(str) { | |
380 … | + return String(str) | |
381 … | + .replace(/&/g, '&') | |
382 … | + .replace(/</g, '<') | |
383 … | + .replace(/>/g, '>') | |
384 … | + .replace(/"/g, '"') | |
385 … | +} | |
386 … | + | |
387 … | +function respond(res, status, message) { | |
388 … | + res.writeHead(status) | |
389 … | + res.end(message) | |
390 … | +} | |
391 … | + | |
392 … | +function ctype(name) { | |
393 … | + switch (name && /[^.\/]*$/.exec(name)[0] || 'html') { | |
394 … | + case 'html': return 'text/html' | |
395 … | + case 'js': return 'text/javascript' | |
396 … | + case 'css': return 'text/css' | |
397 … | + case 'json': return 'application/json' | |
398 … | + } | |
399 … | +} | |
400 … | + | |
401 … | +function servePath(req, res, url) { | |
402 … | + switch (url) { | |
403 … | + case '/robots.txt': return res.end('User-agent: *') | |
404 … | + } | |
405 … | + var m = /^(\/?[^\/]*)(\/.*)?$/.exec(url) | |
406 … | + switch (m[1]) { | |
407 … | + case '/static': return serveStatic(req, res, m[2]) | |
408 … | + case '/emoji': return serveEmoji(req, res, m[2]) | |
409 … | + } | |
410 … | + return respond(res, 404, 'Not found') | |
411 … | +} | |
412 … | + | |
413 … | +function ifModified(req, lastMod) { | |
414 … | + var ifModSince = req.headers['if-modified-since'] | |
415 … | + if (!ifModSince) return false | |
416 … | + var d = new Date(ifModSince) | |
417 … | + return d && Math.floor(d/1000) >= Math.floor(lastMod/1000) | |
418 … | +} | |
419 … | + | |
420 … | +function serveStatic(req, res, file) { | |
421 … | + serveFile(req, res, path.join(__dirname, 'static', file)) | |
422 … | +} | |
423 … | + | |
424 … | +function serveFile(req, res, file) { | |
425 … | + fs.stat(file, function (err, stat) { | |
426 … | + if (err && err.code === 'ENOENT') return respond(res, 404, 'Not found') | |
427 … | + if (err) return respond(res, 500, err.stack || err) | |
428 … | + if (!stat.isFile()) return respond(res, 403, 'May only load files') | |
429 … | + if (ifModified(req, stat.mtime)) return respond(res, 304, 'Not modified') | |
430 … | + res.writeHead(200, { | |
431 … | + 'Content-Type': ctype(file), | |
432 … | + 'Content-Length': stat.size, | |
433 … | + 'Last-Modified': stat.mtime.toGMTString() | |
434 … | + }) | |
435 … | + fs.createReadStream(file).pipe(res) | |
436 … | + }) | |
437 … | +} | |
438 … | + | |
439 … | +function prepend(fn, arg) { | |
440 … | + return function (read) { | |
441 … | + return function (abort, cb) { | |
442 … | + if (fn && !abort) { | |
443 … | + var _fn = fn | |
444 … | + fn = null | |
445 … | + return _fn(arg, function (err, value) { | |
446 … | + if (err) return read(err, function (err) { | |
447 … | + cb(err || true) | |
448 … | + }) | |
449 … | + cb(null, value) | |
450 … | + }) | |
451 … | + } | |
452 … | + read(abort, cb) | |
453 … | + } | |
454 … | + } | |
455 … | +} | |
456 … | + | |
457 … | +function formatMsgs(id, ext, opts) { | |
458 … | + switch (ext || 'html') { | |
459 … | + case 'html': return pull(renderThread(opts), wrapPage(id)) | |
460 … | + case 'js': return pull(renderThread(opts), wrapJSEmbed(opts)) | |
461 … | + case 'json': return wrapJSON() | |
462 … | + default: return null | |
463 … | + } | |
464 … | +} | |
465 … | + | |
466 … | +function wrap(before, after) { | |
467 … | + return function (read) { | |
468 … | + return cat([pull.once(before), read, pull.once(after)]) | |
469 … | + } | |
470 … | +} | |
471 … | + | |
472 … | +function renderThread(opts) { | |
473 … | + return pull( | |
474 … | + pull.map(renderMsg.bind(this, opts)), | |
475 … | + wrap('<div class="ssb-thread">', '</div>') | |
476 … | + ) | |
477 … | +} | |
478 … | + | |
479 … | +function wrapPage(id) { | |
480 … | + return wrap('<!doctype html><html><head>' | |
481 … | + + '<meta charset=utf-8>' | |
482 … | + + '<title>' + id + ' | ssb-viewer</title>' | |
483 … | + + '<meta name=viewport content="width=device-width,initial-scale=1">' | |
484 … | + + '<link rel=stylesheet href="/static/base.css">' | |
485 … | + + '<link rel=stylesheet href="/static/nicer.css">' | |
486 … | + + '<link rel=stylesheet href="http://evbogue.com/style.css">' | |
487 … | + + '</head><body>', | |
488 … | + '</body></html>' | |
489 … | + ) | |
490 … | +} | |
491 … | + | |
492 … | +function wrapJSON() { | |
493 … | + var first = true | |
494 … | + return pull( | |
495 … | + pull.map(JSON.stringify), | |
496 … | + join(','), | |
497 … | + wrap('[', ']') | |
498 … | + ) | |
499 … | +} | |
500 … | + | |
501 … | +function wrapJSEmbed(opts) { | |
502 … | + return pull( | |
503 … | + wrap('<link rel=stylesheet href="' + opts.base + 'static/base.css">', ''), | |
504 … | + pull.map(docWrite), | |
505 … | + opts.base_token && rewriteBase(new RegExp(opts.base_token, 'g')) | |
506 … | + ) | |
507 … | +} | |
508 … | + | |
509 … | + | |
510 … | +function rewriteBase(token) { | |
511 … | + // detect the origin of the script and rewrite the js/html to use it | |
512 … | + return pull( | |
513 … | + replace(token, '" + SSB_VIEWER_ORIGIN + "/'), | |
514 … | + wrap('var SSB_VIEWER_ORIGIN = (function () {' | |
515 … | + + 'var scripts = document.getElementsByTagName("script")\n' | |
516 … | + + 'var script = scripts[scripts.length-1]\n' | |
517 … | + + 'if (!script) return location.origin\n' | |
518 … | + + 'return script.src.replace(/\\/%.*$/, "")\n' | |
519 … | + + '}())\n', '') | |
520 … | + ) | |
521 … | +} | |
522 … | + | |
523 … | +function join(delim) { | |
524 … | + var first = true | |
525 … | + return pull.map(function (val) { | |
526 … | + if (!first) return delim + String(val) | |
527 … | + first = false | |
528 … | + return val | |
529 … | + }) | |
530 … | +} | |
531 … | + | |
532 … | +function replace(re, rep) { | |
533 … | + return pull.map(function (val) { | |
534 … | + return String(val).replace(re, rep) | |
535 … | + }) | |
536 … | +} | |
537 … | + | |
538 … | +function docWrite(str) { | |
539 … | + return 'document.write(' + JSON.stringify(str) + ')\n' | |
540 … | +} | |
541 … | + | |
542 … | +function hash(arr) { | |
543 … | + return arr.reduce(function (hash, item) { | |
544 … | + return hash.update(String(item)) | |
545 … | + }, crypto.createHash('sha256')).digest('base64') | |
546 … | +} | |
547 … | + | |
548 … | +function renderMsg(opts, msg) { | |
549 … | + var c = msg.value.content || {} | |
550 … | + var name = encodeURIComponent(msg.key) | |
551 … | + return '<div class="ssb-message" id="' + name + '">' | |
552 … | + + '<img class="ssb-avatar-image" alt=""' | |
553 … | + + ' src="' + opts.img_base + escape(msg.author.image) + '"' | |
554 … | + + ' height="32" width="32">' | |
555 … | + + '<a class="ssb-avatar-name"' | |
556 … | + + ' href="/' + escape(msg.value.author) + '"' | |
557 … | + + '>' + msg.author.name + '</a>' | |
558 … | + + msgTimestamp(msg, name) | |
559 … | + + render(opts, c) | |
560 … | + + '</div>' | |
561 … | +} | |
562 … | + | |
563 … | +function msgTimestamp(msg, name) { | |
564 … | + var date = new Date(msg.value.timestamp) | |
565 … | + return '<time class="ssb-timestamp" datetime="' + date.toISOString() + '">' | |
566 … | + + '<a href="#' + name + '">' | |
567 … | + + formatDate(date) + '</a></time>' | |
568 … | +} | |
569 … | + | |
570 … | +function formatDate(date) { | |
571 … | + // return date.toISOString().replace('T', ' ') | |
572 … | + return htime(date) | |
573 … | +} | |
574 … | + | |
575 … | +function render(opts, c) | |
576 … | +{ | |
577 … | + if (c.type === 'post') { | |
578 … | + var channel = c.channel ? ' in <a href="/channel/' + c.channel + '">#' + c.channel + '</a>' : '' | |
579 … | + return channel + renderPost(opts, c) | |
580 … | + } else if (c.type == 'vote' && c.vote.expression == 'Dig') { | |
581 … | + var channel = c.channel ? ' in <a href="/channel/' + c.channel + '">#' + c.channel + '</a>' : '' | |
582 … | + var linkedText = 'this' | |
583 … | + if (typeof c.vote.linkedText != 'undefined') | |
584 … | + linkedText = c.vote.linkedText.substring(0, 75) | |
585 … | + return ' dug ' + '<a href="/' + c.vote.link + '">' + linkedText + '</a>' + channel | |
586 … | + } | |
587 … | + else if (c.type == 'vote') { | |
588 … | + var linkedText = 'this' | |
589 … | + if (typeof c.vote.linkedText != 'undefined') | |
590 … | + linkedText = c.vote.linkedText.substring(0, 75) | |
591 … | + return ' voted <a href="/' + c.vote.link + '">' + linkedText + '</a>' | |
592 … | + } | |
593 … | + else if (c.type == 'contact' && c.following) { | |
594 … | + var name = c.contact | |
595 … | + if (typeof c.contactAbout != 'undefined') | |
596 … | + name = c.contactAbout.name | |
597 … | + return ' followed <a href="/' + c.contact + '">' + name + "</a>" | |
598 … | + } | |
599 … | + else if (c.type == 'contact' && !c.following) { | |
600 … | + var name = c.contact | |
601 … | + if (typeof c.contactAbout != 'undefined') | |
602 … | + name = c.contactAbout.name | |
603 … | + return ' unfollowed <a href="/' + c.contact + '">' + name + "</a>" | |
604 … | + } | |
605 … | + else if (typeof c == 'string') | |
606 … | + return ' sent a private message ' | |
607 … | + else if (c.type == 'about') | |
608 … | + return ' changed something in about' | |
609 … | + else if (c.type == 'issue') | |
610 … | + return ' created an issue' | |
611 … | + else if (c.type == 'git-update') | |
612 … | + return ' pushed to <a href="http://gitmx.com/'+ encodeURIComponent(c.repo) + '/">' + c.repo.substring(0, 10)+'...' + '</a><ul>' + | |
613 … | + (c.commits != undefined ? | |
614 … | + c.commits.map(com => { return '<li><code>' + com.sha1.substring(0, 10) + '</code> "' + com.title + '"</li>' }).join('') : "</ul>") | |
615 … | + else if (c.type == 'ssb-dns') | |
616 … | + return ' updated dns' | |
617 … | + else if (c.type == 'pub') | |
618 … | + return ' connected to a pub' | |
619 … | + else if (c.type == 'channel' && c.subscribed) | |
620 … | + return ' subscribed to channel <a href="/channel/' + c.channel + '">#' + c.channel + "</a>" | |
621 … | + else if (c.type == 'channel' && !c.subscribed) | |
622 … | + return ' unsubscribed from channel <a href="/channel/' + c.channel + '">#' + c.channel + "</a>" | |
623 … | + else | |
624 … | + return renderDefault(c) | |
625 … | +} | |
626 … | + | |
627 … | +function renderPost(opts, c) { | |
628 … | + if (c.root) | |
629 … | + return '<div class="ssb-post"> Re: <a href="/' + encodeURIComponent(c.root) + '">' + c.root.substring(0, 10) + '</a><br />' + marked(c.text, opts.marked) + '</div>' | |
630 … | + else return '<div class="ssb-post">' + marked(c.text, opts.marked) + '</div>' | |
631 … | +} | |
632 … | + | |
633 … | +function renderDefault(c) { | |
634 … | + return '<pre>' + JSON.stringify(c, 0, 2) + '</pre>' | |
635 … | +} | |
636 … | + |
plugins/viewer/lib/about.js | ||
---|---|---|
@@ -1,0 +1,31 @@ | ||
1 … | +var pull = require('pull-stream') | |
2 … | +var sort = require('ssb-sort') | |
3 … | + | |
4 … | +function linkDest(val) { | |
5 … | + return typeof val === 'string' ? val : val && val.link | |
6 … | +} | |
7 … | + | |
8 … | +function reduceAbout(about, msg) { | |
9 … | + var c = msg.value.content | |
10 … | + if (!c) return about | |
11 … | + if (c.name) about.name = c.name.replace(/^@?/, '@') | |
12 … | + if (c.image) about.image = linkDest(c.image) | |
13 … | + return about | |
14 … | +} | |
15 … | + | |
16 … | +module.exports = function (sbot, id, cb) { | |
17 … | + var about = {} | |
18 … | + pull( | |
19 … | + sbot.links({ | |
20 … | + rel: 'about', | |
21 … | + dest: id, | |
22 … | + values: true, | |
23 … | + }), | |
24 … | + pull.collect(function (err, msgs) { | |
25 … | + if (err) return cb(err) | |
26 … | + cb(null, sort(msgs).reduce(reduceAbout, { | |
27 … | + name: String(id).substr(0, 10) + '…', | |
28 … | + })) | |
29 … | + }) | |
30 … | + ) | |
31 … | +} |
plugins/viewer/static/base.css | ||
---|---|---|
@@ -1,0 +1,15 @@ | ||
1 … | +.ssb-timestamp { | |
2 … | + float: right; | |
3 … | +} | |
4 … | + | |
5 … | +.ssb-avatar-image { | |
6 … | + vertical-align: top; | |
7 … | +} | |
8 … | + | |
9 … | +.ssb-avatar-name { | |
10 … | + margin-left: 1ex; | |
11 … | +} | |
12 … | + | |
13 … | +.ssb-post img { | |
14 … | + max-width: 100%; | |
15 … | +} |
plugins/viewer/static/nicer.css | ||
---|---|---|
@@ -1,0 +1,47 @@ | ||
1 … | +* { | |
2 … | + word-wrap: break-word; | |
3 … | +} | |
4 … | + | |
5 … | + | |
6 … | +pre { | |
7 … | + height: auto; | |
8 … | + max-height: 200px; | |
9 … | + overflow: auto; | |
10 … | + background-color: #eeeeee; | |
11 … | + word-break: normal !important; | |
12 … | + word-wrap: normal !important; | |
13 … | + white-space: pre !important; | |
14 … | +} | |
15 … | + | |
16 … | +.ssb-message { | |
17 … | + border-bottom: 1px solid #ddd; | |
18 … | + margin: 1em 0; | |
19 … | +} | |
20 … | + | |
21 … | +h1, h2, h3, h4 { | |
22 … | + line-height: 1.2; | |
23 … | +} | |
24 … | + | |
25 … | +.ssb-thread { | |
26 … | + //width: 80ex; | |
27 … | + max-width: 100%; | |
28 … | + min-width: 57%; | |
29 … | + margin: 0 auto; | |
30 … | + line-height: 1.5; | |
31 … | + font-family: sans-serif; | |
32 … | +} | |
33 … | + | |
34 … | +.ssb-message:target { | |
35 … | + background-color: #fcfae8; | |
36 … | + padding: 1em 1em 0; | |
37 … | + margin: -1em -1em 0; | |
38 … | +} | |
39 … | +.ssb-message:target:first-child { | |
40 … | + margin-top: 0; | |
41 … | +} | |
42 … | + | |
43 … | +.ssb-emoji { | |
44 … | + height: 1em; | |
45 … | + width: 1em; | |
46 … | + vertical-align: top; | |
47 … | +} |
plugins/viewer/yarn.lock | ||
---|---|---|
@@ -1,0 +1,603 @@ | ||
1 … | +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. | |
2 … | +# yarn lockfile v1 | |
3 … | + | |
4 … | + | |
5 … | +asyncmemo@^1.0.0: | |
6 … | + version "1.0.0" | |
7 … | + resolved "https://registry.yarnpkg.com/asyncmemo/-/asyncmemo-1.0.0.tgz#ef249dc869d6c07e7dfd4a22c8a18850bb39d7f1" | |
8 … | + | |
9 … | +balanced-match@^1.0.0: | |
10 … | + version "1.0.0" | |
11 … | + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" | |
12 … | + | |
13 … | +brace-expansion@^1.1.7: | |
14 … | + version "1.1.8" | |
15 … | + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" | |
16 … | + dependencies: | |
17 … | + balanced-match "^1.0.0" | |
18 … | + concat-map "0.0.1" | |
19 … | + | |
20 … | +chloride-test@^1.1.0: | |
21 … | + version "1.2.2" | |
22 … | + resolved "https://registry.yarnpkg.com/chloride-test/-/chloride-test-1.2.2.tgz#178686a85e9278045112e96e8c791793f9a10aea" | |
23 … | + dependencies: | |
24 … | + json-buffer "^2.0.11" | |
25 … | + | |
26 … | +chloride@^2.2.1, chloride@^2.2.7: | |
27 … | + version "2.2.7" | |
28 … | + resolved "https://registry.yarnpkg.com/chloride/-/chloride-2.2.7.tgz#0e6a9d11894abe4a44911d3988da192e2208b786" | |
29 … | + dependencies: | |
30 … | + is-electron "^2.0.0" | |
31 … | + sodium-browserify "^1.0.3" | |
32 … | + sodium-browserify-tweetnacl "^0.2.0" | |
33 … | + sodium-chloride "^1.1.0" | |
34 … | + optionalDependencies: | |
35 … | + sodium-native "^1.10.0" | |
36 … | + | |
37 … | +concat-map@0.0.1: | |
38 … | + version "0.0.1" | |
39 … | + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" | |
40 … | + | |
41 … | +deep-equal@~1.0.0, deep-equal@~1.0.1: | |
42 … | + version "1.0.1" | |
43 … | + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" | |
44 … | + | |
45 … | +deep-extend@^0.4.0, deep-extend@~0.4.0: | |
46 … | + version "0.4.2" | |
47 … | + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" | |
48 … | + | |
49 … | +define-properties@^1.1.2: | |
50 … | + version "1.1.2" | |
51 … | + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" | |
52 … | + dependencies: | |
53 … | + foreach "^2.0.5" | |
54 … | + object-keys "^1.0.8" | |
55 … | + | |
56 … | +defined@~1.0.0: | |
57 … | + version "1.0.0" | |
58 … | + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" | |
59 … | + | |
60 … | +ed2curve@^0.1.4: | |
61 … | + version "0.1.4" | |
62 … | + resolved "https://registry.yarnpkg.com/ed2curve/-/ed2curve-0.1.4.tgz#94a44248bb87da35db0eff7af0aa576168117f59" | |
63 … | + dependencies: | |
64 … | + tweetnacl "0.x.x" | |
65 … | + | |
66 … | +emoji-named-characters@^1.0.2, emoji-named-characters@~1.0.2: | |
67 … | + version "1.0.2" | |
68 … | + resolved "https://registry.yarnpkg.com/emoji-named-characters/-/emoji-named-characters-1.0.2.tgz#cdeb36d0e66002c4b9d7bf1dfbc3a199fb7d409b" | |
69 … | + | |
70 … | +emoji-server@^1.0.0: | |
71 … | + version "1.0.0" | |
72 … | + resolved "https://registry.yarnpkg.com/emoji-server/-/emoji-server-1.0.0.tgz#d063cfee9af118cc5aeefbc2e9b3dd5085815c63" | |
73 … | + dependencies: | |
74 … | + emoji-named-characters "~1.0.2" | |
75 … | + | |
76 … | +es-abstract@^1.5.0: | |
77 … | + version "1.7.0" | |
78 … | + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.7.0.tgz#dfade774e01bfcd97f96180298c449c8623fb94c" | |
79 … | + dependencies: | |
80 … | + es-to-primitive "^1.1.1" | |
81 … | + function-bind "^1.1.0" | |
82 … | + is-callable "^1.1.3" | |
83 … | + is-regex "^1.0.3" | |
84 … | + | |
85 … | +es-to-primitive@^1.1.1: | |
86 … | + version "1.1.1" | |
87 … | + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" | |
88 … | + dependencies: | |
89 … | + is-callable "^1.1.1" | |
90 … | + is-date-object "^1.0.1" | |
91 … | + is-symbol "^1.0.1" | |
92 … | + | |
93 … | +explain-error@^1.0.1: | |
94 … | + version "1.0.4" | |
95 … | + resolved "https://registry.yarnpkg.com/explain-error/-/explain-error-1.0.4.tgz#a793d3ac0cad4c6ab571e9968fbbab6cb2532929" | |
96 … | + | |
97 … | +for-each@~0.3.2: | |
98 … | + version "0.3.2" | |
99 … | + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.2.tgz#2c40450b9348e97f281322593ba96704b9abd4d4" | |
100 … | + dependencies: | |
101 … | + is-function "~1.0.0" | |
102 … | + | |
103 … | +foreach@^2.0.5: | |
104 … | + version "2.0.5" | |
105 … | + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" | |
106 … | + | |
107 … | +fs.realpath@^1.0.0: | |
108 … | + version "1.0.0" | |
109 … | + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" | |
110 … | + | |
111 … | +function-bind@^1.0.2, function-bind@^1.1.0, function-bind@~1.1.0: | |
112 … | + version "1.1.0" | |
113 … | + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" | |
114 … | + | |
115 … | +glob@~7.1.1: | |
116 … | + version "7.1.2" | |
117 … | + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" | |
118 … | + dependencies: | |
119 … | + fs.realpath "^1.0.0" | |
120 … | + inflight "^1.0.4" | |
121 … | + inherits "2" | |
122 … | + minimatch "^3.0.4" | |
123 … | + once "^1.3.0" | |
124 … | + path-is-absolute "^1.0.0" | |
125 … | + | |
126 … | +has@^1.0.1, has@~1.0.1: | |
127 … | + version "1.0.1" | |
128 … | + resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" | |
129 … | + dependencies: | |
130 … | + function-bind "^1.0.2" | |
131 … | + | |
132 … | +human-time@^0.0.1: | |
133 … | + version "0.0.1" | |
134 … | + resolved "https://registry.yarnpkg.com/human-time/-/human-time-0.0.1.tgz#280d0336379199306b2e1518e3d5f6381cb8507d" | |
135 … | + | |
136 … | +increment-buffer@~1.0.0: | |
137 … | + version "1.0.1" | |
138 … | + resolved "https://registry.yarnpkg.com/increment-buffer/-/increment-buffer-1.0.1.tgz#65076d75189d808b39ad13ab5b958e05216f9e0d" | |
139 … | + | |
140 … | +inflight@^1.0.4: | |
141 … | + version "1.0.6" | |
142 … | + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" | |
143 … | + dependencies: | |
144 … | + once "^1.3.0" | |
145 … | + wrappy "1" | |
146 … | + | |
147 … | +inherits@2, inherits@^2.0.1, inherits@~2.0.3: | |
148 … | + version "2.0.3" | |
149 … | + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" | |
150 … | + | |
151 … | +ini@~1.3.0: | |
152 … | + version "1.3.4" | |
153 … | + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" | |
154 … | + | |
155 … | +ip@^1.1.2, ip@^1.1.3: | |
156 … | + version "1.1.5" | |
157 … | + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" | |
158 … | + | |
159 … | +ip@~0.3.2: | |
160 … | + version "0.3.3" | |
161 … | + resolved "https://registry.yarnpkg.com/ip/-/ip-0.3.3.tgz#8ee8309e92f0b040d287f72efaca1a21702d3fb4" | |
162 … | + | |
163 … | +is-callable@^1.1.1, is-callable@^1.1.3: | |
164 … | + version "1.1.3" | |
165 … | + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" | |
166 … | + | |
167 … | +is-date-object@^1.0.1: | |
168 … | + version "1.0.1" | |
169 … | + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" | |
170 … | + | |
171 … | +is-electron@^2.0.0: | |
172 … | + version "2.0.0" | |
173 … | + resolved "https://registry.yarnpkg.com/is-electron/-/is-electron-2.0.0.tgz#c82d3599640f7df91c84eaaee76bc56713c6ac79" | |
174 … | + | |
175 … | +is-function@~1.0.0: | |
176 … | + version "1.0.1" | |
177 … | + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" | |
178 … | + | |
179 … | +is-regex@^1.0.3: | |
180 … | + version "1.0.4" | |
181 … | + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" | |
182 … | + dependencies: | |
183 … | + has "^1.0.1" | |
184 … | + | |
185 … | +is-symbol@^1.0.1: | |
186 … | + version "1.0.1" | |
187 … | + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" | |
188 … | + | |
189 … | +is-valid-domain@~0.0.1: | |
190 … | + version "0.0.2" | |
191 … | + resolved "https://registry.yarnpkg.com/is-valid-domain/-/is-valid-domain-0.0.2.tgz#3e7a9423ff7c3b2fe11663afbd6d3837a251fb77" | |
192 … | + | |
193 … | +json-buffer@^2.0.11: | |
194 … | + version "2.0.11" | |
195 … | + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-2.0.11.tgz#3e441fda3098be8d1e3171ad591bc62a33e2d55f" | |
196 … | + | |
197 … | +libsodium-wrappers@^0.2.9: | |
198 … | + version "0.2.12" | |
199 … | + resolved "https://registry.yarnpkg.com/libsodium-wrappers/-/libsodium-wrappers-0.2.12.tgz#51fb50774b8edc517927b307b812a46c3a467e1e" | |
200 … | + dependencies: | |
201 … | + libsodium "0.2.12" | |
202 … | + | |
203 … | +libsodium@0.2.12: | |
204 … | + version "0.2.12" | |
205 … | + resolved "https://registry.yarnpkg.com/libsodium/-/libsodium-0.2.12.tgz#83083564dcf089cb82a5035be92ba5d224a2ccde" | |
206 … | + | |
207 … | +looper@^3.0.0, looper@~3.0.0: | |
208 … | + version "3.0.0" | |
209 … | + resolved "https://registry.yarnpkg.com/looper/-/looper-3.0.0.tgz#2efa54c3b1cbaba9b94aee2e5914b0be57fbb749" | |
210 … | + | |
211 … | +looper@^4.0.0: | |
212 … | + version "4.0.0" | |
213 … | + resolved "https://registry.yarnpkg.com/looper/-/looper-4.0.0.tgz#7706aded59a99edca06e6b54bb86c8ec19c95155" | |
214 … | + | |
215 … | +lrucache@^1.0.2: | |
216 … | + version "1.0.2" | |
217 … | + resolved "https://registry.yarnpkg.com/lrucache/-/lrucache-1.0.2.tgz#066e7072a2b3f8647993abc017d735a559b0ee5a" | |
218 … | + | |
219 … | +minimatch@^3.0.4: | |
220 … | + version "3.0.4" | |
221 … | + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" | |
222 … | + dependencies: | |
223 … | + brace-expansion "^1.1.7" | |
224 … | + | |
225 … | +minimist@0.0.8: | |
226 … | + version "0.0.8" | |
227 … | + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" | |
228 … | + | |
229 … | +minimist@^1.2.0, minimist@~1.2.0: | |
230 … | + version "1.2.0" | |
231 … | + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" | |
232 … | + | |
233 … | +mkdirp@~0.5.0: | |
234 … | + version "0.5.1" | |
235 … | + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" | |
236 … | + dependencies: | |
237 … | + minimist "0.0.8" | |
238 … | + | |
239 … | +multiserver@^1.7.0: | |
240 … | + version "1.9.1" | |
241 … | + resolved "https://registry.yarnpkg.com/multiserver/-/multiserver-1.9.1.tgz#f7dfa757aaaf6de2d64aa6853adbdb1ca884ab67" | |
242 … | + dependencies: | |
243 … | + pull-cat "~1.1.5" | |
244 … | + pull-stream "^3.4.3" | |
245 … | + pull-ws "^3.2.7" | |
246 … | + secret-handshake "^1.1.5" | |
247 … | + separator-escape "0.0.0" | |
248 … | + socks "1.1.9" | |
249 … | + stream-to-pull-stream "^1.7.2" | |
250 … | + | |
251 … | +muxrpc@^6.3.3: | |
252 … | + version "6.3.3" | |
253 … | + resolved "https://registry.yarnpkg.com/muxrpc/-/muxrpc-6.3.3.tgz#68ad940ef7f601df9da9ef2211b0a173d5286f9d" | |
254 … | + dependencies: | |
255 … | + explain-error "^1.0.1" | |
256 … | + packet-stream "~2.0.0" | |
257 … | + packet-stream-codec "^1.1.1" | |
258 … | + pull-goodbye "~0.0.1" | |
259 … | + pull-stream "^3.2.3" | |
260 … | + | |
261 … | +nan@^2.4.0: | |
262 … | + version "2.6.2" | |
263 … | + resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45" | |
264 … | + | |
265 … | +node-gyp-build@^3.0.0: | |
266 … | + version "3.2.0" | |
267 … | + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-3.2.0.tgz#283be074924aabb9240ce3f880c7ca0c8e7a00dc" | |
268 … | + | |
269 … | +non-private-ip@^1.2.1: | |
270 … | + version "1.4.2" | |
271 … | + resolved "https://registry.yarnpkg.com/non-private-ip/-/non-private-ip-1.4.2.tgz#ed51fa7bf7e91a9c632394f10547b6a395e8bead" | |
272 … | + dependencies: | |
273 … | + ip "~0.3.2" | |
274 … | + | |
275 … | +object-inspect@~1.2.1: | |
276 … | + version "1.2.2" | |
277 … | + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.2.2.tgz#c82115e4fcc888aea14d64c22e4f17f6a70d5e5a" | |
278 … | + | |
279 … | +object-keys@^1.0.8: | |
280 … | + version "1.0.11" | |
281 … | + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" | |
282 … | + | |
283 … | +once@^1.3.0: | |
284 … | + version "1.4.0" | |
285 … | + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" | |
286 … | + dependencies: | |
287 … | + wrappy "1" | |
288 … | + | |
289 … | +options@>=0.0.5: | |
290 … | + version "0.0.6" | |
291 … | + resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" | |
292 … | + | |
293 … | +os-homedir@^1.0.1: | |
294 … | + version "1.0.2" | |
295 … | + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" | |
296 … | + | |
297 … | +packet-stream-codec@^1.1.1: | |
298 … | + version "1.1.2" | |
299 … | + resolved "https://registry.yarnpkg.com/packet-stream-codec/-/packet-stream-codec-1.1.2.tgz#79b302fc144cdfbb4ab6feba7040e6a5d99c79c7" | |
300 … | + dependencies: | |
301 … | + pull-reader "^1.2.4" | |
302 … | + pull-through "^1.0.17" | |
303 … | + | |
304 … | +packet-stream@~2.0.0: | |
305 … | + version "2.0.2" | |
306 … | + resolved "https://registry.yarnpkg.com/packet-stream/-/packet-stream-2.0.2.tgz#b90b7f9bab4a962422cbc9cb24719c353e493267" | |
307 … | + | |
308 … | +path-is-absolute@^1.0.0: | |
309 … | + version "1.0.1" | |
310 … | + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" | |
311 … | + | |
312 … | +private-box@^0.2.1: | |
313 … | + version "0.2.1" | |
314 … | + resolved "https://registry.yarnpkg.com/private-box/-/private-box-0.2.1.tgz#1df061afca5b3039c7feaadd0daf0f56f07e3ec0" | |
315 … | + dependencies: | |
316 … | + chloride "^2.2.1" | |
317 … | + | |
318 … | +pull-box-stream@^1.0.13: | |
319 … | + version "1.0.13" | |
320 … | + resolved "https://registry.yarnpkg.com/pull-box-stream/-/pull-box-stream-1.0.13.tgz#c3e240398eab3f5951b2ed1078c5988bf7a0a2b9" | |
321 … | + dependencies: | |
322 … | + chloride "^2.2.7" | |
323 … | + increment-buffer "~1.0.0" | |
324 … | + pull-reader "^1.2.5" | |
325 … | + pull-stream "^3.2.3" | |
326 … | + pull-through "^1.0.18" | |
327 … | + split-buffer "~1.0.0" | |
328 … | + | |
329 … | +pull-cat@^1.1.11, pull-cat@^1.1.9, pull-cat@~1.1.5: | |
330 … | + version "1.1.11" | |
331 … | + resolved "https://registry.yarnpkg.com/pull-cat/-/pull-cat-1.1.11.tgz#b642dd1255da376a706b6db4fa962f5fdb74c31b" | |
332 … | + | |
333 … | +pull-goodbye@~0.0.1: | |
334 … | + version "0.0.2" | |
335 … | + resolved "https://registry.yarnpkg.com/pull-goodbye/-/pull-goodbye-0.0.2.tgz#8d8357db55e22a710dfff0f16a8c90b45efe4171" | |
336 … | + dependencies: | |
337 … | + pull-stream "~3.5.0" | |
338 … | + | |
339 … | +pull-handshake@^1.1.1: | |
340 … | + version "1.1.4" | |
341 … | + resolved "https://registry.yarnpkg.com/pull-handshake/-/pull-handshake-1.1.4.tgz#6000a0fd018884cdfd737254f8cc60ab2a637791" | |
342 … | + dependencies: | |
343 … | + pull-cat "^1.1.9" | |
344 … | + pull-pair "~1.1.0" | |
345 … | + pull-pushable "^2.0.0" | |
346 … | + pull-reader "^1.2.3" | |
347 … | + | |
348 … | +pull-pair@~1.1.0: | |
349 … | + version "1.1.0" | |
350 … | + resolved "https://registry.yarnpkg.com/pull-pair/-/pull-pair-1.1.0.tgz#7ee427263fdf4da825397ac0a05e1ab4b74bd76d" | |
351 … | + | |
352 … | +pull-paramap@^1.2.1: | |
353 … | + version "1.2.2" | |
354 … | + resolved "https://registry.yarnpkg.com/pull-paramap/-/pull-paramap-1.2.2.tgz#51a4193ce9c8d7215d95adad45e2bcdb8493b23a" | |
355 … | + dependencies: | |
356 … | + looper "^4.0.0" | |
357 … | + | |
358 … | +pull-pushable@^2.0.0: | |
359 … | + version "2.1.1" | |
360 … | + resolved "https://registry.yarnpkg.com/pull-pushable/-/pull-pushable-2.1.1.tgz#86666abbe3f5402f1f7ead03eefd69b785eca5b8" | |
361 … | + | |
362 … | +pull-reader@^1.2.3, pull-reader@^1.2.4, pull-reader@^1.2.5: | |
363 … | + version "1.2.9" | |
364 … | + resolved "https://registry.yarnpkg.com/pull-reader/-/pull-reader-1.2.9.tgz#d2e9ad00bcfb54e62aa66d42c2dbbcb5eb6843b0" | |
365 … | + | |
366 … | +pull-stream@^3.2.3, pull-stream@^3.4.3, pull-stream@^3.4.5, pull-stream@^3.5.0: | |
367 … | + version "3.6.0" | |
368 … | + resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.6.0.tgz#59d033a6815d4e3097d47c3d2b1893a9e58a2351" | |
369 … | + | |
370 … | +pull-stream@~3.5.0: | |
371 … | + version "3.5.0" | |
372 … | + resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.5.0.tgz#1ee5b6f76fd3b3a49a5afb6ded5c0320acb3cfc7" | |
373 … | + | |
374 … | +pull-through@^1.0.17, pull-through@^1.0.18: | |
375 … | + version "1.0.18" | |
376 … | + resolved "https://registry.yarnpkg.com/pull-through/-/pull-through-1.0.18.tgz#8dd62314263e59cf5096eafbb127a2b6ef310735" | |
377 … | + dependencies: | |
378 … | + looper "~3.0.0" | |
379 … | + | |
380 … | +pull-ws@^3.2.7: | |
381 … | + version "3.2.9" | |
382 … | + resolved "https://registry.yarnpkg.com/pull-ws/-/pull-ws-3.2.9.tgz#8a90502a41d9058fcb3096ad4823a0f189d613ba" | |
383 … | + dependencies: | |
384 … | + relative-url "^1.0.2" | |
385 … | + ws "^1.1.0" | |
386 … | + | |
387 … | +rc@^1.1.6: | |
388 … | + version "1.2.1" | |
389 … | + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95" | |
390 … | + dependencies: | |
391 … | + deep-extend "~0.4.0" | |
392 … | + ini "~1.3.0" | |
393 … | + minimist "^1.2.0" | |
394 … | + strip-json-comments "~2.0.1" | |
395 … | + | |
396 … | +relative-url@^1.0.2: | |
397 … | + version "1.0.2" | |
398 … | + resolved "https://registry.yarnpkg.com/relative-url/-/relative-url-1.0.2.tgz#d21c52a72d6061018bcee9f9c9fc106bf7d65287" | |
399 … | + | |
400 … | +resolve@~1.1.7: | |
401 … | + version "1.1.7" | |
402 … | + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" | |
403 … | + | |
404 … | +resumer@~0.0.0: | |
405 … | + version "0.0.0" | |
406 … | + resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" | |
407 … | + dependencies: | |
408 … | + through "~2.3.4" | |
409 … | + | |
410 … | +secret-handshake@^1.1.5: | |
411 … | + version "1.1.11" | |
412 … | + resolved "https://registry.yarnpkg.com/secret-handshake/-/secret-handshake-1.1.11.tgz#239d613678f1e5c50f223f2605f36475cefd665e" | |
413 … | + dependencies: | |
414 … | + chloride "^2.2.7" | |
415 … | + deep-equal "~1.0.0" | |
416 … | + pull-box-stream "^1.0.13" | |
417 … | + pull-handshake "^1.1.1" | |
418 … | + pull-stream "^3.4.5" | |
419 … | + | |
420 … | +separator-escape@0.0.0: | |
421 … | + version "0.0.0" | |
422 … | + resolved "https://registry.yarnpkg.com/separator-escape/-/separator-escape-0.0.0.tgz#e433676932020454e3c14870c517ea1de56c2fa4" | |
423 … | + | |
424 … | +sha.js@2.4.5: | |
425 … | + version "2.4.5" | |
426 … | + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.5.tgz#27d171efcc82a118b99639ff581660242b506e7c" | |
427 … | + dependencies: | |
428 … | + inherits "^2.0.1" | |
429 … | + | |
430 … | +sha.js@^2.4.8: | |
431 … | + version "2.4.8" | |
432 … | + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.8.tgz#37068c2c476b6baf402d14a49c67f597921f634f" | |
433 … | + dependencies: | |
434 … | + inherits "^2.0.1" | |
435 … | + | |
436 … | +smart-buffer@^1.0.4: | |
437 … | + version "1.1.15" | |
438 … | + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-1.1.15.tgz#7f114b5b65fab3e2a35aa775bb12f0d1c649bf16" | |
439 … | + | |
440 … | +socks@1.1.9: | |
441 … | + version "1.1.9" | |
442 … | + resolved "https://registry.yarnpkg.com/socks/-/socks-1.1.9.tgz#628d7e4d04912435445ac0b6e459376cb3e6d691" | |
443 … | + dependencies: | |
444 … | + ip "^1.1.2" | |
445 … | + smart-buffer "^1.0.4" | |
446 … | + | |
447 … | +sodium-browserify-tweetnacl@^0.2.0: | |
448 … | + version "0.2.3" | |
449 … | + resolved "https://registry.yarnpkg.com/sodium-browserify-tweetnacl/-/sodium-browserify-tweetnacl-0.2.3.tgz#b5537ffcbb9f74ebc443b8b6a211b291e8fcbc8e" | |
450 … | + dependencies: | |
451 … | + chloride-test "^1.1.0" | |
452 … | + ed2curve "^0.1.4" | |
453 … | + sha.js "^2.4.8" | |
454 … | + tweetnacl "^0.14.1" | |
455 … | + tweetnacl-auth "^0.3.0" | |
456 … | + | |
457 … | +sodium-browserify@^1.0.3: | |
458 … | + version "1.2.1" | |
459 … | + resolved "https://registry.yarnpkg.com/sodium-browserify/-/sodium-browserify-1.2.1.tgz#b0b559ca36981679085214855e26645df67aaf1c" | |
460 … | + dependencies: | |
461 … | + libsodium-wrappers "^0.2.9" | |
462 … | + sha.js "2.4.5" | |
463 … | + tweetnacl "^0.14.1" | |
464 … | + | |
465 … | +sodium-chloride@^1.1.0: | |
466 … | + version "1.1.0" | |
467 … | + resolved "https://registry.yarnpkg.com/sodium-chloride/-/sodium-chloride-1.1.0.tgz#247a234b88867f6dff51332b605f193a65bf6839" | |
468 … | + | |
469 … | +sodium-native@^1.10.0: | |
470 … | + version "1.10.1" | |
471 … | + resolved "https://registry.yarnpkg.com/sodium-native/-/sodium-native-1.10.1.tgz#95876693b336c51d4a9a4ea1ccc7a048bbb3e373" | |
472 … | + dependencies: | |
473 … | + nan "^2.4.0" | |
474 … | + node-gyp-build "^3.0.0" | |
475 … | + | |
476 … | +split-buffer@~1.0.0: | |
477 … | + version "1.0.0" | |
478 … | + resolved "https://registry.yarnpkg.com/split-buffer/-/split-buffer-1.0.0.tgz#b7e8e0ab51345158b72c1f6dbef2406d51f1d027" | |
479 … | + | |
480 … | +ssb-avatar@^0.2.0: | |
481 … | + version "0.2.0" | |
482 … | + resolved "https://registry.yarnpkg.com/ssb-avatar/-/ssb-avatar-0.2.0.tgz#06cd70795ee58d1462d100a45c660df3179d3b39" | |
483 … | + dependencies: | |
484 … | + pull-cat "^1.1.9" | |
485 … | + pull-stream "^3.4.3" | |
486 … | + ssb-msgs "^5.2.0" | |
487 … | + ssb-ref "^2.3.2" | |
488 … | + | |
489 … | +ssb-client@^4.4.0: | |
490 … | + version "4.4.1" | |
491 … | + resolved "https://registry.yarnpkg.com/ssb-client/-/ssb-client-4.4.1.tgz#aa0914c1ef0747fc360bc19defce2cebfaff4115" | |
492 … | + dependencies: | |
493 … | + explain-error "^1.0.1" | |
494 … | + multiserver "^1.7.0" | |
495 … | + muxrpc "^6.3.3" | |
496 … | + ssb-config "^2.0.0" | |
497 … | + ssb-keys "^7.0.9" | |
498 … | + | |
499 … | +ssb-config@^2.0.0: | |
500 … | + version "2.2.0" | |
501 … | + resolved "https://registry.yarnpkg.com/ssb-config/-/ssb-config-2.2.0.tgz#41cad038a8575af4062d3fd57d3b167be85b03bc" | |
502 … | + dependencies: | |
503 … | + deep-extend "^0.4.0" | |
504 … | + non-private-ip "^1.2.1" | |
505 … | + os-homedir "^1.0.1" | |
506 … | + rc "^1.1.6" | |
507 … | + | |
508 … | +ssb-keys@^7.0.9: | |
509 … | + version "7.0.9" | |
510 … | + resolved "https://registry.yarnpkg.com/ssb-keys/-/ssb-keys-7.0.9.tgz#06b6eb57784757266ced1a8c6d077cf81a0825f8" | |
511 … | + dependencies: | |
512 … | + chloride "^2.2.7" | |
513 … | + mkdirp "~0.5.0" | |
514 … | + private-box "^0.2.1" | |
515 … | + | |
516 … | +ssb-marked@^0.7.2: | |
517 … | + version "0.7.2" | |
518 … | + resolved "https://registry.yarnpkg.com/ssb-marked/-/ssb-marked-0.7.2.tgz#160e24113782a9ca5e806072aa7a65e7c865dbf2" | |
519 … | + | |
520 … | +ssb-msgs@^5.2.0: | |
521 … | + version "5.2.0" | |
522 … | + resolved "https://registry.yarnpkg.com/ssb-msgs/-/ssb-msgs-5.2.0.tgz#c681da5cd70c574c922dca4f03c521538135c243" | |
523 … | + dependencies: | |
524 … | + ssb-ref "^2.0.0" | |
525 … | + | |
526 … | +ssb-ref@^2.0.0, ssb-ref@^2.3.0, ssb-ref@^2.3.2, ssb-ref@^2.6.2: | |
527 … | + version "2.7.1" | |
528 … | + resolved "https://registry.yarnpkg.com/ssb-ref/-/ssb-ref-2.7.1.tgz#5d4effc545ec0ffd7fc15ba27829a640b8a2afba" | |
529 … | + dependencies: | |
530 … | + ip "^1.1.3" | |
531 … | + is-valid-domain "~0.0.1" | |
532 … | + | |
533 … | +ssb-sort@^1.0.0: | |
534 … | + version "1.0.0" | |
535 … | + resolved "https://registry.yarnpkg.com/ssb-sort/-/ssb-sort-1.0.0.tgz#8e9956f50752d2b158247b06e49c3f491c1cd27b" | |
536 … | + dependencies: | |
537 … | + ssb-ref "^2.3.0" | |
538 … | + | |
539 … | +stream-to-pull-stream@^1.7.2: | |
540 … | + version "1.7.2" | |
541 … | + resolved "https://registry.yarnpkg.com/stream-to-pull-stream/-/stream-to-pull-stream-1.7.2.tgz#757609ae1cebd33c7432d4afbe31ff78650b9dde" | |
542 … | + dependencies: | |
543 … | + looper "^3.0.0" | |
544 … | + pull-stream "^3.2.3" | |
545 … | + | |
546 … | +string.prototype.trim@~1.1.2: | |
547 … | + version "1.1.2" | |
548 … | + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" | |
549 … | + dependencies: | |
550 … | + define-properties "^1.1.2" | |
551 … | + es-abstract "^1.5.0" | |
552 … | + function-bind "^1.0.2" | |
553 … | + | |
554 … | +strip-json-comments@~2.0.1: | |
555 … | + version "2.0.1" | |
556 … | + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" | |
557 … | + | |
558 … | +tape@^4.6.2: | |
559 … | + version "4.6.3" | |
560 … | + resolved "https://registry.yarnpkg.com/tape/-/tape-4.6.3.tgz#637e77581e9ab2ce17577e9bd4ce4f575806d8b6" | |
561 … | + dependencies: | |
562 … | + deep-equal "~1.0.1" | |
563 … | + defined "~1.0.0" | |
564 … | + for-each "~0.3.2" | |
565 … | + function-bind "~1.1.0" | |
566 … | + glob "~7.1.1" | |
567 … | + has "~1.0.1" | |
568 … | + inherits "~2.0.3" | |
569 … | + minimist "~1.2.0" | |
570 … | + object-inspect "~1.2.1" | |
571 … | + resolve "~1.1.7" | |
572 … | + resumer "~0.0.0" | |
573 … | + string.prototype.trim "~1.1.2" | |
574 … | + through "~2.3.8" | |
575 … | + | |
576 … | +through@~2.3.4, through@~2.3.8: | |
577 … | + version "2.3.8" | |
578 … | + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" | |
579 … | + | |
580 … | +tweetnacl-auth@^0.3.0: | |
581 … | + version "0.3.1" | |
582 … | + resolved "https://registry.yarnpkg.com/tweetnacl-auth/-/tweetnacl-auth-0.3.1.tgz#b75bc2df15649bb84e8b9aa3c0669c6c4bce0d25" | |
583 … | + dependencies: | |
584 … | + tweetnacl "0.x.x" | |
585 … | + | |
586 … | +tweetnacl@0.x.x, tweetnacl@^0.14.1: | |
587 … | + version "0.14.5" | |
588 … | + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" | |
589 … | + | |
590 … | +ultron@1.0.x: | |
591 … | + version "1.0.2" | |
592 … | + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" | |
593 … | + | |
594 … | +wrappy@1: | |
595 … | + version "1.0.2" | |
596 … | + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" | |
597 … | + | |
598 … | +ws@^1.1.0: | |
599 … | + version "1.1.4" | |
600 … | + resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.4.tgz#57f40d036832e5f5055662a397c4de76ed66bf61" | |
601 … | + dependencies: | |
602 … | + options ">=0.0.5" | |
603 … | + ultron "1.0.x" |
yarn.lock | ||
---|---|---|
The diff is too large to show. Use a local git client to view these changes. Old file size: 104384 bytes New file size: 104890 bytes |
Built with git-ssb-web