git ssb

30+

cel / git-ssb-web



Tree: 227a1624073790b244e01bf9e1efc9429a6e0feb

Files: 227a1624073790b244e01bf9e1efc9429a6e0feb / lib / util.js

6313 bytesRaw
1var pull = require('pull-stream')
2var h = require('pull-hyperscript')
3var paramap = require('pull-paramap')
4var Highlight = require('highlight.js')
5var removeMd = require('remove-markdown')
6var u = exports
7
8u.imgMimes = {
9 png: 'image/png',
10 jpeg: 'image/jpeg',
11 jpg: 'image/jpeg',
12 gif: 'image/gif',
13 tif: 'image/tiff',
14 svg: 'image/svg+xml',
15 xcf: 'image/x-xcf',
16 ico: 'image/x-icon',
17 bmp: 'image/bmp'
18}
19
20u.getExtension = function(filename) {
21 var m = /\.([^.]+)$/.exec(filename)
22 return m && m[1]
23}
24
25u.readNext = function (fn) {
26 var next
27 return function (end, cb) {
28 if (next) return next(end, cb)
29 fn(function (err, _next) {
30 if (err) return cb(err)
31 next = _next
32 next(null, cb)
33 })
34 }
35}
36
37u.readOnce = function (fn) {
38 var ended
39 return function (end, cb) {
40 fn(function (err, data) {
41 if (err || ended) return cb(err || ended)
42 ended = true
43 cb(null, data)
44 })
45 }
46}
47
48u.when = function (bool, elFunction) {
49 return bool
50 ? elFunction()
51 : pull.once('')
52}
53
54u.sourceMap = function (source, fn) {
55 return pull(
56 source,
57 pull.filter(Boolean),
58 pull.map(fn)
59 )
60}
61
62u.paraSourceMap = function paraSourceMap (source, fn) {
63 return pull(
64 pull.values(source),
65 paramap(fn, 8)
66 )
67}
68
69u.escape = function (str) {
70 return String(str)
71 .replace(/&/g, '&')
72 .replace(/</g, '&lt;')
73 .replace(/>/g, '&gt;')
74 .replace(/"/g, '&quot;')
75}
76
77u.encodeLink = function (url) {
78 if (!Array.isArray(url)) url = [url]
79 return '/' + url.map(encodeURIComponent).join('/')
80}
81
82u.link = function (parts, text, raw, props) {
83 if (text == null) text = parts[parts.length-1]
84 if (!raw) text = u.escape(text)
85 return '<a href="' + u.encodeLink(parts) + '"' +
86 (props ? ' ' + props : '') +
87 '>' + text + '</a>'
88}
89
90u.timestamp = function (time, req) {
91 time = Number(time)
92 var d = new Date(time)
93 return '<span title="' + time + '">' +
94 d.toLocaleString(req._locale) + '</span>'
95}
96
97u.nav = function (links, page, after) {
98 return h('nav', [
99 u.sourceMap(pull.values(links), link => {
100 return h('a', {
101 href: (typeof link[0] == 'string') ? link[0] : u.encodeLink(link[0]),
102 class: (link[2] == page) ? 'active' : ''
103 },
104 link[1])
105 }),
106 pull.once(after || '')
107 ])
108}
109
110u.hiddenInputs = function (values) {
111 return Object.keys(values).map(function (key) {
112 return '<input type="hidden"' +
113 ' name="' + u.escape(key) + '"' +
114 ' value="' + u.escape(values[key]) + '"/>'
115 }).join('')
116}
117
118u.highlight = function(code, lang) {
119 if (!lang && /^#!\/bin\/[^\/]*sh$/m.test(code)) lang = 'sh'
120 if (!lang || code.length > 100000) return u.escape(code)
121 // auto highlighting removed because it was causing highlight.js to hang
122 try {
123 return Highlight.highlight(lang, code).value
124 } catch(e) {
125 if (!/^Unknown language:/.test(e.message)) console.error('highlight:', e)
126 return u.escape(code)
127 }
128}
129
130u.pre = function (text) {
131 return '<pre>' + u.escape(text) + '</pre>'
132}
133
134u.json = function (obj) {
135 return u.linkify(u.pre(JSON.stringify(obj, null, 2)))
136}
137
138u.linkify = function (text) {
139 // regex is from ssb-ref
140 return text.replace(/(@|%|&|&amp;)[A-Za-z0-9\/+]{43}=\.[\w\d]+/g, function (str) {
141 return '<a href="/' + str + '">' + str + '</a>'
142 })
143}
144
145u.readObjectString = function (obj, cb) {
146 pull(obj.read, pull.collect(function (err, bufs) {
147 if (err) return cb(err)
148 cb(null, Buffer.concat(bufs, obj.length).toString('utf8'))
149 }))
150}
151
152u.pullReverse = function () {
153 return function (read) {
154 return u.readNext(function (cb) {
155 pull(read, pull.collect(function (err, items) {
156 cb(err, items && pull.values(items.reverse()))
157 }))
158 })
159 }
160}
161
162function compareMsgs(a, b) {
163 return (a.value.timestamp - b.value.timestamp) || (a.key - b.key)
164}
165
166u.pullSort = function (comparator, descending) {
167 return function (read) {
168 return u.readNext(function (cb) {
169 pull(read, pull.collect(function (err, items) {
170 if (err) return cb(err)
171 items.sort(comparator)
172 if (descending) items.reverse()
173 cb(null, pull.values(items))
174 }))
175 })
176 }
177}
178
179u.sortMsgs = function (descending) {
180 return u.pullSort(compareMsgs, descending)
181}
182
183u.truncate = function (str, len) {
184 str = String(str)
185 return str.length < len ? str : str.substr(0, len) + '…'
186}
187
188u.messageTitle = function (msg) {
189 var c = msg.value.content
190 return u.truncate(c.title || c.text || msg.key, 40)
191}
192
193u.ifModifiedSince = function (req, lastMod) {
194 var ifModSince = req.headers['if-modified-since']
195 if (!ifModSince) return false
196 var d = new Date(ifModSince)
197 return d && Math.floor(d/1000) >= Math.floor(lastMod/1000)
198}
199
200u.decryptMessage = function (sbot, msg, cb) {
201 var c = msg && msg.value && msg.value.content
202 if (sbot.private && c && typeof c === 'string' && c.slice(-4) === '.box') {
203 sbot.private.unbox(msg.value.content, function (err, content) {
204 if (err || !content) return cb(null, msg) // leave message encrypted
205 var msg1 = {}
206 for (var k in msg) msg1[k] = msg[k]
207 msg1.value = {}
208 msg1.private = true
209 for (var j in msg.value) msg1.value[j] = msg.value[j]
210 msg1.value.private = true
211 msg1.value.content = content
212 if (!content.recps) {
213 sbot.whoami(function (err, feed) {
214 if (err) return cb(err)
215 content.recps = [msg1.value.author]
216 if (feed.id !== msg1.value.author) content.recps.push(feed.id)
217 cb(null, msg1)
218 })
219 } else cb(null, msg1)
220 })
221 } else cb(null, msg)
222}
223
224u.isMessageReadable = function (msg) {
225 return msg && msg.value && msg.value.content
226 && typeof msg.value.content === 'object'
227}
228
229u.readableMessages = function () {
230 return pull.filter(u.isMessageReadable)
231}
232
233u.decryptMessages = function (sbot) {
234 return paramap(function (msg, cb) {
235 u.decryptMessage(sbot, msg, cb)
236 }, 4)
237}
238
239u.formatMarkdownTitle = function (title) {
240 return u.escape(removeMd(title))
241}
242
243u.privateIcon = function (req) {
244 return `<img src="/emoji/lock.png" height="16" width="16" alt="${req._t('repo.Private')}" title="${req._t('repo.RepoIsPrivate')}">`
245}
246
247u.msgIdToDomId = function (id) {
248 return 'msg-' + id.replace(/^%/, '')
249 .replace(/\+/g, '-')
250 .replace(/\//g, '_')
251 .replace(/=/g, '')
252}
253

Built with git-ssb-web