rsuite-theme
Version:
The suite theme for pagurian
475 lines (377 loc) • 10.5 kB
JavaScript
;
/* eslint-disable max-params */
var trim = require('trim');
var repeat = require('repeat-string');
var decimal = require('is-decimal');
var getIndent = require('../util/get-indentation');
var removeIndent = require('../util/remove-indentation');
var interrupt = require('../util/interrupt');
module.exports = list;
var C_ASTERISK = '*';
var C_UNDERSCORE = '_';
var C_PLUS = '+';
var C_DASH = '-';
var C_DOT = '.';
var C_SPACE = ' ';
var C_NEWLINE = '\n';
var C_TAB = '\t';
var C_PAREN_CLOSE = ')';
var C_X_LOWER = 'x';
var TAB_SIZE = 4;
var EXPRESSION_LOOSE_LIST_ITEM = /\n\n(?!\s*$)/;
var EXPRESSION_TASK_ITEM = /^\[([ \t]|x|X)][ \t]/;
var EXPRESSION_BULLET = /^([ \t]*)([*+-]|\d+[.)])( {1,4}(?! )| |\t|$|(?=\n))([^\n]*)/;
var EXPRESSION_PEDANTIC_BULLET = /^([ \t]*)([*+-]|\d+[.)])([ \t]+)/;
var EXPRESSION_INITIAL_INDENT = /^( {1,4}|\t)?/gm;
/* Map of characters which can be used to mark
* list-items. */
var LIST_UNORDERED_MARKERS = {};
LIST_UNORDERED_MARKERS[C_ASTERISK] = true;
LIST_UNORDERED_MARKERS[C_PLUS] = true;
LIST_UNORDERED_MARKERS[C_DASH] = true;
/* Map of characters which can be used to mark
* list-items after a digit. */
var LIST_ORDERED_MARKERS = {};
LIST_ORDERED_MARKERS[C_DOT] = true;
/* Map of characters which can be used to mark
* list-items after a digit. */
var LIST_ORDERED_COMMONMARK_MARKERS = {};
LIST_ORDERED_COMMONMARK_MARKERS[C_DOT] = true;
LIST_ORDERED_COMMONMARK_MARKERS[C_PAREN_CLOSE] = true;
function list(eat, value, silent) {
var self = this;
var commonmark = self.options.commonmark;
var pedantic = self.options.pedantic;
var tokenizers = self.blockTokenizers;
var interuptors = self.interruptList;
var markers;
var index = 0;
var length = value.length;
var start = null;
var size = 0;
var queue;
var ordered;
var character;
var marker;
var nextIndex;
var startIndex;
var prefixed;
var currentMarker;
var content;
var line;
var prevEmpty;
var empty;
var items;
var allLines;
var emptyLines;
var item;
var enterTop;
var exitBlockquote;
var isLoose;
var node;
var now;
var end;
var indented;
while (index < length) {
character = value.charAt(index);
if (character === C_TAB) {
size += TAB_SIZE - (size % TAB_SIZE);
} else if (character === C_SPACE) {
size++;
} else {
break;
}
index++;
}
if (size >= TAB_SIZE) {
return;
}
character = value.charAt(index);
markers = commonmark ?
LIST_ORDERED_COMMONMARK_MARKERS :
LIST_ORDERED_MARKERS;
if (LIST_UNORDERED_MARKERS[character] === true) {
marker = character;
ordered = false;
} else {
ordered = true;
queue = '';
while (index < length) {
character = value.charAt(index);
if (!decimal(character)) {
break;
}
queue += character;
index++;
}
character = value.charAt(index);
if (!queue || markers[character] !== true) {
return;
}
start = parseInt(queue, 10);
marker = character;
}
character = value.charAt(++index);
if (character !== C_SPACE && character !== C_TAB) {
return;
}
if (silent) {
return true;
}
index = 0;
items = [];
allLines = [];
emptyLines = [];
while (index < length) {
nextIndex = value.indexOf(C_NEWLINE, index);
startIndex = index;
prefixed = false;
indented = false;
if (nextIndex === -1) {
nextIndex = length;
}
end = index + TAB_SIZE;
size = 0;
while (index < length) {
character = value.charAt(index);
if (character === C_TAB) {
size += TAB_SIZE - (size % TAB_SIZE);
} else if (character === C_SPACE) {
size++;
} else {
break;
}
index++;
}
if (size >= TAB_SIZE) {
indented = true;
}
if (item && size >= item.indent) {
indented = true;
}
character = value.charAt(index);
currentMarker = null;
if (!indented) {
if (LIST_UNORDERED_MARKERS[character] === true) {
currentMarker = character;
index++;
size++;
} else {
queue = '';
while (index < length) {
character = value.charAt(index);
if (!decimal(character)) {
break;
}
queue += character;
index++;
}
character = value.charAt(index);
index++;
if (queue && markers[character] === true) {
currentMarker = character;
size += queue.length + 1;
}
}
if (currentMarker) {
character = value.charAt(index);
if (character === C_TAB) {
size += TAB_SIZE - (size % TAB_SIZE);
index++;
} else if (character === C_SPACE) {
end = index + TAB_SIZE;
while (index < end) {
if (value.charAt(index) !== C_SPACE) {
break;
}
index++;
size++;
}
if (index === end && value.charAt(index) === C_SPACE) {
index -= TAB_SIZE - 1;
size -= TAB_SIZE - 1;
}
} else if (character !== C_NEWLINE && character !== '') {
currentMarker = null;
}
}
}
if (currentMarker) {
if (!pedantic && marker !== currentMarker) {
break;
}
prefixed = true;
} else {
if (!commonmark && !indented && value.charAt(startIndex) === C_SPACE) {
indented = true;
} else if (commonmark && item) {
indented = size >= item.indent || size > TAB_SIZE;
}
prefixed = false;
index = startIndex;
}
line = value.slice(startIndex, nextIndex);
content = startIndex === index ? line : value.slice(index, nextIndex);
if (
currentMarker === C_ASTERISK ||
currentMarker === C_UNDERSCORE ||
currentMarker === C_DASH
) {
if (tokenizers.thematicBreak.call(self, eat, line, true)) {
break;
}
}
prevEmpty = empty;
empty = !trim(content).length;
if (indented && item) {
item.value = item.value.concat(emptyLines, line);
allLines = allLines.concat(emptyLines, line);
emptyLines = [];
} else if (prefixed) {
if (emptyLines.length !== 0) {
item.value.push('');
item.trail = emptyLines.concat();
}
item = {
value: [line],
indent: size,
trail: []
};
items.push(item);
allLines = allLines.concat(emptyLines, line);
emptyLines = [];
} else if (empty) {
if (prevEmpty) {
break;
}
emptyLines.push(line);
} else {
if (prevEmpty) {
break;
}
if (interrupt(interuptors, tokenizers, self, [eat, line, true])) {
break;
}
item.value = item.value.concat(emptyLines, line);
allLines = allLines.concat(emptyLines, line);
emptyLines = [];
}
index = nextIndex + 1;
}
node = eat(allLines.join(C_NEWLINE)).reset({
type: 'list',
ordered: ordered,
start: start,
loose: null,
children: []
});
enterTop = self.enterList();
exitBlockquote = self.enterBlock();
isLoose = false;
index = -1;
length = items.length;
while (++index < length) {
item = items[index].value.join(C_NEWLINE);
now = eat.now();
item = eat(item)(listItem(self, item, now), node);
if (item.loose) {
isLoose = true;
}
item = items[index].trail.join(C_NEWLINE);
if (index !== length - 1) {
item += C_NEWLINE;
}
eat(item);
}
enterTop();
exitBlockquote();
node.loose = isLoose;
return node;
}
function listItem(ctx, value, position) {
var offsets = ctx.offset;
var fn = ctx.options.pedantic ? pedanticListItem : normalListItem;
var checked = null;
var task;
var indent;
value = fn.apply(null, arguments);
if (ctx.options.gfm) {
task = value.match(EXPRESSION_TASK_ITEM);
if (task) {
indent = task[0].length;
checked = task[1].toLowerCase() === C_X_LOWER;
offsets[position.line] += indent;
value = value.slice(indent);
}
}
return {
type: 'listItem',
loose: EXPRESSION_LOOSE_LIST_ITEM.test(value) ||
value.charAt(value.length - 1) === C_NEWLINE,
checked: checked,
children: ctx.tokenizeBlock(value, position)
};
}
/* Create a list-item using overly simple mechanics. */
function pedanticListItem(ctx, value, position) {
var offsets = ctx.offset;
var line = position.line;
/* Remove the list-item’s bullet. */
value = value.replace(EXPRESSION_PEDANTIC_BULLET, replacer);
/* The initial line was also matched by the below, so
* we reset the `line`. */
line = position.line;
return value.replace(EXPRESSION_INITIAL_INDENT, replacer);
/* A simple replacer which removed all matches,
* and adds their length to `offset`. */
function replacer($0) {
offsets[line] = (offsets[line] || 0) + $0.length;
line++;
return '';
}
}
/* Create a list-item using sane mechanics. */
function normalListItem(ctx, value, position) {
var offsets = ctx.offset;
var line = position.line;
var max;
var bullet;
var rest;
var lines;
var trimmedLines;
var index;
var length;
/* Remove the list-item’s bullet. */
value = value.replace(EXPRESSION_BULLET, replacer);
lines = value.split(C_NEWLINE);
trimmedLines = removeIndent(value, getIndent(max).indent).split(C_NEWLINE);
/* We replaced the initial bullet with something
* else above, which was used to trick
* `removeIndentation` into removing some more
* characters when possible. However, that could
* result in the initial line to be stripped more
* than it should be. */
trimmedLines[0] = rest;
offsets[line] = (offsets[line] || 0) + bullet.length;
line++;
index = 0;
length = lines.length;
while (++index < length) {
offsets[line] = (offsets[line] || 0) +
lines[index].length - trimmedLines[index].length;
line++;
}
return trimmedLines.join(C_NEWLINE);
function replacer($0, $1, $2, $3, $4) {
bullet = $1 + $2 + $3;
rest = $4;
/* Make sure that the first nine numbered list items
* can indent with an extra space. That is, when
* the bullet did not receive an extra final space. */
if (Number($2) < 10 && bullet.length % 2 === 1) {
$2 = C_SPACE + $2;
}
max = $1 + repeat(C_SPACE, $2.length) + $3;
return max + rest;
}
}