Add Linkification.
This commit is contained in:
parent
a1e8d1a924
commit
202d7617e3
@ -31,6 +31,7 @@ module.exports = (grunt) ->
|
|||||||
'src/Quotelinks/**/*'
|
'src/Quotelinks/**/*'
|
||||||
'src/Posting/**/*'
|
'src/Posting/**/*'
|
||||||
'src/Images/**/*'
|
'src/Images/**/*'
|
||||||
|
'src/Linkification/**/*'
|
||||||
'src/Menu/**/*'
|
'src/Menu/**/*'
|
||||||
'src/Monitoring/**/*'
|
'src/Monitoring/**/*'
|
||||||
'src/Archive/**/*'
|
'src/Archive/**/*'
|
||||||
|
|||||||
@ -27,6 +27,9 @@ Config =
|
|||||||
'Image Hover': [false, 'Show a floating expanded image on hover.']
|
'Image Hover': [false, 'Show a floating expanded image on hover.']
|
||||||
'Sauce': [true, 'Add sauce links to images.']
|
'Sauce': [true, 'Add sauce links to images.']
|
||||||
'Reveal Spoilers': [false, 'Reveal spoiler thumbnails.']
|
'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':
|
||||||
'Menu': [true, 'Add a drop-down menu to posts.']
|
'Menu': [true, 'Add a drop-down menu to posts.']
|
||||||
'Report Link': [true, 'Add a report link to the menu.']
|
'Report Link': [true, 'Add a report link to the menu.']
|
||||||
|
|||||||
@ -128,6 +128,7 @@ Main =
|
|||||||
initFeature 'Index Navigation', Nav
|
initFeature 'Index Navigation', Nav
|
||||||
initFeature 'Keybinds', Keybinds
|
initFeature 'Keybinds', Keybinds
|
||||||
initFeature 'Show Dice Roll', Dice
|
initFeature 'Show Dice Roll', Dice
|
||||||
|
initFeature 'Linkify', Linkify
|
||||||
# c.timeEnd 'All initializations'
|
# c.timeEnd 'All initializations'
|
||||||
|
|
||||||
$.on d, 'AddCallback', Main.addCallback
|
$.on d, 'AddCallback', Main.addCallback
|
||||||
|
|||||||
92
src/Linkification/Linkify.coffee
Normal file
92
src/Linkification/Linkify.coffee
Normal 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
|
||||||
@ -72,3 +72,5 @@ ExpandComment =
|
|||||||
Fourchan.code.call post
|
Fourchan.code.call post
|
||||||
if g.BOARD.ID is 'sci'
|
if g.BOARD.ID is 'sci'
|
||||||
Fourchan.math.call post
|
Fourchan.math.call post
|
||||||
|
if Conf['Linkify']
|
||||||
|
Linkify.node.call post
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user