mirror of https://github.com/lukechilds/node.git
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
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
|
|
});
|
|
}
|
|
|