git ssb

2+

Dominic / yap



Tree: feb9d3ba55bb5896bdc42c4579acc0780735f4dc

Files: feb9d3ba55bb5896bdc42c4579acc0780735f4dc / util.js

6165 bytesRaw
1var URL = require('url')
2var QS = require('qs')
3var hyperscript = require('hyperscript')
4var cpara = require('cont').para
5var pull = require('pull-stream')
6var paramap = require('pull-paramap')
7var nested = require('libnested')
8var renderer = require('ssb-markdown')
9var ref = require('ssb-ref')
10var htmlEscape = require('html-escape')
11function isFunction (f) {
12 return 'function' === typeof f
13}
14
15var isArray = Array.isArray
16
17function isEmpty (e) {
18 for(var k in e) return false
19 return true
20}
21
22function isString (s) {
23 return 'string' === typeof s
24}
25
26function cleanOpts (opts) {
27 return (function copy (opts) {
28 var o = undefined
29 if(opts && 'object' === typeof opts)
30 for(var k in opts) {
31 if('undefined' !== typeof opts[k]) {
32 var v = copy(opts[k])
33 if('undefined' !== typeof v) {
34 o = o || {}
35 o[k] = v
36 }
37 }
38 }
39 else
40 return opts //a string, or other value
41 return o
42 })(opts)
43}
44
45function encodeOpts (opts) {
46 opts = cleanOpts(opts)
47 return opts ? '?'+QS.stringify(opts) : ''
48}
49
50exports.cleanOpts = cleanOpts
51
52exports.toUrl = function toUrl(path, opts) {
53 return '/'+(
54 Array.isArray(path) ? path.join('/') : ''+path
55 ) + encodeOpts(opts)
56}
57exports.h = function () {
58 return [].slice.call(arguments)
59}
60
61function toCont (f) {
62 if(f.length === 1) return function (cb) {
63 f(function (err, hs) {
64 exports.toHTML(hs)(cb)
65 })
66 }
67 else if(f.length === 2)
68 return function (cb) {
69 pull(
70 f,
71 paramap(function (e, cb) {
72 exports.toHTML(e)(cb)
73 }, 32),
74 pull.collect(cb)
75 )
76 }
77}
78
79function flatten (a) {
80 var _a = []
81 for(var i = 0; i < a.length; i++)
82 if(isArray(a[i]) && !isString(a[i][0]))
83 _a = _a.concat(flatten(a[i]))
84 else
85 _a.push(a[i])
86 return _a
87}
88
89
90//even better would be streaming html,
91//not just into arrays.
92var k = 0
93exports.toHTML = function toHTML (hs) {
94 return function (cb) {
95 if(!isFunction(cb)) throw new Error('cb must be a function, was:'+cb)
96 var called = false
97 var C = (
98 isFunction(hs) ? toCont(hs)
99 : isArray(hs) ? cpara(hs.map(toHTML))
100 : function (cb) {
101 if(!called) {
102 called = true
103 cb(null, hs)
104 }
105 else
106 throw new Error('called twice')
107 }
108 )
109
110 C(function (err, val) {
111 if(err) cb(err)
112 else if(isArray(val) && isString(val[0])) {
113 cb(null, hyperscript.apply(null, flatten(val)))
114 } else
115 cb(null, val)
116 })
117 }
118}
119
120exports.createHiddenInputs = function createHiddenInputs (meta, _path) {
121 _path = _path ? [].concat(_path) : []
122 var hidden = []
123 nested.each(meta, function (value, path) {
124 if(value !== undefined)
125 hidden.push(['input', {
126 name: _path.concat(path).map(function (e) { return '['+e+']' }).join(''),
127 value: value,
128 type: 'hidden'
129 }])
130 }, true)
131 return hidden
132}
133
134var cacheId = exports.cacheId = function (id) {
135 if('string' === typeof id)
136 return '_'+Buffer.from(id.substring(1, 12), 'base64').toString('hex')
137 else
138 return 'R'+id.lte+'-'+(id.lte - id.gte)
139}
140exports.cacheTag = function (url, id, time) {
141 if(time)
142 return ['link', {
143 rel: 'partial-refresh', href: url, id: cacheId(id), 'data-cache': ''+time
144 }]
145}
146
147
148function renderEmoji (emoji, url) {
149 if (!url) return ':' + emoji + ':'
150 return `
151 <img
152 src="${htmlEscape(url)}"
153 alt=":${htmlEscape(emoji)}:"
154 title=":${htmlEscape(emoji)}:"
155 class="emoji"
156 >
157 `
158}
159
160//copied from patchwork
161exports.markdown = function markdown (content) {
162 if (typeof content === 'string') { content = { text: content } }
163 var mentions = {}
164 var typeLookup = {}
165 var emojiMentions = {}
166 if (Array.isArray(content.mentions)) {
167 content.mentions.forEach(function (link) {
168 if (link && link.link && link.type) {
169 typeLookup[link.link] = link.type
170 }
171 if (link && link.name && link.link) {
172 if (link.emoji) {
173 // handle custom emoji
174 emojiMentions[link.name] = link.link
175 } else {
176 // handle old-style patchwork v2 mentions (deprecated)
177 mentions['@' + link.name] = link.link
178 }
179 }
180 })
181 }
182
183 var blobsUrl = '/blobs/get/'
184 var emojiUrl = '/img/emoji/'
185
186 function id2Url (id) {
187 return (
188 ref.isMsg(id) ? '/thread?id='+encodeURIComponent(id)
189 : ref.isBlobLink(id) ? blobsUrl+encodeURIComponent(id)
190 : ref.isFeed(id) ? '/public?author='+encodeURIComponent(id)
191 : id[0] == '#' ? '/public?channel='+id.substring(1)
192 : id
193 )
194 }
195
196 return ['div.Markdown', {
197 innerHTML: renderer.block(content.text, {
198 emoji: (emoji) => {
199 var url = emojiMentions[emoji]
200 ? blobsUrl + emojiMentions[emoji]
201 : emojiUrl + emoji + '.png'
202 return renderEmoji(emoji, url)
203 },
204 toUrl: (id) => {
205 var link = ref.parseLink(id)
206 if (link && ref.isBlob(link.link)) {
207 var url = blobsUrl+link.link
208 var query = {}
209 if (link.query && link.query.unbox) query['unbox'] = link.query.unbox
210 if (typeLookup[link.link]) query['contentType'] = typeLookup[link.link]
211 return url + '?' + QS.stringify(query)
212 } else if (link || id.startsWith('#') || id.startsWith('?')) {
213 return id2Url(id)
214 } else if (mentions[id]) {
215 // handle old-style patchwork v2 mentions (deprecated)
216 return id2Url(mentions[id])
217 }
218 return false
219 },
220 imageLink: function (id) {
221 return id2Url(id)
222 }
223 })
224 }]
225}
226
227exports.createRenderer = function (render) {
228 return function (sbot) {
229 return function (opts, apply) {
230 if(opts.id && ref.isMsgLink(opts.id))
231 return function (cb) {
232 sbot.get({id:opts.id, private: true}, function (err, msg) {
233 if(err) return cb(err)
234 var data = {key: opts.id, value: msg, timestamp: msg.timestamp || Date.now() }
235 cb(null, render(data, apply))
236 })
237 }
238 else if(opts.key && opts.value)
239 return render(opts, apply)
240 }
241 }
242}
243
244
245
246
247
248
249
250
251
252
253
254

Built with git-ssb-web