You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

153 lines
2.7 KiB

/**
* @author Titus Wormer
* @copyright 2015 Titus Wormer
* @license MIT
* @module remark:parse:tokenize:url
* @fileoverview Tokenise a URL.
*/
'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 C_BRACKET_OPEN = '[';
var C_BRACKET_CLOSE = ']';
var C_PAREN_OPEN = '(';
var C_PAREN_CLOSE = ')';
var C_LT = '<';
var C_AT_SIGN = '@';
var HTTP_PROTOCOL = 'http://';
var HTTPS_PROTOCOL = 'https://';
var MAILTO_PROTOCOL = 'mailto:';
var PROTOCOLS = [
HTTP_PROTOCOL,
HTTPS_PROTOCOL,
MAILTO_PROTOCOL
];
var PROTOCOLS_LENGTH = PROTOCOLS.length;
/* Tokenise a URL. */
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 exit;
if (!self.options.gfm) {
return;
}
subvalue = '';
index = -1;
length = PROTOCOLS_LENGTH;
while (++index < length) {
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 === C_LT) {
break;
}
if (
character === '.' ||
character === ',' ||
character === ':' ||
character === ';' ||
character === '"' ||
character === '\'' ||
character === ')' ||
character === ']'
) {
nextCharacter = value.charAt(index + 1);
if (!nextCharacter || whitespace(nextCharacter)) {
break;
}
}
if (character === C_PAREN_OPEN || character === C_BRACKET_OPEN) {
parenCount++;
}
if (character === C_PAREN_CLOSE || character === C_BRACKET_CLOSE) {
parenCount--;
if (parenCount < 0) {
break;
}
}
queue += character;
index++;
}
if (!queue) {
return;
}
subvalue += queue;
content = subvalue;
if (protocol === MAILTO_PROTOCOL) {
position = queue.indexOf(C_AT_SIGN);
if (position === -1 || position === length - 1) {
return;
}
content = content.substr(MAILTO_PROTOCOL.length);
}
/* istanbul ignore if - never used (yet) */
if (silent) {
return true;
}
exit = self.enterLink();
content = self.tokenizeInline(content, eat.now());
exit();
return eat(subvalue)({
type: 'link',
title: null,
url: decode(subvalue),
children: content
});
}