|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import {push, splice} from 'micromark-util-chunked' |
|
import {classifyCharacter} from 'micromark-util-classify-character' |
|
import {resolveAll} from 'micromark-util-resolve-all' |
|
|
|
export const attention = { |
|
name: 'attention', |
|
tokenize: tokenizeAttention, |
|
resolveAll: resolveAllAttention |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
function resolveAllAttention(events, context) { |
|
let index = -1 |
|
|
|
let open |
|
|
|
let group |
|
|
|
let text |
|
|
|
let openingSequence |
|
|
|
let closingSequence |
|
|
|
let use |
|
|
|
let nextEvents |
|
|
|
let offset |
|
|
|
|
|
|
|
|
|
|
|
while (++index < events.length) { |
|
|
|
if ( |
|
events[index][0] === 'enter' && |
|
events[index][1].type === 'attentionSequence' && |
|
events[index][1]._close |
|
) { |
|
open = index |
|
|
|
|
|
while (open--) { |
|
|
|
if ( |
|
events[open][0] === 'exit' && |
|
events[open][1].type === 'attentionSequence' && |
|
events[open][1]._open && |
|
|
|
context.sliceSerialize(events[open][1]).charCodeAt(0) === |
|
context.sliceSerialize(events[index][1]).charCodeAt(0) |
|
) { |
|
|
|
|
|
|
|
|
|
if ( |
|
(events[open][1]._close || events[index][1]._open) && |
|
(events[index][1].end.offset - events[index][1].start.offset) % 3 && |
|
!( |
|
(events[open][1].end.offset - |
|
events[open][1].start.offset + |
|
events[index][1].end.offset - |
|
events[index][1].start.offset) % |
|
3 |
|
) |
|
) { |
|
continue |
|
} |
|
|
|
|
|
use = |
|
events[open][1].end.offset - events[open][1].start.offset > 1 && |
|
events[index][1].end.offset - events[index][1].start.offset > 1 |
|
? 2 |
|
: 1 |
|
const start = Object.assign({}, events[open][1].end) |
|
const end = Object.assign({}, events[index][1].start) |
|
movePoint(start, -use) |
|
movePoint(end, use) |
|
openingSequence = { |
|
type: use > 1 ? 'strongSequence' : 'emphasisSequence', |
|
start, |
|
end: Object.assign({}, events[open][1].end) |
|
} |
|
closingSequence = { |
|
type: use > 1 ? 'strongSequence' : 'emphasisSequence', |
|
start: Object.assign({}, events[index][1].start), |
|
end |
|
} |
|
text = { |
|
type: use > 1 ? 'strongText' : 'emphasisText', |
|
start: Object.assign({}, events[open][1].end), |
|
end: Object.assign({}, events[index][1].start) |
|
} |
|
group = { |
|
type: use > 1 ? 'strong' : 'emphasis', |
|
start: Object.assign({}, openingSequence.start), |
|
end: Object.assign({}, closingSequence.end) |
|
} |
|
events[open][1].end = Object.assign({}, openingSequence.start) |
|
events[index][1].start = Object.assign({}, closingSequence.end) |
|
nextEvents = [] |
|
|
|
|
|
if (events[open][1].end.offset - events[open][1].start.offset) { |
|
nextEvents = push(nextEvents, [ |
|
['enter', events[open][1], context], |
|
['exit', events[open][1], context] |
|
]) |
|
} |
|
|
|
|
|
nextEvents = push(nextEvents, [ |
|
['enter', group, context], |
|
['enter', openingSequence, context], |
|
['exit', openingSequence, context], |
|
['enter', text, context] |
|
]) |
|
|
|
|
|
|
|
|
|
nextEvents = push( |
|
nextEvents, |
|
resolveAll( |
|
context.parser.constructs.insideSpan.null, |
|
events.slice(open + 1, index), |
|
context |
|
) |
|
) |
|
|
|
|
|
nextEvents = push(nextEvents, [ |
|
['exit', text, context], |
|
['enter', closingSequence, context], |
|
['exit', closingSequence, context], |
|
['exit', group, context] |
|
]) |
|
|
|
|
|
if (events[index][1].end.offset - events[index][1].start.offset) { |
|
offset = 2 |
|
nextEvents = push(nextEvents, [ |
|
['enter', events[index][1], context], |
|
['exit', events[index][1], context] |
|
]) |
|
} else { |
|
offset = 0 |
|
} |
|
splice(events, open - 1, index - open + 3, nextEvents) |
|
index = open + nextEvents.length - offset - 2 |
|
break |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
index = -1 |
|
while (++index < events.length) { |
|
if (events[index][1].type === 'attentionSequence') { |
|
events[index][1].type = 'data' |
|
} |
|
} |
|
return events |
|
} |
|
|
|
|
|
|
|
|
|
|
|
function tokenizeAttention(effects, ok) { |
|
const attentionMarkers = this.parser.constructs.attentionMarkers.null |
|
const previous = this.previous |
|
const before = classifyCharacter(previous) |
|
|
|
|
|
let marker |
|
return start |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function start(code) { |
|
marker = code |
|
effects.enter('attentionSequence') |
|
return inside(code) |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function inside(code) { |
|
if (code === marker) { |
|
effects.consume(code) |
|
return inside |
|
} |
|
const token = effects.exit('attentionSequence') |
|
|
|
|
|
const after = classifyCharacter(code) |
|
|
|
|
|
|
|
const open = |
|
!after || (after === 2 && before) || attentionMarkers.includes(code) |
|
const close = |
|
!before || (before === 2 && after) || attentionMarkers.includes(previous) |
|
token._open = Boolean(marker === 42 ? open : open && (before || !close)) |
|
token._close = Boolean(marker === 42 ? close : close && (after || !open)) |
|
return ok(code) |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function movePoint(point, offset) { |
|
point.column += offset |
|
point.offset += offset |
|
point._bufferIndex += offset |
|
} |
|
|