Files: 428676644191b3fcf658e49167d835bb682488a2 / message / html / markdown.js
2416 bytesRaw
1 | const renderer = require('ssb-markdown') |
2 | const h = require('mutant/h') |
3 | const ref = require('ssb-ref') |
4 | const nest = require('depnest') |
5 | var htmlEscape = require('html-escape') |
6 | var watch = require('mutant/watch') |
7 | |
8 | exports.needs = nest({ |
9 | 'blob.sync.url': 'first', |
10 | 'blob.obs.has': 'first', |
11 | 'emoji.sync.url': 'first' |
12 | }) |
13 | |
14 | exports.gives = nest('message.html.markdown') |
15 | |
16 | exports.create = function (api) { |
17 | return nest('message.html.markdown', markdown) |
18 | |
19 | function markdown (content) { |
20 | if (typeof content === 'string') { content = {text: content} } |
21 | // handle patchwork style mentions and custom emoji. |
22 | var mentions = {} |
23 | var emojiMentions = {} |
24 | if (Array.isArray(content.mentions)) { |
25 | content.mentions.forEach(function (link) { |
26 | if (link && link.name && link.link) { |
27 | if (link.emoji) emojiMentions[link.name] = link.link |
28 | else mentions['@' + link.name] = link.link |
29 | } |
30 | }) |
31 | } |
32 | |
33 | return h('Markdown', { |
34 | hooks: [ |
35 | LoadingBlobHook(api.blob.obs.has) |
36 | ], |
37 | innerHTML: renderer.block(content.text, { |
38 | emoji: (emoji) => { |
39 | var url = emojiMentions[emoji] |
40 | ? api.blob.sync.url(emojiMentions[emoji]) |
41 | : api.emoji.sync.url(emoji) |
42 | return renderEmoji(emoji, url) |
43 | }, |
44 | toUrl: (id) => { |
45 | if (ref.isBlob(id)) return api.blob.sync.url(id) |
46 | if (mentions[id]) { |
47 | return mentions[id] |
48 | } else if (ref.isLink(id) || id.startsWith('#') || id.startsWith('?')) { |
49 | return id |
50 | } |
51 | return false |
52 | }, |
53 | imageLink: (id) => id |
54 | }) |
55 | }) |
56 | } |
57 | |
58 | function renderEmoji (emoji, url) { |
59 | if (!url) return ':' + emoji + ':' |
60 | return ` |
61 | <img |
62 | src="${htmlEscape(url)}" |
63 | alt=":${htmlEscape(emoji)}:" |
64 | title=":${htmlEscape(emoji)}:" |
65 | class="emoji" |
66 | > |
67 | ` |
68 | } |
69 | } |
70 | |
71 | function LoadingBlobHook (hasBlob) { |
72 | return function (element) { |
73 | var releases = [] |
74 | element.querySelectorAll('img').forEach(img => { |
75 | var id = ref.extract(img.src) |
76 | if (id) { |
77 | releases.push(watch(hasBlob(id), has => { |
78 | if (has === false) { |
79 | img.classList.add('-pending') |
80 | } else { |
81 | img.classList.remove('-pending') |
82 | } |
83 | })) |
84 | } |
85 | }) |
86 | return function () { |
87 | while (releases.length) { |
88 | releases.pop()() |
89 | } |
90 | } |
91 | } |
92 | } |
93 |
Built with git-ssb-web