@mapbox/jsxtreme-markdown
Version:
Transform Markdown into JSX or React component modules
189 lines (151 loc) • 3.79 kB
JavaScript
'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 link = 'link';
var image = 'image';
var shortcut = 'shortcut';
var collapsed = 'collapsed';
var full = 'full';
var exclamationMark = '!';
var leftSquareBracket = '[';
var backslash = '\\';
var rightSquareBracket = ']';
function reference(eat, value, silent) {
var self = this;
var commonmark = self.options.commonmark;
var character = value.charAt(0);
var index = 0;
var length = value.length;
var subvalue = '';
var intro = '';
var type = link;
var referenceType = 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 === exclamationMark) {
type = image;
intro = character;
character = value.charAt(++index);
}
if (character !== leftSquareBracket) {
return;
}
index++;
intro += character;
queue = '';
// Eat the text.
depth = 0;
while (index < length) {
character = value.charAt(index);
if (character === leftSquareBracket) {
bracketed = true;
depth++;
} else if (character === rightSquareBracket) {
if (!depth) {
break;
}
depth--;
}
if (character === backslash) {
queue += backslash;
character = value.charAt(++index);
}
queue += character;
index++;
}
subvalue = queue;
content = queue;
character = value.charAt(index);
if (character !== rightSquareBracket) {
return;
}
index++;
subvalue += character;
queue = '';
if (!commonmark) {
// The original markdown syntax definition explicitly allows for whitespace
// between the link text and link label; commonmark departs from this, in
// part to improve support for shortcut reference links
while (index < length) {
character = value.charAt(index);
if (!whitespace(character)) {
break;
}
queue += character;
index++;
}
}
character = value.charAt(index);
if (character === leftSquareBracket) {
identifier = '';
queue += character;
index++;
while (index < length) {
character = value.charAt(index);
if (character === leftSquareBracket || character === rightSquareBracket) {
break;
}
if (character === backslash) {
identifier += backslash;
character = value.charAt(++index);
}
identifier += character;
index++;
}
character = value.charAt(index);
if (character === rightSquareBracket) {
referenceType = identifier ? full : collapsed;
queue += identifier + character;
index++;
} else {
identifier = '';
}
subvalue += queue;
queue = '';
} else {
if (!content) {
return;
}
identifier = content;
}
// Brackets cannot be inside the identifier.
if (referenceType !== full && bracketed) {
return;
}
subvalue = intro + subvalue;
if (type === link && self.inLink) {
return null;
}
/* istanbul ignore if - never used (yet) */
if (silent) {
return true;
}
now = eat.now();
now.column += intro.length;
now.offset += intro.length;
identifier = referenceType === full ? identifier : content;
node = {
type: type + 'Reference',
identifier: normalize(identifier),
label: identifier,
referenceType: referenceType,
};
if (type === link) {
exit = self.enterLink();
node.children = self.tokenizeInline(content, now);
exit();
} else {
node.alt = self.decode.raw(self.unescape(content), now) || null;
}
return eat(subvalue)(node);
}