| 'use strict' |
| |
| var whitespace = require('is-whitespace-character') |
| |
| module.exports = table |
| |
| var tab = '\t' |
| var lineFeed = '\n' |
| var space = ' ' |
| var dash = '-' |
| var colon = ':' |
| var backslash = '\\' |
| var graveAccent = '`' |
| var verticalBar = '|' |
| |
| var minColumns = 1 |
| var minRows = 2 |
| |
| var left = 'left' |
| var center = 'center' |
| var right = 'right' |
| |
| 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(lineFeed, index) |
| pipeIndex = value.indexOf(verticalBar, index + 1) |
| |
| if (lineIndex === -1) { |
| lineIndex = value.length |
| } |
| |
| if (pipeIndex === -1 || pipeIndex > lineIndex) { |
| if (lineCount < minRows) { |
| return |
| } |
| |
| break |
| } |
| |
| lines.push(value.slice(index, lineIndex)) |
| lineCount++ |
| index = lineIndex + 1 |
| } |
| |
| // Parse the alignment row. |
| subvalue = lines.join(lineFeed) |
| alignments = lines.splice(1, 1)[0] || [] |
| index = 0 |
| length = alignments.length |
| lineCount-- |
| alignment = false |
| align = [] |
| |
| while (index < length) { |
| character = alignments.charAt(index) |
| |
| if (character === verticalBar) { |
| hasDash = null |
| |
| if (alignment === false) { |
| if (first === false) { |
| return |
| } |
| } else { |
| align.push(alignment) |
| alignment = false |
| } |
| |
| first = false |
| } else if (character === dash) { |
| hasDash = true |
| alignment = alignment || null |
| } else if (character === colon) { |
| if (alignment === left) { |
| alignment = center |
| } else if (hasDash && alignment === null) { |
| alignment = right |
| } else { |
| alignment = left |
| } |
| } else if (!whitespace(character)) { |
| return |
| } |
| |
| index++ |
| } |
| |
| if (alignment !== false) { |
| align.push(alignment) |
| } |
| |
| // Exit when without enough columns. |
| if (align.length < minColumns) { |
| 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(lineFeed) |
| } |
| |
| // 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 === tab || character === space) { |
| if (cell) { |
| queue += character |
| } else { |
| eat(character) |
| } |
| |
| index++ |
| continue |
| } |
| |
| if (character === '' || character === verticalBar) { |
| 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 === backslash && index !== length - 2) { |
| cell += line.charAt(index + 1) |
| index++ |
| } |
| |
| if (character === graveAccent) { |
| 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(lineFeed + alignments) |
| } |
| } |
| |
| return table |
| } |