Tweak/rewrite Linkify.
This commit is contained in:
parent
58531319ca
commit
6d5f422c3f
@ -2,91 +2,73 @@ 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
|
||||
# gruber revised + magnet support
|
||||
# http://rodneyrehm.de/t/url-regex.html
|
||||
@catchAll = /\b([a-z][\w-]+:(\/{1,3}|[a-z0-9%]|\?(dn|x[lts]|as|kt|mt|tr)=)|www\d{0,3}\.|[a-z0-9.\-]+\.[a-z]{2,4}\/)([^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])/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.surround 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
|
||||
if Conf['Clean Links']
|
||||
{parentNode} = node
|
||||
if parentNode.nodeName is 'S' and parentNode.textContent.length < link.length
|
||||
$.replace parentNode, node
|
||||
continue unless start[...link.length] is link
|
||||
endIndex = link[start.length - data.length...].length
|
||||
walker.currentNode = Linkify.surround anchor, link, index, endIndex, startNode, node
|
||||
anchor = false
|
||||
return if @isClone or !links = @info.comment.match Linkify.catchAll
|
||||
walker = d.createTreeWalker @nodes.comment, 4
|
||||
for link in links
|
||||
boundaries = Linkify.find link, walker
|
||||
# continue unless boundaries
|
||||
anchor = Linkify.createLink link
|
||||
if Linkify.surround anchor, link, boundaries
|
||||
Linkify.cleanLink anchor if Conf['Clean Links']
|
||||
walker.currentNode = anchor.lastChild
|
||||
else
|
||||
walker.currentNode = boundaries.endNode
|
||||
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]
|
||||
find: (link, walker) ->
|
||||
# Walk through the nodes until we find the entire link.
|
||||
text = ''
|
||||
while node = walker.nextNode()
|
||||
{data} = node
|
||||
text += node.data
|
||||
if text.indexOf(link) > -1
|
||||
startNode = endNode = node
|
||||
break
|
||||
|
||||
surround: (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
|
||||
# Walk backwards to find the startNode.
|
||||
text = data
|
||||
until (index = text.indexOf link) > -1
|
||||
startNode = walker.previousNode()
|
||||
text = "#{startNode.data}#{text}"
|
||||
|
||||
return {
|
||||
startNode, endNode
|
||||
startOffset: index
|
||||
endOffset: endNode.length - (text.length - index - link.length)
|
||||
}
|
||||
|
||||
createLink: (link) ->
|
||||
unless /^[a-z][\w-]+:/.test link
|
||||
link = "http://#{link}"
|
||||
a = $.el 'a',
|
||||
href: link
|
||||
target: '_blank'
|
||||
a
|
||||
|
||||
surround: (anchor, link, {startOffset, endOffset, startNode, endNode}) ->
|
||||
# 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
|
||||
range.setStart startNode, startOffset
|
||||
range.setEnd endNode, endOffset
|
||||
try
|
||||
range.surroundContents anchor
|
||||
if !Conf['Clean Links'] and parentClone and anchor.firstChild
|
||||
$.replace anchor.firstChild, parentClone
|
||||
endNode
|
||||
# if !Conf['Clean Links'] and parentClone and anchor.firstChild
|
||||
# $.replace anchor.firstChild, parentClone
|
||||
true
|
||||
catch
|
||||
false
|
||||
|
||||
cleanLink: (anchor) ->
|
||||
# TODO
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user