/** * @author Titus Wormer * @copyright 2015 Titus Wormer * @license MIT * @module remark:parse:tokenize:auto-link * @fileoverview Tokenise an auto-link. */ 'use strict'; var decode = require('parse-entities'); var locate = require('../locate/tag'); module.exports = autoLink; autoLink.locator = locate; autoLink.notInLink = true; var C_LT = '<'; var C_GT = '>'; var C_AT_SIGN = '@'; var C_SLASH = '/'; var MAILTO = 'mailto:'; var MAILTO_LENGTH = MAILTO.length; /* Tokenise a link. */ function autoLink(eat, value, silent) { var self; var subvalue; var length; var index; var queue; var character; var hasAtCharacter; var link; var now; var content; var tokenize; var exit; if (value.charAt(0) !== C_LT) { return; } self = this; subvalue = ''; length = value.length; index = 0; queue = ''; hasAtCharacter = false; link = ''; index++; subvalue = C_LT; while (index < length) { character = value.charAt(index); if ( character === ' ' || character === C_GT || character === C_AT_SIGN || (character === ':' && value.charAt(index + 1) === C_SLASH) ) { break; } queue += character; index++; } if (!queue) { return; } link += queue; queue = ''; character = value.charAt(index); link += character; index++; if (character === C_AT_SIGN) { hasAtCharacter = true; } else { if ( character !== ':' || value.charAt(index + 1) !== C_SLASH ) { return; } link += C_SLASH; index++; } while (index < length) { character = value.charAt(index); if (character === ' ' || character === C_GT) { break; } queue += character; index++; } character = value.charAt(index); if (!queue || character !== C_GT) { 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, MAILTO_LENGTH).toLowerCase() === MAILTO) { content = content.substr(MAILTO_LENGTH); now.column += MAILTO_LENGTH; now.offset += MAILTO_LENGTH; } else { link = MAILTO + link; } } /* Temporarily remove support for escapes in autolinks. */ tokenize = self.inlineTokenizers.escape; self.inlineTokenizers.escape = null; exit = self.enterLink(); content = self.tokenizeInline(content, now); self.inlineTokenizers.escape = tokenize; exit(); return eat(subvalue)({ type: 'link', title: null, url: decode(link), children: content }); }