Add Linkification.

This commit is contained in:
noface 2013-06-18 19:42:42 +02:00 committed by Mayhem
parent a1e8d1a924
commit 202d7617e3
5 changed files with 99 additions and 0 deletions

View File

@ -31,6 +31,7 @@ module.exports = (grunt) ->
'src/Quotelinks/**/*'
'src/Posting/**/*'
'src/Images/**/*'
'src/Linkification/**/*'
'src/Menu/**/*'
'src/Monitoring/**/*'
'src/Archive/**/*'

View File

@ -27,6 +27,9 @@ Config =
'Image Hover': [false, 'Show a floating expanded image on hover.']
'Sauce': [true, 'Add sauce links to images.']
'Reveal Spoilers': [false, 'Reveal spoiler thumbnails.']
'Linkification':
'Linkify': [true, 'Convert text links into hyperlinks.']
'Clean Links': [true, 'Remove spoiler texts commonly used to bypass banned links.']
'Menu':
'Menu': [true, 'Add a drop-down menu to posts.']
'Report Link': [true, 'Add a report link to the menu.']

View File

@ -128,6 +128,7 @@ Main =
initFeature 'Index Navigation', Nav
initFeature 'Keybinds', Keybinds
initFeature 'Show Dice Roll', Dice
initFeature 'Linkify', Linkify
# c.timeEnd 'All initializations'
$.on d, 'AddCallback', Main.addCallback

View File

@ -0,0 +1,92 @@
Linkify =
init: ->
return if g.VIEW is 'catalog' or !Conf['Linkify']
@catchAll = /\b(?:([a-z][\w-]+):(?:\/{1,3}|[a-z0-9%]|(\?(?:dn|xl|xt|as|xs|kt|mt|tr)=))|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\((?:[^\s()<>]+|(?:\([^\s()<>]+\)))*\))+(?:\((?:[^\s()<>]+|(?:\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])/i
@globalCatchAll = ///#{@catchAll.source}///g
Post::callbacks.push
name: 'Linkify'
cb: @node
node: ->
return if @isClone or !links = @info.comment.match Linkify.globalCatchAll
walker = d.createTreeWalker @nodes.comment, 4, null, false
anchor = false
while (node = walker.nextNode())?
{parentNode} = node
if parentNode.nodeName is 'A'
# prettyprint has some issues
if parentNode.textContent is links[0]
delete links[0]
walker.currentNode = parentNode.lastChild
continue
continue unless data = node.data
while !anchor
return unless link = links.shift()
[anchor, link] = Linkify.parseLink link
if data.length >= link.length and (index = data.indexOf link) >= 0
walker.currentNode = Linkify.sourround anchor, link, index, index + link.length, node
anchor = false
continue
index = found = 0
nextContent = node.nextSibling?.textContent
while index isnt data.length
start = data[index++..]
startLength = start.length
threshold = startLength is 2
if threshold and nextContent and link[...startLength + nextContent.length] is start + nextContent
found = true
if threshold or found = link[...startLength] is start
index--
break
continue unless found
startNode = node
while start.length < link.length
start += data = (node = walker.nextNode())?.data
{parentNode} = node
if parentNode.nodeName is 'S' and Conf['Clean Links']
$.replace parentNode, node
continue unless start[...link.length] is link
endIndex = link[start.length - data.length...].length
walker.currentNode = Linkify.sourround anchor, link, index, endIndex, startNode, node
anchor = false
return
parseLink: (link) ->
unless result = link.match @catchAll
return false
[link, protocol, isMagnet] = result
try
decodeURIComponent link
catch
return false
target = if isMagnet or /^(irc|ftps?)$/.test protocol
'_self'
else
'_blank'
href = if protocol
link
else
"http://#{link}"
anchor = $.el 'a',
target: target
href: href
rel: 'noreferrer'
[anchor, link]
sourround: (anchor, link, startIndex, endIndex, startNode, endNode = startNode) ->
parent = startNode.parentNode
if parent?.nodeName is 'S' and parent.textContent.length < link.length
parentClone = parent.cloneNode true
$.replace parent, startNode
range = d.createRange()
range.setStart startNode, startIndex
range.setEnd endNode, endIndex
try
range.surroundContents anchor
if !Conf['Clean Links'] and parentClone and anchor.firstChild
$.replace anchor.firstChild, parentClone
catch
endNode

View File

@ -72,3 +72,5 @@ ExpandComment =
Fourchan.code.call post
if g.BOARD.ID is 'sci'
Fourchan.math.call post
if Conf['Linkify']
Linkify.node.call post