| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- 'use strict';
- var whitespace = require('is-whitespace-character');
- module.exports = table;
- var C_BACKSLASH = '\\';
- var C_TICK = '`';
- var C_DASH = '-';
- var C_PIPE = '|';
- var C_COLON = ':';
- var C_SPACE = ' ';
- var C_NEWLINE = '\n';
- var C_TAB = '\t';
- var MIN_TABLE_COLUMNS = 1;
- var MIN_TABLE_ROWS = 2;
- var TABLE_ALIGN_LEFT = 'left';
- var TABLE_ALIGN_CENTER = 'center';
- var TABLE_ALIGN_RIGHT = 'right';
- var TABLE_ALIGN_NONE = null;
- function table(eat, value, silent) {
- var self = this;
- var index;
- var alignments;
- var alignment;
- var subvalue;
- var row;
- var length;
- var lines;
- var queue;
- var character;
- var hasDash;
- var align;
- var cell;
- var preamble;
- var count;
- var opening;
- var now;
- var position;
- var lineCount;
- var line;
- var rows;
- var table;
- var lineIndex;
- var pipeIndex;
- var first;
- /* Exit when not in gfm-mode. */
- if (!self.options.gfm) {
- return;
- }
- /* Get the rows.
- * Detecting tables soon is hard, so there are some
- * checks for performance here, such as the minimum
- * number of rows, and allowed characters in the
- * alignment row. */
- index = 0;
- lineCount = 0;
- length = value.length + 1;
- lines = [];
- while (index < length) {
- lineIndex = value.indexOf(C_NEWLINE, index);
- pipeIndex = value.indexOf(C_PIPE, index + 1);
- if (lineIndex === -1) {
- lineIndex = value.length;
- }
- if (pipeIndex === -1 || pipeIndex > lineIndex) {
- if (lineCount < MIN_TABLE_ROWS) {
- return;
- }
- break;
- }
- lines.push(value.slice(index, lineIndex));
- lineCount++;
- index = lineIndex + 1;
- }
- /* Parse the alignment row. */
- subvalue = lines.join(C_NEWLINE);
- alignments = lines.splice(1, 1)[0] || [];
- index = 0;
- length = alignments.length;
- lineCount--;
- alignment = false;
- align = [];
- while (index < length) {
- character = alignments.charAt(index);
- if (character === C_PIPE) {
- hasDash = null;
- if (alignment === false) {
- if (first === false) {
- return;
- }
- } else {
- align.push(alignment);
- alignment = false;
- }
- first = false;
- } else if (character === C_DASH) {
- hasDash = true;
- alignment = alignment || TABLE_ALIGN_NONE;
- } else if (character === C_COLON) {
- if (alignment === TABLE_ALIGN_LEFT) {
- alignment = TABLE_ALIGN_CENTER;
- } else if (hasDash && alignment === TABLE_ALIGN_NONE) {
- alignment = TABLE_ALIGN_RIGHT;
- } else {
- alignment = TABLE_ALIGN_LEFT;
- }
- } else if (!whitespace(character)) {
- return;
- }
- index++;
- }
- if (alignment !== false) {
- align.push(alignment);
- }
- /* Exit when without enough columns. */
- if (align.length < MIN_TABLE_COLUMNS) {
- return;
- }
- /* istanbul ignore if - never used (yet) */
- if (silent) {
- return true;
- }
- /* Parse the rows. */
- position = -1;
- rows = [];
- table = eat(subvalue).reset({
- type: 'table',
- align: align,
- children: rows
- });
- while (++position < lineCount) {
- line = lines[position];
- row = {type: 'tableRow', children: []};
- /* Eat a newline character when this is not the
- * first row. */
- if (position) {
- eat(C_NEWLINE);
- }
- /* Eat the row. */
- eat(line).reset(row, table);
- length = line.length + 1;
- index = 0;
- queue = '';
- cell = '';
- preamble = true;
- count = null;
- opening = null;
- while (index < length) {
- character = line.charAt(index);
- if (character === C_TAB || character === C_SPACE) {
- if (cell) {
- queue += character;
- } else {
- eat(character);
- }
- index++;
- continue;
- }
- if (character === '' || character === C_PIPE) {
- if (preamble) {
- eat(character);
- } else {
- if (character && opening) {
- queue += character;
- index++;
- continue;
- }
- if ((cell || character) && !preamble) {
- subvalue = cell;
- if (queue.length > 1) {
- if (character) {
- subvalue += queue.slice(0, queue.length - 1);
- queue = queue.charAt(queue.length - 1);
- } else {
- subvalue += queue;
- queue = '';
- }
- }
- now = eat.now();
- eat(subvalue)({
- type: 'tableCell',
- children: self.tokenizeInline(cell, now)
- }, row);
- }
- eat(queue + character);
- queue = '';
- cell = '';
- }
- } else {
- if (queue) {
- cell += queue;
- queue = '';
- }
- cell += character;
- if (character === C_BACKSLASH && index !== length - 2) {
- cell += line.charAt(index + 1);
- index++;
- }
- if (character === C_TICK) {
- count = 1;
- while (line.charAt(index + 1) === character) {
- cell += character;
- index++;
- count++;
- }
- if (!opening) {
- opening = count;
- } else if (count >= opening) {
- opening = 0;
- }
- }
- }
- preamble = false;
- index++;
- }
- /* Eat the alignment row. */
- if (!position) {
- eat(C_NEWLINE + alignments);
- }
- }
- return table;
- }
|