All checks were successful
Publish To Prod / deploy_and_publish (push) Successful in 35s
161 lines
4.3 KiB
JavaScript
161 lines
4.3 KiB
JavaScript
module.exports = create
|
|
|
|
var classifyCharacter = require('micromark/dist/util/classify-character')
|
|
var chunkedSplice = require('micromark/dist/util/chunked-splice')
|
|
var resolveAll = require('micromark/dist/util/resolve-all')
|
|
var shallow = require('micromark/dist/util/shallow')
|
|
|
|
function create(options) {
|
|
var settings = options || {}
|
|
var single = settings.singleTilde
|
|
var tokenizer = {
|
|
tokenize: tokenizeStrikethrough,
|
|
resolveAll: resolveAllStrikethrough
|
|
}
|
|
|
|
if (single === null || single === undefined) {
|
|
single = true
|
|
}
|
|
|
|
return {text: {126: tokenizer}, insideSpan: {null: tokenizer}}
|
|
|
|
// Take events and resolve strikethrough.
|
|
function resolveAllStrikethrough(events, context) {
|
|
var index = -1
|
|
var strikethrough
|
|
var text
|
|
var open
|
|
var nextEvents
|
|
|
|
// Walk through all events.
|
|
while (++index < events.length) {
|
|
// Find a token that can close.
|
|
if (
|
|
events[index][0] === 'enter' &&
|
|
events[index][1].type === 'strikethroughSequenceTemporary' &&
|
|
events[index][1]._close
|
|
) {
|
|
open = index
|
|
|
|
// Now walk back to find an opener.
|
|
while (open--) {
|
|
// Find a token that can open the closer.
|
|
if (
|
|
events[open][0] === 'exit' &&
|
|
events[open][1].type === 'strikethroughSequenceTemporary' &&
|
|
events[open][1]._open &&
|
|
// If the sizes are the same:
|
|
events[index][1].end.offset - events[index][1].start.offset ===
|
|
events[open][1].end.offset - events[open][1].start.offset
|
|
) {
|
|
events[index][1].type = 'strikethroughSequence'
|
|
events[open][1].type = 'strikethroughSequence'
|
|
|
|
strikethrough = {
|
|
type: 'strikethrough',
|
|
start: shallow(events[open][1].start),
|
|
end: shallow(events[index][1].end)
|
|
}
|
|
|
|
text = {
|
|
type: 'strikethroughText',
|
|
start: shallow(events[open][1].end),
|
|
end: shallow(events[index][1].start)
|
|
}
|
|
|
|
// Opening.
|
|
nextEvents = [
|
|
['enter', strikethrough, context],
|
|
['enter', events[open][1], context],
|
|
['exit', events[open][1], context],
|
|
['enter', text, context]
|
|
]
|
|
|
|
// Between.
|
|
chunkedSplice(
|
|
nextEvents,
|
|
nextEvents.length,
|
|
0,
|
|
resolveAll(
|
|
context.parser.constructs.insideSpan.null,
|
|
events.slice(open + 1, index),
|
|
context
|
|
)
|
|
)
|
|
|
|
// Closing.
|
|
chunkedSplice(nextEvents, nextEvents.length, 0, [
|
|
['exit', text, context],
|
|
['enter', events[index][1], context],
|
|
['exit', events[index][1], context],
|
|
['exit', strikethrough, context]
|
|
])
|
|
|
|
chunkedSplice(events, open - 1, index - open + 3, nextEvents)
|
|
|
|
index = open + nextEvents.length - 2
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return removeRemainingSequences(events)
|
|
}
|
|
|
|
function removeRemainingSequences(events) {
|
|
var index = -1
|
|
var length = events.length
|
|
|
|
while (++index < length) {
|
|
if (events[index][1].type === 'strikethroughSequenceTemporary') {
|
|
events[index][1].type = 'data'
|
|
}
|
|
}
|
|
|
|
return events
|
|
}
|
|
|
|
function tokenizeStrikethrough(effects, ok, nok) {
|
|
var previous = this.previous
|
|
var events = this.events
|
|
var size = 0
|
|
|
|
return start
|
|
|
|
function start(code) {
|
|
if (
|
|
code !== 126 ||
|
|
(previous === 126 &&
|
|
events[events.length - 1][1].type !== 'characterEscape')
|
|
) {
|
|
return nok(code)
|
|
}
|
|
|
|
effects.enter('strikethroughSequenceTemporary')
|
|
return more(code)
|
|
}
|
|
|
|
function more(code) {
|
|
var before = classifyCharacter(previous)
|
|
var token
|
|
var after
|
|
|
|
if (code === 126) {
|
|
// If this is the third marker, exit.
|
|
if (size > 1) return nok(code)
|
|
effects.consume(code)
|
|
size++
|
|
return more
|
|
}
|
|
|
|
if (size < 2 && !single) return nok(code)
|
|
token = effects.exit('strikethroughSequenceTemporary')
|
|
after = classifyCharacter(code)
|
|
token._open = !after || (after === 2 && before)
|
|
token._close = !before || (before === 2 && after)
|
|
return ok(code)
|
|
}
|
|
}
|
|
}
|