@mapbox/jsxtreme-markdown
Version:
Transform Markdown into JSX or React component modules
254 lines (197 loc) • 4.3 kB
JavaScript
'use strict';
module.exports = fencedCode;
var lineFeed = '\n';
var tab = '\t';
var space = ' ';
var tilde = '~';
var graveAccent = '`';
var minFenceCount = 3;
var tabSize = 4;
function fencedCode(eat, value, silent) {
var self = this;
var gfm = self.options.gfm;
var length = value.length + 1;
var index = 0;
var subvalue = '';
var fenceCount;
var marker;
var character;
var flag;
var lang;
var meta;
var queue;
var content;
var exdentedContent;
var closing;
var exdentedClosing;
var indent;
var now;
if (!gfm) {
return;
}
// Eat initial spacing.
while (index < length) {
character = value.charAt(index);
if (character !== space && character !== tab) {
break;
}
subvalue += character;
index++;
}
indent = index;
// Eat the fence.
character = value.charAt(index);
if (character !== tilde && character !== graveAccent) {
return;
}
index++;
marker = character;
fenceCount = 1;
subvalue += character;
while (index < length) {
character = value.charAt(index);
if (character !== marker) {
break;
}
subvalue += character;
fenceCount++;
index++;
}
if (fenceCount < minFenceCount) {
return;
}
// Eat spacing before flag.
while (index < length) {
character = value.charAt(index);
if (character !== space && character !== tab) {
break;
}
subvalue += character;
index++;
}
// Eat flag.
flag = '';
queue = '';
while (index < length) {
character = value.charAt(index);
if (
character === lineFeed ||
(marker === graveAccent && character === marker)
) {
break;
}
if (character === space || character === tab) {
queue += character;
} else {
flag += queue + character;
queue = '';
}
index++;
}
character = value.charAt(index);
if (character && character !== lineFeed) {
return;
}
if (silent) {
return true;
}
now = eat.now();
now.column += subvalue.length;
now.offset += subvalue.length;
subvalue += flag;
flag = self.decode.raw(self.unescape(flag), now);
if (queue) {
subvalue += queue;
}
queue = '';
closing = '';
exdentedClosing = '';
content = '';
exdentedContent = '';
var skip = true;
// Eat content.
while (index < length) {
character = value.charAt(index);
content += closing;
exdentedContent += exdentedClosing;
closing = '';
exdentedClosing = '';
if (character !== lineFeed) {
content += character;
exdentedClosing += character;
index++;
continue;
}
// The first line feed is ignored. Others aren’t.
if (skip) {
subvalue += character;
skip = false;
} else {
closing += character;
exdentedClosing += character;
}
queue = '';
index++;
while (index < length) {
character = value.charAt(index);
if (character !== space) {
break;
}
queue += character;
index++;
}
closing += queue;
exdentedClosing += queue.slice(indent);
if (queue.length >= tabSize) {
continue;
}
queue = '';
while (index < length) {
character = value.charAt(index);
if (character !== marker) {
break;
}
queue += character;
index++;
}
closing += queue;
exdentedClosing += queue;
if (queue.length < fenceCount) {
continue;
}
queue = '';
while (index < length) {
character = value.charAt(index);
if (character !== space && character !== tab) {
break;
}
closing += character;
exdentedClosing += character;
index++;
}
if (!character || character === lineFeed) {
break;
}
}
subvalue += content + closing;
// Get lang and meta from the flag.
index = -1;
length = flag.length;
while (++index < length) {
character = flag.charAt(index);
if (character === space || character === tab) {
if (!lang) {
lang = flag.slice(0, index);
}
} else if (lang) {
meta = flag.slice(index);
break;
}
}
return eat(subvalue)({
type: 'code',
lang: lang || flag || null,
meta: meta || null,
value: exdentedContent,
});
}