|
|
|
|
|
|
|
|
|
|
|
|
|
import {splice} from 'micromark-util-chunked' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function subtokenize(events) { |
|
|
|
const jumps = {} |
|
let index = -1 |
|
|
|
let event |
|
|
|
let lineIndex |
|
|
|
let otherIndex |
|
|
|
let otherEvent |
|
|
|
let parameters |
|
|
|
let subevents |
|
|
|
let more |
|
while (++index < events.length) { |
|
while (index in jumps) { |
|
index = jumps[index] |
|
} |
|
event = events[index] |
|
|
|
|
|
|
|
if ( |
|
index && |
|
event[1].type === 'chunkFlow' && |
|
events[index - 1][1].type === 'listItemPrefix' |
|
) { |
|
subevents = event[1]._tokenizer.events |
|
otherIndex = 0 |
|
if ( |
|
otherIndex < subevents.length && |
|
subevents[otherIndex][1].type === 'lineEndingBlank' |
|
) { |
|
otherIndex += 2 |
|
} |
|
if ( |
|
otherIndex < subevents.length && |
|
subevents[otherIndex][1].type === 'content' |
|
) { |
|
while (++otherIndex < subevents.length) { |
|
if (subevents[otherIndex][1].type === 'content') { |
|
break |
|
} |
|
if (subevents[otherIndex][1].type === 'chunkText') { |
|
subevents[otherIndex][1]._isInFirstContentOfListItem = true |
|
otherIndex++ |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
if (event[0] === 'enter') { |
|
if (event[1].contentType) { |
|
Object.assign(jumps, subcontent(events, index)) |
|
index = jumps[index] |
|
more = true |
|
} |
|
} |
|
|
|
else if (event[1]._container) { |
|
otherIndex = index |
|
lineIndex = undefined |
|
while (otherIndex--) { |
|
otherEvent = events[otherIndex] |
|
if ( |
|
otherEvent[1].type === 'lineEnding' || |
|
otherEvent[1].type === 'lineEndingBlank' |
|
) { |
|
if (otherEvent[0] === 'enter') { |
|
if (lineIndex) { |
|
events[lineIndex][1].type = 'lineEndingBlank' |
|
} |
|
otherEvent[1].type = 'lineEnding' |
|
lineIndex = otherIndex |
|
} |
|
} else { |
|
break |
|
} |
|
} |
|
if (lineIndex) { |
|
|
|
event[1].end = Object.assign({}, events[lineIndex][1].start) |
|
|
|
|
|
parameters = events.slice(lineIndex, index) |
|
parameters.unshift(event) |
|
splice(events, lineIndex, index - lineIndex + 1, parameters) |
|
} |
|
} |
|
} |
|
return !more |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function subcontent(events, eventIndex) { |
|
const token = events[eventIndex][1] |
|
const context = events[eventIndex][2] |
|
let startPosition = eventIndex - 1 |
|
|
|
const startPositions = [] |
|
const tokenizer = |
|
token._tokenizer || context.parser[token.contentType](token.start) |
|
const childEvents = tokenizer.events |
|
|
|
const jumps = [] |
|
|
|
const gaps = {} |
|
|
|
let stream |
|
|
|
let previous |
|
let index = -1 |
|
|
|
let current = token |
|
let adjust = 0 |
|
let start = 0 |
|
const breaks = [start] |
|
|
|
|
|
|
|
while (current) { |
|
|
|
while (events[++startPosition][1] !== current) { |
|
|
|
} |
|
startPositions.push(startPosition) |
|
if (!current._tokenizer) { |
|
stream = context.sliceStream(current) |
|
if (!current.next) { |
|
stream.push(null) |
|
} |
|
if (previous) { |
|
tokenizer.defineSkip(current.start) |
|
} |
|
if (current._isInFirstContentOfListItem) { |
|
tokenizer._gfmTasklistFirstContentOfListItem = true |
|
} |
|
tokenizer.write(stream) |
|
if (current._isInFirstContentOfListItem) { |
|
tokenizer._gfmTasklistFirstContentOfListItem = undefined |
|
} |
|
} |
|
|
|
|
|
previous = current |
|
current = current.next |
|
} |
|
|
|
|
|
|
|
current = token |
|
while (++index < childEvents.length) { |
|
if ( |
|
|
|
childEvents[index][0] === 'exit' && |
|
childEvents[index - 1][0] === 'enter' && |
|
childEvents[index][1].type === childEvents[index - 1][1].type && |
|
childEvents[index][1].start.line !== childEvents[index][1].end.line |
|
) { |
|
start = index + 1 |
|
breaks.push(start) |
|
|
|
current._tokenizer = undefined |
|
current.previous = undefined |
|
current = current.next |
|
} |
|
} |
|
|
|
|
|
tokenizer.events = [] |
|
|
|
|
|
|
|
|
|
if (current) { |
|
|
|
current._tokenizer = undefined |
|
current.previous = undefined |
|
} else { |
|
breaks.pop() |
|
} |
|
|
|
|
|
|
|
index = breaks.length |
|
while (index--) { |
|
const slice = childEvents.slice(breaks[index], breaks[index + 1]) |
|
const start = startPositions.pop() |
|
jumps.unshift([start, start + slice.length - 1]) |
|
splice(events, start, 2, slice) |
|
} |
|
index = -1 |
|
while (++index < jumps.length) { |
|
gaps[adjust + jumps[index][0]] = adjust + jumps[index][1] |
|
adjust += jumps[index][1] - jumps[index][0] - 1 |
|
} |
|
return gaps |
|
} |
|
|