| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- 'use strict';
- var whitespace = require('is-whitespace-character');
- var locate = require('../locate/link');
- var normalize = require('../util/normalize');
- module.exports = reference;
- reference.locator = locate;
- var T_LINK = 'link';
- var T_IMAGE = 'image';
- var T_FOOTNOTE = 'footnote';
- var REFERENCE_TYPE_SHORTCUT = 'shortcut';
- var REFERENCE_TYPE_COLLAPSED = 'collapsed';
- var REFERENCE_TYPE_FULL = 'full';
- var C_CARET = '^';
- var C_BACKSLASH = '\\';
- var C_BRACKET_OPEN = '[';
- var C_BRACKET_CLOSE = ']';
- function reference(eat, value, silent) {
- var self = this;
- var character = value.charAt(0);
- var index = 0;
- var length = value.length;
- var subvalue = '';
- var intro = '';
- var type = T_LINK;
- var referenceType = REFERENCE_TYPE_SHORTCUT;
- var content;
- var identifier;
- var now;
- var node;
- var exit;
- var queue;
- var bracketed;
- var depth;
- /* Check whether we’re eating an image. */
- if (character === '!') {
- type = T_IMAGE;
- intro = character;
- character = value.charAt(++index);
- }
- if (character !== C_BRACKET_OPEN) {
- return;
- }
- index++;
- intro += character;
- queue = '';
- /* Check whether we’re eating a footnote. */
- if (self.options.footnotes && value.charAt(index) === C_CARET) {
- /* Exit if `![^` is found, so the `!` will be seen as text after this,
- * and we’ll enter this function again when `[^` is found. */
- if (type === T_IMAGE) {
- return;
- }
- intro += C_CARET;
- index++;
- type = T_FOOTNOTE;
- }
- /* Eat the text. */
- depth = 0;
- while (index < length) {
- character = value.charAt(index);
- if (character === C_BRACKET_OPEN) {
- bracketed = true;
- depth++;
- } else if (character === C_BRACKET_CLOSE) {
- if (!depth) {
- break;
- }
- depth--;
- }
- if (character === C_BACKSLASH) {
- queue += C_BACKSLASH;
- character = value.charAt(++index);
- }
- queue += character;
- index++;
- }
- subvalue = queue;
- content = queue;
- character = value.charAt(index);
- if (character !== C_BRACKET_CLOSE) {
- return;
- }
- index++;
- subvalue += character;
- queue = '';
- while (index < length) {
- character = value.charAt(index);
- if (!whitespace(character)) {
- break;
- }
- queue += character;
- index++;
- }
- character = value.charAt(index);
- /* Inline footnotes cannot have an identifier. */
- if (type !== T_FOOTNOTE && character === C_BRACKET_OPEN) {
- identifier = '';
- queue += character;
- index++;
- while (index < length) {
- character = value.charAt(index);
- if (character === C_BRACKET_OPEN || character === C_BRACKET_CLOSE) {
- break;
- }
- if (character === C_BACKSLASH) {
- identifier += C_BACKSLASH;
- character = value.charAt(++index);
- }
- identifier += character;
- index++;
- }
- character = value.charAt(index);
- if (character === C_BRACKET_CLOSE) {
- referenceType = identifier ? REFERENCE_TYPE_FULL : REFERENCE_TYPE_COLLAPSED;
- queue += identifier + character;
- index++;
- } else {
- identifier = '';
- }
- subvalue += queue;
- queue = '';
- } else {
- if (!content) {
- return;
- }
- identifier = content;
- }
- /* Brackets cannot be inside the identifier. */
- if (referenceType !== REFERENCE_TYPE_FULL && bracketed) {
- return;
- }
- subvalue = intro + subvalue;
- if (type === T_LINK && self.inLink) {
- return null;
- }
- /* istanbul ignore if - never used (yet) */
- if (silent) {
- return true;
- }
- if (type === T_FOOTNOTE && content.indexOf(' ') !== -1) {
- return eat(subvalue)({
- type: 'footnote',
- children: this.tokenizeInline(content, eat.now())
- });
- }
- now = eat.now();
- now.column += intro.length;
- now.offset += intro.length;
- identifier = referenceType === REFERENCE_TYPE_FULL ? identifier : content;
- node = {
- type: type + 'Reference',
- identifier: normalize(identifier)
- };
- if (type === T_LINK || type === T_IMAGE) {
- node.referenceType = referenceType;
- }
- if (type === T_LINK) {
- exit = self.enterLink();
- node.children = self.tokenizeInline(content, now);
- exit();
- } else if (type === T_IMAGE) {
- node.alt = self.decode.raw(self.unescape(content), now) || null;
- }
- return eat(subvalue)(node);
- }
|