138 lines
3.5 KiB
JavaScript
138 lines
3.5 KiB
JavaScript
|
'use strict'
|
||
|
var emojiNamedCharacters = require('emoji-named-characters')
|
||
|
var marked = require('ssb-marked')
|
||
|
var ssbref = require('ssb-ref')
|
||
|
var mlib = require('ssb-msgs')
|
||
|
|
||
|
var renderer = new marked.Renderer();
|
||
|
|
||
|
// override to only allow external links or hashes, and correctly link to ssb objects
|
||
|
renderer.urltransform = function (url) {
|
||
|
var c = url.charAt(0)
|
||
|
var hasSigil = (c == '@' || c == '&' || c == '%')
|
||
|
|
||
|
if (this.options.sanitize && !hasSigil) {
|
||
|
try {
|
||
|
var prot = decodeURIComponent(unescape(url))
|
||
|
.replace(/[^\w:]/g, '')
|
||
|
.toLowerCase();
|
||
|
} catch (e) {
|
||
|
return false;
|
||
|
}
|
||
|
if (prot.indexOf('javascript:') === 0) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var islink = ssbref.isLink(url)
|
||
|
if (hasSigil && !islink && this.options.mentionNames) {
|
||
|
// do a name lookup
|
||
|
url = this.options.mentionNames[url.slice(1)]
|
||
|
if (!url)
|
||
|
return false
|
||
|
islink = true
|
||
|
}
|
||
|
|
||
|
if (islink) {
|
||
|
if (ssbref.isFeedId(url))
|
||
|
return '#/profile/'+url
|
||
|
else if (ssbref.isMsgId(url))
|
||
|
return '#/msg/'+url
|
||
|
else if (ssbref.isBlobId(url))
|
||
|
return '#/webview/'+url
|
||
|
}
|
||
|
else if (url.indexOf('http') !== 0) {
|
||
|
return false;
|
||
|
}
|
||
|
return url
|
||
|
}
|
||
|
|
||
|
// override to make http/s links external
|
||
|
renderer.link = function(href, title, text) {
|
||
|
href = this.urltransform(href)
|
||
|
var out
|
||
|
if (href !== false)
|
||
|
out = '<a href="' + href + '"';
|
||
|
else
|
||
|
out = '<a class="bad"'
|
||
|
if (title) {
|
||
|
out += ' title="' + title + '"';
|
||
|
}
|
||
|
|
||
|
// make a popup if http/s
|
||
|
if (href && href.indexOf('http') === 0)
|
||
|
out += ' target="_blank"'
|
||
|
|
||
|
out += '>' + text + '</a>';
|
||
|
return out;
|
||
|
};
|
||
|
|
||
|
// override to support <video> tags (HACK)
|
||
|
renderer.image = function (href, title, text) {
|
||
|
href = href.replace(/^&/, '&')
|
||
|
if (ssbref.isLink(href)) {
|
||
|
if ((''+text).indexOf('.webm') >= 0) {
|
||
|
var out = '<video autoplay=1 loop=1 muted=1 src="http://localhost:7777/' + href + '?fallback=video" alt="' + text + '"'
|
||
|
if (title) {
|
||
|
out += ' title="' + title + '"'
|
||
|
}
|
||
|
out += '></video>'
|
||
|
} else {
|
||
|
var out = '<a href="#/webview/' + href + '"><img src="http://localhost:7777/' + href + '?fallback=img" alt="' + text + '"'
|
||
|
if (title) {
|
||
|
out += ' title="' + title + '"'
|
||
|
}
|
||
|
out += '></a>'
|
||
|
}
|
||
|
return out
|
||
|
}
|
||
|
return text
|
||
|
}
|
||
|
|
||
|
marked.setOptions({
|
||
|
gfm: true,
|
||
|
mentions: true,
|
||
|
tables: true,
|
||
|
breaks: true,
|
||
|
pedantic: false,
|
||
|
sanitize: true,
|
||
|
smartLists: true,
|
||
|
smartypants: false,
|
||
|
emoji: renderEmoji,
|
||
|
renderer: renderer
|
||
|
});
|
||
|
|
||
|
exports.block = function(text, mentionNames) {
|
||
|
if (mentionNames && mentionNames.key && mentionNames.value) {
|
||
|
// is a message, get the mentions links
|
||
|
mentionNames = mlib.links(mentionNames.value.content.mentions, 'feed')
|
||
|
}
|
||
|
if (Array.isArray(mentionNames)) {
|
||
|
// is an array of links, turn into an object map
|
||
|
var n = {}
|
||
|
mentionNames.forEach(function (link) {
|
||
|
n[link.name] = link.link
|
||
|
})
|
||
|
mentionNames = n
|
||
|
}
|
||
|
|
||
|
return marked(''+(text||''), { mentionNames: mentionNames })
|
||
|
}
|
||
|
|
||
|
var emojiRegex = /(\s|>|^)?:([A-z0-9_]+):(\s|<|$)/g;
|
||
|
exports.emojis = function (str) {
|
||
|
return str.replace(emojiRegex, function(full, $1, $2, $3) {
|
||
|
return ($1||'') + renderEmoji($2) + ($3||'')
|
||
|
})
|
||
|
}
|
||
|
|
||
|
function renderEmoji (emoji) {
|
||
|
return emoji in emojiNamedCharacters ?
|
||
|
'<img src="./img/emoji/' + encodeURI(emoji) + '.png"'
|
||
|
+ ' alt=":' + escape(emoji) + ':"'
|
||
|
+ ' title=":' + escape(emoji) + ':"'
|
||
|
+ ' class="emoji" align="absmiddle" height="20" width="20">'
|
||
|
: ':' + emoji + ':'
|
||
|
}
|
||
|
|