Files: ea522127885486018de1547de0db04f3d3144eb6 / lib / util.js
6879 bytesRaw
1 | var pull = require('pull-stream') |
2 | var cat = require('pull-cat') |
3 | var h = require('hyperscript') |
4 | var b64url = require('base64-url') |
5 | var u = exports |
6 | |
7 | u.ssbRefRegex = /((?:@|%|&|ssb:\/\/%)[A-Za-z0-9\/+]{43}=\.[\w\d]+)/g |
8 | u.ssbRefRegexOnly = /^(?:@|%|&|ssb:\/\/%)[A-Za-z0-9\/+]{43}=\.[\w\d]+$/ |
9 | u.ssbRefEncRegex = /((?:ssb:\/\/)?(?:[@%&]|%26|%40|%25)(?:[A-Za-z0-9\/+]|%2[fF]|%2[bB]){43}(?:=|%3[dD])\.[\w\d]+)/g |
10 | |
11 | u.isRef = function (str) { |
12 | if (!str) return false |
13 | u.ssbRefRegexOnly.lastIndex = 0 |
14 | return u.ssbRefRegexOnly.test(str) |
15 | } |
16 | |
17 | u.readNext = function (fn) { |
18 | var next |
19 | return function (end, cb) { |
20 | if (next) return next(end, cb) |
21 | fn(function (err, _next) { |
22 | if (err) return cb(err) |
23 | next = _next |
24 | next(null, cb) |
25 | }) |
26 | } |
27 | } |
28 | |
29 | u.pullReverse = function () { |
30 | return function (read) { |
31 | return u.readNext(function (cb) { |
32 | pull(read, pull.collect(function (err, items) { |
33 | cb(err, items && pull.values(items.reverse())) |
34 | })) |
35 | }) |
36 | } |
37 | } |
38 | |
39 | u.toHTML = function (el) { |
40 | if (!el) return '' |
41 | if (typeof el === 'string' || Array.isArray(el)) { |
42 | return h('div', el).innerHTML |
43 | } |
44 | var html = el.outerHTML || String(el) |
45 | if (el.nodeName === 'html') html = '<!doctype html>' + html + '\n' |
46 | return html |
47 | } |
48 | |
49 | u.hyperwrap = function (fn) { |
50 | var token = '__HYPERWRAP_' + Math.random() + '__' |
51 | return function (read) { |
52 | return u.readNext(function (cb) { |
53 | fn(token, function (err, el) { |
54 | if (err) return cb(err) |
55 | var parts = u.toHTML(el).split(token) |
56 | switch (parts.length) { |
57 | case 0: return cb(null, pull.empty()) |
58 | case 1: return cb(null, pull.once(parts[0])) |
59 | case 2: return cb(null, |
60 | cat([pull.once(parts[0]), read, pull.once(parts[1])])) |
61 | default: return cb(new Error('duplicate wrap')) |
62 | } |
63 | }) |
64 | }) |
65 | } |
66 | } |
67 | |
68 | u.ifString = function (str) { |
69 | if (typeof str === 'string') return str |
70 | } |
71 | |
72 | u.ifNumber = function (num) { |
73 | if (!isNaN(num)) return num |
74 | } |
75 | |
76 | u.toLink = function (link) { |
77 | return typeof link === 'string' ? {link: link} : link || null |
78 | } |
79 | |
80 | u.linkDest = function (link) { |
81 | return link && (u.ifString(link) || u.ifString(link.link)) |
82 | } |
83 | |
84 | u.toArray = function (x) { |
85 | return x == null ? [] : Array.isArray(x) ? x : [x] |
86 | } |
87 | |
88 | u.fromArray = function (arr) { |
89 | return Array.isArray(arr) && arr.length === 1 ? arr[0] : arr |
90 | } |
91 | |
92 | u.toLinkArray = function (x) { |
93 | return u.toArray(x).map(u.toLink).filter(u.linkDest) |
94 | } |
95 | |
96 | u.renderError = function(err) { |
97 | return h('div.error', |
98 | h('h3', err.name), |
99 | h('pre', err.stack)) |
100 | } |
101 | |
102 | u.pullLength = function (cb) { |
103 | var len = 0 |
104 | return pull.through(function (data) { |
105 | len += data.length |
106 | }, function (err) { |
107 | cb(err, len) |
108 | }) |
109 | } |
110 | |
111 | u.tryDecodeJSON = function (json) { |
112 | try { |
113 | return JSON.parse(json) |
114 | } catch(e) { |
115 | return null |
116 | } |
117 | } |
118 | |
119 | u.extractRefs = function (str) { |
120 | var ids = [] |
121 | String(str).replace(u.ssbRefRegex, function (id) { |
122 | ids.push(id) |
123 | }) |
124 | return ids |
125 | } |
126 | |
127 | u.extractFeedIds = function (str) { |
128 | return u.extractRefs(str).filter(function (ref) { |
129 | return ref[0] === '@' |
130 | }) |
131 | } |
132 | |
133 | u.extractBlobIds = function (str) { |
134 | return u.extractRefs(str).filter(function (ref) { |
135 | return ref[0] === '&' |
136 | }) |
137 | } |
138 | |
139 | u.isMsgReadable = function (msg) { |
140 | var c = msg && msg.value && msg.value.content |
141 | return typeof c === 'object' && c !== null |
142 | } |
143 | |
144 | u.isMsgEncrypted = function (msg) { |
145 | var value = msg && msg.value |
146 | return value && (value.private || typeof value.content === 'string') |
147 | } |
148 | |
149 | u.pullConcat = function (cb) { |
150 | return pull.collect(function (err, bufs) { |
151 | if (err) return cb(err) |
152 | cb(null, Buffer.concat(bufs)) |
153 | }) |
154 | } |
155 | |
156 | u.customError = function (name) { |
157 | return function (message) { |
158 | var error = new Error(message) |
159 | error.name = name |
160 | error.stack = error.stack.replace(/^ at .*\n/m, '') |
161 | return error |
162 | } |
163 | } |
164 | |
165 | u.escapeHTML = function (html) { |
166 | if (!html) return '' |
167 | return html.toString('utf8') |
168 | .replace(/&/g, '&') |
169 | .replace(/"/g, '"') |
170 | .replace(/</g, '<') |
171 | .replace(/>/g, '>') |
172 | .replace(/\n/g, '
') |
173 | } |
174 | |
175 | u.unescapeHTML = function (text) { |
176 | if (typeof text !== 'string') return text |
177 | return text.replace(/&/g, '&') |
178 | .replace(/"/g, '"') |
179 | .replace(/'/g, '\'') |
180 | .replace(/>/g, '>') |
181 | .replace(/</g, '<') |
182 | } |
183 | |
184 | u.pullSlice = function (start, end) { |
185 | if (end == null) end = Infinity |
186 | var offset = 0 |
187 | return function (read) { |
188 | return function (abort, cb) { |
189 | if (abort) read(abort, cb) |
190 | else if (offset >= end) read(true, function (err) { |
191 | cb(err || true) |
192 | }) |
193 | else if (offset < start) read(null, function next(err, data) { |
194 | if (err) return cb(err) |
195 | offset += data.length |
196 | if (offset <= start) read(null, next) |
197 | else if (offset < end) cb(null, |
198 | data.slice(data.length - (offset - start))) |
199 | else cb(null, data.slice(data.length - (offset - start), |
200 | data.length - (offset - end))) |
201 | }) |
202 | else read(null, function (err, data) { |
203 | if (err) return cb(err) |
204 | offset += data.length |
205 | if (offset <= end) cb(null, data) |
206 | else cb(null, data.slice(0, data.length - (offset - end))) |
207 | }) |
208 | } |
209 | } |
210 | } |
211 | |
212 | u.mergeOpts = function (a, b) { |
213 | var obj = {}, k |
214 | for (k in a) { |
215 | obj[k] = a[k] |
216 | } |
217 | for (k in b) { |
218 | if (b[k] != null) obj[k] = b[k] |
219 | else delete obj[k] |
220 | } |
221 | return obj |
222 | } |
223 | |
224 | u.escapeId = function (id) { |
225 | return b64url.escape(id) |
226 | } |
227 | |
228 | u.unescapeId = function (str) { |
229 | var m = /^(.)(.*)(\..*)$/.exec(str) |
230 | if (!m) return b64url.unescape(str) |
231 | return m[1] + b64url.unescape(m[2]) + m[3] |
232 | } |
233 | |
234 | u.rows = function (str) { |
235 | return String(str).split(/[^\n]{150}|\n/).length |
236 | } |
237 | |
238 | u.token = function () { |
239 | return '__' + Math.random().toString(36).substr(2) + '__' |
240 | } |
241 | |
242 | u.unwrapP = function(html) { |
243 | return String(html).replace(/^<p>(.*)<\/p>\s*$/, function ($0, $1) { |
244 | return $1 |
245 | }) |
246 | } |
247 | |
248 | u.estimateMessageSize = function (content) { |
249 | var draftMsg = { |
250 | key: '%0000000000000000000000000000000000000000000=.sha256', |
251 | value: { |
252 | previous: '%0000000000000000000000000000000000000000000=.sha256', |
253 | author: '@0000000000000000000000000000000000000000000=.ed25519', |
254 | sequence: 10000, |
255 | timestamp: 1000000000000, |
256 | hash: 'sha256', |
257 | content: content, |
258 | signature: '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000==.sig.ed25519' |
259 | } |
260 | } |
261 | |
262 | return JSON.stringify(draftMsg, null, 2).length |
263 | } |
264 | |
265 | u.truncate = function (str, len) { |
266 | str = String(str) |
267 | return str.length > len ? str.substr(0, len) + '...' : str |
268 | } |
269 | |
270 | u.extractHostPort = function (id, addr) { |
271 | var i = addr.lastIndexOf(':' + id) |
272 | if (i > -1 && addr.length === i + id.length + 1) { |
273 | return addr.substr(0, i) |
274 | } |
275 | var m = /^(?:net|onion):([^~;]*(?::[0-9]*)?)~shs:([0-9a-zA-Z/=+]{44})$/.exec(addr) |
276 | if (m && id === '@' + m[2] + '.ed25519') { |
277 | return m[1] |
278 | } |
279 | return addr |
280 | } |
281 |
Built with git-ssb-web