233 lines
4.4 KiB
JavaScript
233 lines
4.4 KiB
JavaScript
'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 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 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
|
|
|
|
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 ((cell || character) && !preamble) {
|
|
subvalue = cell
|
|
|
|
if (queue.length > 1) {
|
|
if (character) {
|
|
subvalue += queue.slice(0, -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++
|
|
}
|
|
}
|
|
|
|
preamble = false
|
|
index++
|
|
}
|
|
|
|
// Eat the alignment row.
|
|
if (!position) {
|
|
eat(lineFeed + alignments)
|
|
}
|
|
}
|
|
|
|
return table
|
|
}
|