Files
sgauthier 6e64e138e2
All checks were successful
Publish To Prod / deploy_and_publish (push) Successful in 35s
planning
2024-10-14 09:15:30 +02:00

577 lines
13 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
exports.flow = {
null: {tokenize: tokenizeTable, resolve: resolveTable, interruptible: true}
}
var createSpace = require('micromark/dist/tokenize/factory-space')
var setextUnderlineMini = {tokenize: tokenizeSetextUnderlineMini, partial: true}
var nextPrefixedOrBlank = {tokenize: tokenizeNextPrefixedOrBlank, partial: true}
function resolveTable(events, context) {
var length = events.length
var index = -1
var token
var inHead
var inDelimiterRow
var inRow
var cell
var content
var text
var contentStart
var contentEnd
var cellStart
while (++index < length) {
token = events[index][1]
if (inRow) {
if (token.type === 'temporaryTableCellContent') {
contentStart = contentStart || index
contentEnd = index
}
if (
// Combine separate content parts into one.
(token.type === 'tableCellDivider' || token.type === 'tableRow') &&
contentEnd
) {
content = {
type: 'tableContent',
start: events[contentStart][1].start,
end: events[contentEnd][1].end
}
text = {
type: 'chunkText',
start: content.start,
end: content.end,
contentType: 'text'
}
events.splice(
contentStart,
contentEnd - contentStart + 1,
['enter', content, context],
['enter', text, context],
['exit', text, context],
['exit', content, context]
)
index -= contentEnd - contentStart - 3
length = events.length
contentStart = undefined
contentEnd = undefined
}
}
if (
events[index][0] === 'exit' &&
cellStart &&
cellStart + 1 < index &&
(token.type === 'tableCellDivider' ||
(token.type === 'tableRow' &&
(cellStart + 3 < index ||
events[cellStart][1].type !== 'whitespace')))
) {
cell = {
type: inDelimiterRow
? 'tableDelimiter'
: inHead
? 'tableHeader'
: 'tableData',
start: events[cellStart][1].start,
end: events[index][1].end
}
events.splice(index + (token.type === 'tableCellDivider' ? 1 : 0), 0, [
'exit',
cell,
context
])
events.splice(cellStart, 0, ['enter', cell, context])
index += 2
length = events.length
cellStart = index + 1
}
if (token.type === 'tableRow') {
inRow = events[index][0] === 'enter'
if (inRow) {
cellStart = index + 1
}
}
if (token.type === 'tableDelimiterRow') {
inDelimiterRow = events[index][0] === 'enter'
if (inDelimiterRow) {
cellStart = index + 1
}
}
if (token.type === 'tableHead') {
inHead = events[index][0] === 'enter'
}
}
return events
}
function tokenizeTable(effects, ok, nok) {
var align = []
var tableHeaderCount = 0
var seenDelimiter
var hasDash
return start
function start(code) {
/* istanbul ignore if - used to be passed in beta micromark versions. */
if (code === null || code === -5 || code === -4 || code === -3) {
return nok(code)
}
effects.enter('table')._align = align
effects.enter('tableHead')
effects.enter('tableRow')
// If we start with a pipe, we open a cell marker.
if (code === 124) {
return cellDividerHead(code)
}
tableHeaderCount++
effects.enter('temporaryTableCellContent')
// Cant be space or eols at the start of a construct, so were in a cell.
return inCellContentHead(code)
}
function cellDividerHead(code) {
// Always a pipe.
effects.enter('tableCellDivider')
effects.consume(code)
effects.exit('tableCellDivider')
seenDelimiter = true
return cellBreakHead
}
function cellBreakHead(code) {
// EOF, CR, LF, CRLF.
if (code === null || code === -5 || code === -4 || code === -3) {
return atRowEndHead(code)
}
// HT, VS, SP.
if (code === -2 || code === -1 || code === 32) {
effects.enter('whitespace')
effects.consume(code)
return inWhitespaceHead
}
if (seenDelimiter) {
seenDelimiter = undefined
tableHeaderCount++
}
// `|`
if (code === 124) {
return cellDividerHead(code)
}
// Anything else is cell content.
effects.enter('temporaryTableCellContent')
return inCellContentHead(code)
}
function inWhitespaceHead(code) {
// HT, VS, SP.
if (code === -2 || code === -1 || code === 32) {
effects.consume(code)
return inWhitespaceHead
}
effects.exit('whitespace')
return cellBreakHead(code)
}
function inCellContentHead(code) {
// EOF, whitespace, pipe
if (code === null || code < 0 || code === 32 || code === 124) {
effects.exit('temporaryTableCellContent')
return cellBreakHead(code)
}
effects.consume(code)
// `\`
return code === 92 ? inCellContentEscapeHead : inCellContentHead
}
function inCellContentEscapeHead(code) {
// `\` or `|`
if (code === 92 || code === 124) {
effects.consume(code)
return inCellContentHead
}
// Anything else.
return inCellContentHead(code)
}
function atRowEndHead(code) {
if (code === null) {
return nok(code)
}
effects.exit('tableRow')
effects.exit('tableHead')
// Always a line ending.
effects.enter('lineEnding')
effects.consume(code)
effects.exit('lineEnding')
// If a setext heading, exit.
return effects.check(
setextUnderlineMini,
nok,
// Support an indent before the delimiter row.
createSpace(effects, rowStartDelimiter, 'linePrefix', 4)
)
}
function rowStartDelimiter(code) {
// If theres another space, or were at the EOL/EOF, exit.
if (code === null || code < 0 || code === 32) {
return nok(code)
}
effects.enter('tableDelimiterRow')
return atDelimiterRowBreak(code)
}
function atDelimiterRowBreak(code) {
// EOF, CR, LF, CRLF.
if (code === null || code === -5 || code === -4 || code === -3) {
return rowEndDelimiter(code)
}
// HT, VS, SP.
if (code === -2 || code === -1 || code === 32) {
effects.enter('whitespace')
effects.consume(code)
return inWhitespaceDelimiter
}
// `-`
if (code === 45) {
effects.enter('tableDelimiterFiller')
effects.consume(code)
hasDash = true
align.push(null)
return inFillerDelimiter
}
// `:`
if (code === 58) {
effects.enter('tableDelimiterAlignment')
effects.consume(code)
effects.exit('tableDelimiterAlignment')
align.push('left')
return afterLeftAlignment
}
// If we start with a pipe, we open a cell marker.
if (code === 124) {
effects.enter('tableCellDivider')
effects.consume(code)
effects.exit('tableCellDivider')
return atDelimiterRowBreak
}
return nok(code)
}
function inWhitespaceDelimiter(code) {
// HT, VS, SP.
if (code === -2 || code === -1 || code === 32) {
effects.consume(code)
return inWhitespaceDelimiter
}
effects.exit('whitespace')
return atDelimiterRowBreak(code)
}
function inFillerDelimiter(code) {
// `-`
if (code === 45) {
effects.consume(code)
return inFillerDelimiter
}
effects.exit('tableDelimiterFiller')
// `:`
if (code === 58) {
effects.enter('tableDelimiterAlignment')
effects.consume(code)
effects.exit('tableDelimiterAlignment')
align[align.length - 1] =
align[align.length - 1] === 'left' ? 'center' : 'right'
return afterRightAlignment
}
return atDelimiterRowBreak(code)
}
function afterLeftAlignment(code) {
// `-`
if (code === 45) {
effects.enter('tableDelimiterFiller')
effects.consume(code)
hasDash = true
return inFillerDelimiter
}
// Anything else is not ok.
return nok(code)
}
function afterRightAlignment(code) {
// EOF, CR, LF, CRLF.
if (code === null || code === -5 || code === -4 || code === -3) {
return rowEndDelimiter(code)
}
// HT, VS, SP.
if (code === -2 || code === -1 || code === 32) {
effects.enter('whitespace')
effects.consume(code)
return inWhitespaceDelimiter
}
// `|`
if (code === 124) {
effects.enter('tableCellDivider')
effects.consume(code)
effects.exit('tableCellDivider')
return atDelimiterRowBreak
}
return nok(code)
}
function rowEndDelimiter(code) {
effects.exit('tableDelimiterRow')
// Exit if there was no dash at all, or if the header cell count is not the
// delimiter cell count.
if (!hasDash || tableHeaderCount !== align.length) {
return nok(code)
}
if (code === null) {
return tableClose(code)
}
return effects.check(nextPrefixedOrBlank, tableClose, tableContinue)(code)
}
function tableClose(code) {
effects.exit('table')
return ok(code)
}
function tableContinue(code) {
// Always a line ending.
effects.enter('lineEnding')
effects.consume(code)
effects.exit('lineEnding')
// We checked that its not a prefixed or blank line, so were certain a
// body is coming, though it may be indented.
return createSpace(effects, bodyStart, 'linePrefix', 4)
}
function bodyStart(code) {
effects.enter('tableBody')
return rowStartBody(code)
}
function rowStartBody(code) {
effects.enter('tableRow')
// If we start with a pipe, we open a cell marker.
if (code === 124) {
return cellDividerBody(code)
}
effects.enter('temporaryTableCellContent')
// Cant be space or eols at the start of a construct, so were in a cell.
return inCellContentBody(code)
}
function cellDividerBody(code) {
// Always a pipe.
effects.enter('tableCellDivider')
effects.consume(code)
effects.exit('tableCellDivider')
return cellBreakBody
}
function cellBreakBody(code) {
// EOF, CR, LF, CRLF.
if (code === null || code === -5 || code === -4 || code === -3) {
return atRowEndBody(code)
}
// HT, VS, SP.
if (code === -2 || code === -1 || code === 32) {
effects.enter('whitespace')
effects.consume(code)
return inWhitespaceBody
}
// `|`
if (code === 124) {
return cellDividerBody(code)
}
// Anything else is cell content.
effects.enter('temporaryTableCellContent')
return inCellContentBody(code)
}
function inWhitespaceBody(code) {
// HT, VS, SP.
if (code === -2 || code === -1 || code === 32) {
effects.consume(code)
return inWhitespaceBody
}
effects.exit('whitespace')
return cellBreakBody(code)
}
function inCellContentBody(code) {
// EOF, whitespace, pipe
if (code === null || code < 0 || code === 32 || code === 124) {
effects.exit('temporaryTableCellContent')
return cellBreakBody(code)
}
effects.consume(code)
// `\`
return code === 92 ? inCellContentEscapeBody : inCellContentBody
}
function inCellContentEscapeBody(code) {
// `\` or `|`
if (code === 92 || code === 124) {
effects.consume(code)
return inCellContentBody
}
// Anything else.
return inCellContentBody(code)
}
function atRowEndBody(code) {
effects.exit('tableRow')
if (code === null) {
return tableBodyClose(code)
}
return effects.check(
nextPrefixedOrBlank,
tableBodyClose,
tableBodyContinue
)(code)
}
function tableBodyClose(code) {
effects.exit('tableBody')
return tableClose(code)
}
function tableBodyContinue(code) {
// Always a line ending.
effects.enter('lineEnding')
effects.consume(code)
effects.exit('lineEnding')
// Support an optional prefix, then start a body row.
return createSpace(effects, rowStartBody, 'linePrefix', 4)
}
}
// Based on micromark, but that wont work as were in a table, and that expects
// content.
// <https://github.com/micromark/micromark/blob/main/lib/tokenize/setext-underline.js>
function tokenizeSetextUnderlineMini(effects, ok, nok) {
return start
function start(code) {
// `-`
if (code !== 45) {
return nok(code)
}
effects.enter('setextUnderline')
return sequence(code)
}
function sequence(code) {
if (code === 45) {
effects.consume(code)
return sequence
}
return whitespace(code)
}
function whitespace(code) {
if (code === -2 || code === -1 || code === 32) {
effects.consume(code)
return whitespace
}
if (code === null || code === -5 || code === -4 || code === -3) {
return ok(code)
}
return nok(code)
}
}
function tokenizeNextPrefixedOrBlank(effects, ok, nok) {
var size = 0
return start
function start(code) {
// This is a check, so we dont care about tokens, but we open a bogus one
// so were valid.
effects.enter('check')
// EOL.
effects.consume(code)
return whitespace
}
function whitespace(code) {
// VS or SP.
if (code === -1 || code === 32) {
effects.consume(code)
size++
return size === 4 ? ok : whitespace
}
// EOF or whitespace
if (code === null || code < 0) {
return ok(code)
}
// Anything else.
return nok(code)
}
}