@mapbox/jsxtreme-markdown
Version:
Transform Markdown into JSX or React component modules
134 lines (106 loc) • 2.52 kB
JavaScript
'use strict';
var whitespace = require('is-whitespace-character');
var decode = require('parse-entities');
var locate = require('../locate/tag');
module.exports = autoLink;
autoLink.locator = locate;
autoLink.notInLink = true;
var lessThan = '<';
var greaterThan = '>';
var atSign = '@';
var slash = '/';
var mailto = 'mailto:';
var mailtoLength = mailto.length;
function autoLink(eat, value, silent) {
var self = this;
var subvalue = '';
var length = value.length;
var index = 0;
var queue = '';
var hasAtCharacter = false;
var link = '';
var character;
var now;
var content;
var tokenizers;
var exit;
if (value.charAt(0) !== lessThan) {
return;
}
index++;
subvalue = lessThan;
while (index < length) {
character = value.charAt(index);
if (
whitespace(character) ||
character === greaterThan ||
character === atSign ||
(character === ':' && value.charAt(index + 1) === slash)
) {
break;
}
queue += character;
index++;
}
if (!queue) {
return;
}
link += queue;
queue = '';
character = value.charAt(index);
link += character;
index++;
if (character === atSign) {
hasAtCharacter = true;
} else {
if (character !== ':' || value.charAt(index + 1) !== slash) {
return;
}
link += slash;
index++;
}
while (index < length) {
character = value.charAt(index);
if (whitespace(character) || character === greaterThan) {
break;
}
queue += character;
index++;
}
character = value.charAt(index);
if (!queue || character !== greaterThan) {
return;
}
/* istanbul ignore if - never used (yet) */
if (silent) {
return true;
}
link += queue;
content = link;
subvalue += link + character;
now = eat.now();
now.column++;
now.offset++;
if (hasAtCharacter) {
if (link.slice(0, mailtoLength).toLowerCase() === mailto) {
content = content.slice(mailtoLength);
now.column += mailtoLength;
now.offset += mailtoLength;
} else {
link = mailto + link;
}
}
// Temporarily remove all tokenizers except text in autolinks.
tokenizers = self.inlineTokenizers;
self.inlineTokenizers = { text: tokenizers.text };
exit = self.enterLink();
content = self.tokenizeInline(content, now);
self.inlineTokenizers = tokenizers;
exit();
return eat(subvalue)({
type: 'link',
title: null,
url: decode(link, { nonTerminated: false }),
children: content,
});
}