1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
// Process *this* and _that_
//
'use strict';
// Insert each marker as a separate text token, and add it to delimiter list
//
module.exports.tokenize = function emphasis(state, silent) {
var i, scanned, token,
start = state.pos,
marker = state.src.charCodeAt(start);
if (silent) { return false; }
if (marker !== 0x5F /* _ */ && marker !== 0x2A /* * */) { return false; }
scanned = state.scanDelims(state.pos, marker === 0x2A);
for (i = 0; i < scanned.length; i++) {
token = state.push('text', '', 0);
token.content = String.fromCharCode(marker);
state.delimiters.push({
// Char code of the starting marker (number).
//
marker: marker,
// Total length of these series of delimiters.
//
length: scanned.length,
// A position of the token this delimiter corresponds to.
//
token: state.tokens.length - 1,
// If this delimiter is matched as a valid opener, `end` will be
// equal to its position, otherwise it's `-1`.
//
end: -1,
// Boolean flags that determine if this delimiter could open or close
// an emphasis.
//
open: scanned.can_open,
close: scanned.can_close
});
}
state.pos += scanned.length;
return true;
};
function postProcess(state, delimiters) {
var i,
startDelim,
endDelim,
token,
ch,
isStrong,
max = delimiters.length;
for (i = max - 1; i >= 0; i--) {
startDelim = delimiters[i];
if (startDelim.marker !== 0x5F/* _ */ && startDelim.marker !== 0x2A/* * */) {
continue;
}
// Process only opening markers
if (startDelim.end === -1) {
continue;
}
endDelim = delimiters[startDelim.end];
// If the previous delimiter has the same marker and is adjacent to this one,
// merge those into one strong delimiter.
//
// `<em><em>whatever</em></em>` -> `<strong>whatever</strong>`
//
isStrong = i > 0 &&
delimiters[i - 1].end === startDelim.end + 1 &&
// check that first two markers match and adjacent
delimiters[i - 1].marker === startDelim.marker &&
delimiters[i - 1].token === startDelim.token - 1 &&
// check that last two markers are adjacent (we can safely assume they match)
delimiters[startDelim.end + 1].token === endDelim.token + 1;
ch = String.fromCharCode(startDelim.marker);
token = state.tokens[startDelim.token];
token.type = isStrong ? 'strong_open' : 'em_open';
token.tag = isStrong ? 'strong' : 'em';
token.nesting = 1;
token.markup = isStrong ? ch + ch : ch;
token.content = '';
token = state.tokens[endDelim.token];
token.type = isStrong ? 'strong_close' : 'em_close';
token.tag = isStrong ? 'strong' : 'em';
token.nesting = -1;
token.markup = isStrong ? ch + ch : ch;
token.content = '';
if (isStrong) {
state.tokens[delimiters[i - 1].token].content = '';
state.tokens[delimiters[startDelim.end + 1].token].content = '';
i--;
}
}
}
// Walk through delimiter list and replace text tokens with tags
//
module.exports.postProcess = function emphasis(state) {
var curr,
tokens_meta = state.tokens_meta,
max = state.tokens_meta.length;
postProcess(state, state.delimiters);
for (curr = 0; curr < max; curr++) {
if (tokens_meta[curr] && tokens_meta[curr].delimiters) {
postProcess(state, tokens_meta[curr].delimiters);
}
}
};
|