154 lines
2.8 KiB
JavaScript
154 lines
2.8 KiB
JavaScript
'use strict'
|
|
|
|
var decode = require('parse-entities')
|
|
var whitespace = require('is-whitespace-character')
|
|
var locate = require('../locate/url')
|
|
|
|
module.exports = url
|
|
url.locator = locate
|
|
url.notInLink = true
|
|
|
|
var quotationMark = '"'
|
|
var apostrophe = "'"
|
|
var leftParenthesis = '('
|
|
var rightParenthesis = ')'
|
|
var comma = ','
|
|
var dot = '.'
|
|
var colon = ':'
|
|
var semicolon = ';'
|
|
var lessThan = '<'
|
|
var atSign = '@'
|
|
var leftSquareBracket = '['
|
|
var rightSquareBracket = ']'
|
|
|
|
var http = 'http://'
|
|
var https = 'https://'
|
|
var mailto = 'mailto:'
|
|
|
|
var protocols = [http, https, mailto]
|
|
|
|
var protocolsLength = protocols.length
|
|
|
|
function url(eat, value, silent) {
|
|
var self = this
|
|
var subvalue
|
|
var content
|
|
var character
|
|
var index
|
|
var position
|
|
var protocol
|
|
var match
|
|
var length
|
|
var queue
|
|
var parenCount
|
|
var nextCharacter
|
|
var tokenizers
|
|
var exit
|
|
|
|
if (!self.options.gfm) {
|
|
return
|
|
}
|
|
|
|
subvalue = ''
|
|
index = -1
|
|
|
|
while (++index < protocolsLength) {
|
|
protocol = protocols[index]
|
|
match = value.slice(0, protocol.length)
|
|
|
|
if (match.toLowerCase() === protocol) {
|
|
subvalue = match
|
|
break
|
|
}
|
|
}
|
|
|
|
if (!subvalue) {
|
|
return
|
|
}
|
|
|
|
index = subvalue.length
|
|
length = value.length
|
|
queue = ''
|
|
parenCount = 0
|
|
|
|
while (index < length) {
|
|
character = value.charAt(index)
|
|
|
|
if (whitespace(character) || character === lessThan) {
|
|
break
|
|
}
|
|
|
|
if (
|
|
character === dot ||
|
|
character === comma ||
|
|
character === colon ||
|
|
character === semicolon ||
|
|
character === quotationMark ||
|
|
character === apostrophe ||
|
|
character === rightParenthesis ||
|
|
character === rightSquareBracket
|
|
) {
|
|
nextCharacter = value.charAt(index + 1)
|
|
|
|
if (!nextCharacter || whitespace(nextCharacter)) {
|
|
break
|
|
}
|
|
}
|
|
|
|
if (character === leftParenthesis || character === leftSquareBracket) {
|
|
parenCount++
|
|
}
|
|
|
|
if (character === rightParenthesis || character === rightSquareBracket) {
|
|
parenCount--
|
|
|
|
if (parenCount < 0) {
|
|
break
|
|
}
|
|
}
|
|
|
|
queue += character
|
|
index++
|
|
}
|
|
|
|
if (!queue) {
|
|
return
|
|
}
|
|
|
|
subvalue += queue
|
|
content = subvalue
|
|
|
|
if (protocol === mailto) {
|
|
position = queue.indexOf(atSign)
|
|
|
|
if (position === -1 || position === length - 1) {
|
|
return
|
|
}
|
|
|
|
content = content.substr(mailto.length)
|
|
}
|
|
|
|
/* istanbul ignore if - never used (yet) */
|
|
if (silent) {
|
|
return true
|
|
}
|
|
|
|
exit = self.enterLink()
|
|
|
|
// Temporarily remove all tokenizers except text in url.
|
|
tokenizers = self.inlineTokenizers
|
|
self.inlineTokenizers = {text: tokenizers.text}
|
|
|
|
content = self.tokenizeInline(content, eat.now())
|
|
|
|
self.inlineTokenizers = tokenizers
|
|
exit()
|
|
|
|
return eat(subvalue)({
|
|
type: 'link',
|
|
title: null,
|
|
url: decode(subvalue, {nonTerminated: false}),
|
|
children: content
|
|
})
|
|
}
|