@peaceroad/markdown-it-strong-ja 0.3.5 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -1,45 +1,98 @@
1
+ const REG_ASTERISKS = /^\*+$/
2
+ const REG_ATTRS = /{[^{}\n!@#%^&*()]+?}$/
3
+ const REG_PUNCTUATION = /[!-/:-@[-`{-~ ]/
4
+
1
5
  const hasBackslash = (state, start) => {
2
6
  let slashNum = 0
3
7
  let i = start - 1
8
+ const src = state.src
4
9
  while(i >= 0) {
5
- /// if (state.src.charCodeAt(i) === 0x2A) { i--; continue }
6
- if (state.src.charCodeAt(i) === 0x5C) { slashNum++; i--; continue }
10
+ if (src.charCodeAt(i) === 0x5C) { slashNum++; i--; continue }
7
11
  break
8
12
  }
9
- return slashNum % 2 === 1 ? true : false
13
+ return slashNum % 2 === 1
10
14
  }
11
15
 
12
- const setToken = (state, inlines) => {
16
+ const setToken = (state, inlines, opt) => {
17
+ const src = state.src
13
18
  let i = 0
19
+ let attrsIsText = {
20
+ val: false,
21
+ tag: '',
22
+ }
14
23
  while (i < inlines.length) {
15
24
  let type = inlines[i].type
25
+ //console.log(i, type)
16
26
  const tag = type.replace(/(?:_open|_close)$/, '')
17
27
 
18
28
  if (/_open$/.test(type)) {
19
29
  const startToken = state.push(type, tag, 1)
20
30
  startToken.markup = tag === 'strong' ? '**' : '*'
31
+ attrsIsText = {
32
+ val: true,
33
+ tag: tag,
34
+ }
21
35
  }
22
36
 
23
37
  if (type === 'html_inline') {
24
38
  type = 'text'
25
39
  }
26
40
  if (type === 'text') {
27
- const content = state.src.slice(inlines[i].s, inlines[i].e + 1)
28
- if (/^\**$/.test(content)) {
41
+ let content = src.slice(inlines[i].s, inlines[i].e + 1)
42
+ //console.log('content: ' + content)
43
+ if (REG_ASTERISKS.test(content)) {
29
44
  //console.log('asterisk process::')
30
45
  const asteriskToken = state.push(type, '', 0)
31
46
  asteriskToken.content = content
32
47
  i++
33
48
  continue
34
49
  }
50
+ if (opt.mditAttrs && attrsIsText.val && i + 1 < inlines.length) {
51
+ const hasImmediatelyAfterAsteriskClose = inlines[i+1].type === attrsIsText.tag + '_close'
52
+ //console.log(hasImmediatelyAfterAsteriskClose, inlines[i+1].type, /^[\s\S]*{[^{}\n!@#%^&*()]+?}$/.test(content))
53
+ if (hasImmediatelyAfterAsteriskClose && REG_ATTRS.test(content)) {
54
+ const attrsToken = state.push(type, '', 0)
55
+
56
+ const hasBackslashBeforeCurlyAttribute = content.match(/(\\+){/)
57
+ if (hasBackslashBeforeCurlyAttribute) {
58
+ if (hasBackslashBeforeCurlyAttribute[1].length === 1) {
59
+ attrsToken.content = content.replace(/\\{/, '{')
60
+ } else {
61
+ let backSlashNum = Math.floor(hasBackslashBeforeCurlyAttribute[1].length / 2)
62
+ let k = 0
63
+ let backSlash = ''
64
+ while (k < backSlashNum) {
65
+ backSlash += '\\'
66
+ k++
67
+ }
68
+ //console.log(backSlashNum, backSlash)
69
+ attrsToken.content = content.replace(/\\+{/, backSlash + '{')
70
+ }
71
+ } else {
72
+ attrsToken.content = content
73
+ }
74
+ attrsIsText.val = false
75
+ i++
76
+ continue
77
+ }
78
+ }
35
79
 
36
80
  const childTokens = state.md.parseInline(content, state.env)
81
+ //console.log(childTokens)
82
+ //console.log(childTokens[0].children)
37
83
  if (childTokens[0] && childTokens[0].children) {
38
- //console.log(state.tokens)
39
- //console.log(state.tokens[state.tokens.length - 1])
40
- state.tokens[state.tokens.length - 1].children = childTokens[0].children
41
- childTokens[0].children.forEach(t => {
42
- //console.log('t.type: ' + t.type + ', t.tag: ' + t.tag + ', t.nesting: ' + t.nesting)
84
+ let j = 0
85
+ while (j < childTokens[0].children.length) {
86
+ const t = childTokens[0].children[j]
87
+ if (t.type === 'softbreak') {
88
+ t.type = 'text'
89
+ t.tag = ''
90
+ t.content = '\n'
91
+ }
92
+ if (!opt.mditAttrs && t.tag === 'br') {
93
+ t.tag = ''
94
+ t.content = '\n'
95
+ }
43
96
  const token = state.push(t.type, t.tag, t.nesting)
44
97
  token.attrs = t.attrs
45
98
  token.map = t.map
@@ -51,20 +104,25 @@ const setToken = (state, inlines) => {
51
104
  token.meta = t.meta
52
105
  token.block = t.block
53
106
  token.hidden = t.hidden
54
- })
107
+ j++
108
+ }
55
109
  }
56
110
  }
57
111
 
58
112
  if (/_close$/.test(type)) {
59
113
  const closeToken = state.push(type, tag, -1)
60
114
  closeToken.markup = tag === 'strong' ? '**' : '*'
115
+ attrsIsText = {
116
+ val: false,
117
+ tag: '',
118
+ }
61
119
  }
62
120
 
63
121
  i++
64
122
  }
65
123
  }
66
124
 
67
- const inlinesPush = (inlines, s, e, len, type, tag, tagType) => {
125
+ const pushInlines = (inlines, s, e, len, type, tag, tagType) => {
68
126
  const inline = {
69
127
  s: s,
70
128
  sp: s,
@@ -72,6 +130,7 @@ const inlinesPush = (inlines, s, e, len, type, tag, tagType) => {
72
130
  ep: e,
73
131
  len: len,
74
132
  type: type,
133
+ check: type === 'text' ? true : false,
75
134
  }
76
135
  if (tag) inline.tag = [tag, tagType]
77
136
  inlines.push(inline)
@@ -79,13 +138,14 @@ const inlinesPush = (inlines, s, e, len, type, tag, tagType) => {
79
138
 
80
139
  const hasNextSymbol = (state, n, max, symbol, noMark) => {
81
140
  let nextSymbolPos = -1
82
- if (state.src.charCodeAt(n) === symbol && !hasBackslash(state, n)) {
141
+ const src = state.src
142
+ if (src.charCodeAt(n) === symbol && !hasBackslash(state, n)) {
83
143
  let i = n + 1
84
144
  let tempNoMark = noMark
85
145
  while (i < max) {
86
- tempNoMark += state.src[i]
87
- if (state.src.charCodeAt(i) === symbol && !hasBackslash(state, i)) {
88
- noMark += state.src.substring(n, i + 1)
146
+ tempNoMark += src[i]
147
+ if (src.charCodeAt(i) === symbol && !hasBackslash(state, i)) {
148
+ noMark += src.substring(n, i + 1)
89
149
  nextSymbolPos = i
90
150
  break
91
151
  }
@@ -96,26 +156,29 @@ const hasNextSymbol = (state, n, max, symbol, noMark) => {
96
156
  }
97
157
 
98
158
  const createInlines = (state, start, max, opt) => {
159
+ const src = state.src
160
+ const srcLen = max;
99
161
  let n = start
100
162
  let inlines = []
101
163
  let noMark = ''
102
164
  let textStart = n
103
- while (n < max) {
165
+ while (n < srcLen) {
166
+ //console.log('n: ' + n + ', state.src[n]: ' + state.src[n] + ', noMark: ' + noMark)
104
167
  let nextSymbolPos = -1;
105
- [nextSymbolPos, noMark] = hasNextSymbol(state, n, max, 0x60, noMark) // '`'
168
+ [nextSymbolPos, noMark] = hasNextSymbol(state, n, srcLen, 0x60, noMark) // '`'
106
169
  if (nextSymbolPos !== -1) {
107
- if (nextSymbolPos === max - 1) {
108
- inlinesPush(inlines, textStart, nextSymbolPos, nextSymbolPos - textStart + 1, 'text')
170
+ if (nextSymbolPos === srcLen - 1) {
171
+ pushInlines(inlines, textStart, nextSymbolPos, nextSymbolPos - textStart + 1, 'text')
109
172
  break
110
173
  }
111
174
  n = nextSymbolPos + 1
112
175
  continue
113
176
  }
114
177
  if (opt.dollarMath) {
115
- [nextSymbolPos, noMark] = hasNextSymbol(state, n, max, 0x24, noMark) // '$'
178
+ [nextSymbolPos, noMark] = hasNextSymbol(state, n, srcLen, 0x24, noMark) // '$'
116
179
  if (nextSymbolPos !== -1) {
117
- if (nextSymbolPos === max - 1) {
118
- inlinesPush(inlines, textStart, nextSymbolPos, nextSymbolPos - textStart + 1, 'text')
180
+ if (nextSymbolPos === srcLen - 1) {
181
+ pushInlines(inlines, textStart, nextSymbolPos, nextSymbolPos - textStart + 1, 'text')
119
182
  break
120
183
  }
121
184
  n = nextSymbolPos + 1
@@ -124,14 +187,15 @@ const createInlines = (state, start, max, opt) => {
124
187
  }
125
188
 
126
189
  if (state.md.options.html) {
127
- if (state.src.charCodeAt(n) === 0x3C && !hasBackslash(state, n)) { // '<'
190
+ if (src.charCodeAt(n) === 0x3C && !hasBackslash(state, n)) { // '<'
128
191
  let i = n + 1
129
- while (i < max) {
130
- if (state.src.charCodeAt(i) === 0x3E && !hasBackslash(state, i)) { // '>'
192
+ while (i < srcLen) {
193
+ if (src.charCodeAt(i) === 0x3E && !hasBackslash(state, i)) { // '>'
131
194
  if (noMark.length !== 0) {
132
- inlinesPush(inlines, textStart, n - 1, n - textStart, 'text')
195
+ pushInlines(inlines, textStart, n - 1, n - textStart, 'text')
196
+ noMark = ''
133
197
  }
134
- let tag = state.src.slice(n + 1, i)
198
+ let tag = src.slice(n + 1, i)
135
199
  let tagType = ''
136
200
  if (/^\//.test(tag)) {
137
201
  tag = tag.slice(1)
@@ -139,7 +203,7 @@ const createInlines = (state, start, max, opt) => {
139
203
  } else {
140
204
  tagType = 'open'
141
205
  }
142
- inlinesPush(inlines, n, i, i - n + 1, 'html_inline', tag, tagType)
206
+ pushInlines(inlines, n, i, i - n + 1, 'html_inline', tag, tagType)
143
207
  textStart = i + 1
144
208
  break
145
209
  }
@@ -149,31 +213,34 @@ const createInlines = (state, start, max, opt) => {
149
213
  continue
150
214
  }
151
215
  }
152
- if (state.src.charCodeAt(n) === 0x2A && !hasBackslash(state, n)) { // '*'
153
- if (n !== 0) {
154
- inlinesPush(inlines, textStart, n - 1, n - textStart, 'text')
216
+
217
+ if (src.charCodeAt(n) === 0x2A && !hasBackslash(state, n)) { // '*'
218
+ if (n !== 0 && noMark.length !== 0) {
219
+ pushInlines(inlines, textStart, n - 1, n - textStart, 'text')
220
+ noMark = ''
155
221
  }
156
- if (n === max - 1) {
157
- inlinesPush(inlines, n, n, 1 , '')
222
+ if (n === srcLen - 1) {
223
+ pushInlines(inlines, n, n, 1 , '')
158
224
  break
159
225
  }
160
226
  let i = n + 1
161
- while (i < max) {
162
- if (state.src.charCodeAt(i) === 0x2A) {
163
- if (i === max - 1) inlinesPush(inlines, n, i, i - n + 1 , '')
227
+ while (i < srcLen) {
228
+ if (src.charCodeAt(i) === 0x2A) {
229
+ if (i === srcLen - 1) pushInlines(inlines, n, i, i - n + 1 , '')
164
230
  i++
165
231
  continue
166
232
  }
167
- inlinesPush(inlines, n, i - 1, i - n, '')
233
+ pushInlines(inlines, n, i - 1, i - n, '')
168
234
  textStart = i
169
235
  break
170
236
  }
171
237
  n = i
172
238
  continue
173
239
  }
174
- noMark += state.src[n]
175
- if (n === max - 1) {
176
- inlinesPush(inlines, textStart, n, n - textStart + 1, 'text')
240
+
241
+ noMark += src[n]
242
+ if (n === srcLen - 1) {
243
+ pushInlines(inlines, textStart, n, n - textStart + 1, 'text')
177
244
  break
178
245
  }
179
246
  n++
@@ -181,159 +248,214 @@ const createInlines = (state, start, max, opt) => {
181
248
  return inlines
182
249
  }
183
250
 
184
- const marksPush = (marks, nest, s, e, len, outsideLen, type) => {
185
- //console.log('before marks:')
186
- //console.log(marks)
187
- const np = {
188
- nest: nest,
189
- s: s,
190
- e: e,
191
- len: len,
192
- oLen: outsideLen,
193
- type: type,
194
- }
195
- let i = marks.findIndex(o => o.s > s)
196
- if (i === -1) {
197
- marks.push(np)
198
- } else {
199
- marks.splice(i, 0, np)
251
+ const pushMark = (marks, opts) => {
252
+ //binary search
253
+ let left = 0, right = marks.length
254
+ while (left < right) {
255
+ const mid = (left + right) >> 1
256
+ if (marks[mid].s > opts.s) {
257
+ right = mid
258
+ } else {
259
+ left = mid + 1
260
+ }
200
261
  }
262
+ marks.splice(left, 0, { ...opts });
201
263
  }
202
264
 
203
- const setStrong = (inlines, marks, n, memo) => {
265
+ const setStrong = (state, inlines, marks, n, memo, opt) => {
204
266
  let i = n + 1
205
267
  let j = 0
206
268
  let nest = 0
207
- let insideTagsIsClose = 1
269
+ let insideTagsIsClose = 1 // 1: closed, 0: open still, -1: error
208
270
  while (i < inlines.length) {
209
- if (inlines[i].len === 0) { i++; continue }
210
- if (memo.html) {
211
- if (inlines[i].type === 'html_inline') {
212
- insideTagsIsClose = isJumpTag(inlines, i, memo)
213
- //console.log('insideTagsIsClose: ' + insideTagsIsClose )
214
- if (insideTagsIsClose === -1) return n, nest, memo
215
- if (insideTagsIsClose === 0) { i++; continue }
216
- }
271
+ //console.log('[strong] i: ' + i + ', inlines[i].len: ' + inlines[i].len + ', inlines[i].type: ' + inlines[i].type)
272
+ if (inlines[i].len === 0 || inlines[i].check) { i++; continue }
273
+ if (inlines[i].type === 'html_inline') {
274
+ inlines[i].check = true
275
+ insideTagsIsClose = checkInsideTags(inlines, i, memo)
276
+ //console.log(' nest: ' + nest + ', insideTagsIsClose: ' + insideTagsIsClose )
277
+ if (insideTagsIsClose === -1) return n, nest
278
+ if (insideTagsIsClose === 0) { i++; continue }
217
279
  }
218
280
  if (inlines[i].type !== '') { i++; continue }
219
281
 
220
- //console.log('n: ' + n + ' [strong]: inlines[n].len: ' + inlines[n].len + ', i: ' + i + ', inlines[i].len: ' + inlines[i].len)
221
-
222
282
  nest = checkNest(inlines, marks, n, i)
223
- //console.log('n: ' + n + ' [strong]: nest: ' + nest)
224
- if (nest === -1) return n, nest, memo
283
+ //console.log(' check nest: ' + nest)
284
+ if (nest === -1) return n, nest
285
+
225
286
  if (inlines[i].len === 1 && inlines[n].len > 2) {
226
- //console.log('n: ' + n + ' [strong]: check em inside strong: ' + nest)
227
- marksPush(marks, nest, inlines[n].ep, inlines[n].ep, 1, inlines[n].len - 1, 'em_open')
228
- marksPush(marks, nest, inlines[i].sp, inlines[i].ep, 1, inlines[i].len - 1, 'em_close')
287
+ //console.log(' check em inside strong:: i: ' + i)
288
+ pushMark(marks, {
289
+ nest: nest,
290
+ s: inlines[n].ep,
291
+ e: inlines[n].ep,
292
+ len: 1,
293
+ oLen: inlines[n].len - 1,
294
+ type: 'em_open'
295
+ })
296
+ pushMark(marks, {
297
+ nest: nest,
298
+ s: inlines[i].sp,
299
+ e: inlines[i].ep,
300
+ len: 1,
301
+ oLen: inlines[i].len - 1,
302
+ type: 'em_close'
303
+ })
229
304
  inlines[n].len -= 1
230
305
  inlines[n].ep -= 1
231
- inlines[i].len = 0
232
- inlines[i].sp += 1
233
- if (i++ < inlines.length) {
234
- i++
235
- nest++
236
- } else {
237
- return n, nest, memo
306
+ inlines[i].len -= 1
307
+ if (inlines[i].len > 0) inlines[i].sp += 1
308
+ if (insideTagsIsClose === 1) {
309
+ n, nest = setEm(state, inlines, marks, n, memo, opt)
238
310
  }
239
- if (i > inlines.length - 1) return n, nest, memo
240
- }
241
-
242
- //console.log('memo.html: ' + memo.html + 'insideTagsIsClose: ' + insideTagsIsClose + 'inlines[i].len: ' + inlines[i].len)
243
- if (memo.html && !insideTagsIsClose && inlines[i].len !== 1) {
244
- i++; continue
311
+ //console.log(marks)
245
312
  }
313
+ //console.log(' check len:: inlines[n].len: ' + inlines[n].len + ', inlines[i].len: ' + inlines[i].len)
246
314
  let strongNum = Math.trunc(Math.min(inlines[n].len, inlines[i].len) / 2)
247
315
 
248
316
  if (inlines[i].len > 1) {
249
- //console.log('n: ' + n + ' [strong]: normal push, nest: ' + nest)
317
+ //console.log(' hasPunctuation: ' + hasPunctuation(state, inlines, n, i) + ', memo.inlineMarkEnd: ' + memo.inlineMarkEnd)
318
+ if (hasPunctuation(state, inlines, n, i)) {
319
+ if (memo.inlineMarkEnd) {
320
+ //console.log('check nest em.')
321
+ //console.log('~~~~~~~~~~~~~~~~~')
322
+ marks.push(...createMarks(state, inlines, i, inlines.length - 1, memo, opt))
323
+ //console.log('~~~~~~~~~~~~~~~~~')
324
+ if (inlines[i].len === 0) { i++; continue }
325
+ } else {
326
+ return n, nest
327
+ }
328
+ }
329
+ //console.log(' ===> strong normal push. n: ' + n + ', i: ' + i + ' , nest: ' + nest + ',strongNum: ' + strongNum)
330
+
250
331
  j = 0
251
332
  while (j < strongNum) {
252
- //console.log('j: ' + j + ', inlines[i].sp: ' + inlines[i].sp)
253
- marksPush(marks, nest + strongNum - 1 - j , inlines[n].ep - 1, inlines[n].ep, 2, inlines[n].len - 2,'strong_open')
333
+ //console.log(' - j: ' + j + ', inlines[i].sp: ' + inlines[i].sp)
334
+ pushMark(marks, {
335
+ nest: nest + strongNum - 1 - j,
336
+ s: inlines[n].ep - 1,
337
+ e: inlines[n].ep,
338
+ len: 2,
339
+ oLen: inlines[n].len - 2,
340
+ type: 'strong_open'
341
+ })
254
342
  inlines[n].ep -= 2
255
343
  inlines[n].len -= 2
256
- marksPush(marks, nest + strongNum - 1 - j, inlines[i].sp, inlines[i].sp + 1, 2, inlines[i].len - 2,'strong_close')
344
+ pushMark(marks, {
345
+ nest: nest + strongNum - 1 - j,
346
+ s: inlines[i].sp,
347
+ e: inlines[i].sp + 1,
348
+ len: 2,
349
+ oLen: inlines[i].len - 2,
350
+ type: 'strong_close'
351
+ })
257
352
  inlines[i].sp += 2
258
353
  inlines[i].len -= 2
259
- //console.log(marks)
260
354
  j++
261
355
  }
262
- if (inlines[n].len === 0) return n, nest, memo
356
+ if (inlines[n].len === 0) return n, nest
263
357
  }
264
358
 
265
- //console.log('len: ', inlines[n].len, inlines[i].len)
266
- if ((inlines[n].len > 0 && inlines[i] === 1) || (inlines[n].len === 1 && inlines[i].len > 0)) {
267
- //console.log('check em that warp strong.')
359
+ if (inlines[n].len === 1 && inlines[i].len > 0) {
360
+ //console.log(' check em that warp strong.')
268
361
  nest++
269
- n, nest, memo = setEm(inlines, marks, n, memo, nest)
270
- if (memo.hasEmThatWrapStrong) {
271
- //console.log('set em that wrap strong.')
272
- let k = 0
273
- while (k < strongNum) {
274
- marks[marks.length - 2 - k * 2 - 1].nest += 1
275
- marks[marks.length - 2 - k * 2].nest += 1
276
- k++
277
- }
278
- }
362
+ n, nest = setEm(state, inlines, marks, n, memo, opt, nest)
279
363
  }
280
- if (inlines[n].len === 0) return n, nest, memo
364
+
281
365
  i++
282
366
  }
283
- return n, nest, memo
367
+
368
+ if (n == 0 && memo.inlineMarkEnd) {
369
+ //console.log('check nest em(inlineMarkEnd).')
370
+ //console.log('===============================')
371
+ marks.push(...createMarks(state, inlines, n + 1 , inlines.length - 1, memo, opt))
372
+ //console.log(marks)
373
+ //console.log('===============================')
374
+ }
375
+ return n, nest
284
376
  }
285
377
 
286
- const isJumpTag = (inlines, n, memo) => {
287
- //console.log(n, 'before::memo.htmlTags: ' + JSON.stringify(memo.htmlTags))
288
- const hasSet = Object.keys(memo.htmlTags).some(tag => {
289
- if (tag === inlines[n].tag[0]) {
290
- if (inlines[n].tag[1] === 'open') {
291
- memo.htmlTags[tag]++ }
292
- else {
293
- memo.htmlTags[tag]--
294
- }
295
- return true
296
- }
297
- return false
298
- })
299
- if (!hasSet && !memo.htmlTags[inlines[n].tag[0]]) {
300
- if (inlines[n].tag[1] === 'close') {
301
- memo.htmlTags = {}
302
- return -1
303
- }
304
- memo.htmlTags[inlines[n].tag[0]] = 1
378
+ const checkInsideTags = (inlines, i, memo) => {
379
+ //console.log('isJumTag before::memo.htmlTags: ' + JSON.stringify(memo.htmlTags))
380
+ if (inlines[i].tag === undefined) return 0
381
+ const tagName = inlines[i].tag[0].toLowerCase()
382
+ if (memo.htmlTags[tagName] === undefined) {
383
+ memo.htmlTags[tagName] = 0
305
384
  }
306
- //console.log(n, 'after::memo.htmlTags: ' + JSON.stringify(memo.htmlTags))
385
+ //console.log('memo.htmlTags: ' + JSON.stringify(memo.htmlTags) + ', inlines[i]: ' + JSON.stringify(inlines[i]) + ', inlines[i]')
386
+ if (inlines[i].tag[1] === 'open') {
387
+ memo.htmlTags[tagName] += 1
388
+ }
389
+ if (inlines[i].tag[1] === 'close') {
390
+ memo.htmlTags[tagName] -= 1
391
+ }
392
+ //console.log(' i: ' + i + ', tagName: ' + tagName + ', memo.htmlTags[tagName]: ' + memo.htmlTags[tagName] + ', prevHtmlTags[tagName]: ' + prevHtmlTags[tagName])
393
+ if (memo.htmlTags[tagName] < 0) {
394
+ return -1
395
+ }
396
+ //console.log('isJumTag after::memo.htmlTags: ' + JSON.stringify(memo.htmlTags))
307
397
  const closeAllTags = Object.values(memo.htmlTags).every(val => val === 0)
308
- //console.log('closeAllTags: ' + closeAllTags)
309
398
  if (closeAllTags) return 1
310
- //memo.htmlTags = {}
311
399
  return 0
312
400
  }
313
401
 
314
- const setEm = (inlines, marks, n, memo, sNest) => {
402
+ const isPunctuation = (ch) => {
403
+ return REG_PUNCTUATION.test(ch)
404
+ }
405
+
406
+ const hasPunctuation = (state, inlines, n, i) => {
407
+ const src = state.src
408
+ const openNextChar = isPunctuation(src[inlines[n].e + 1] || '')
409
+ //const openPrevChar = isPunctuation(src[inlines[n].s - 1] || '') || n === 0
410
+ let closePrevChar = isPunctuation(src[inlines[i].s - 1] || '')
411
+ if (i + 1 < inlines.length) {
412
+ //closePrevChar = closePrevChar && inlines[i+1] !== 'html_inline'
413
+ }
414
+ let closeNextChar = isPunctuation(src[inlines[i].e + 1] || '') || i === inlines.length - 1
415
+ //const lastCharIsAsterisk = memo.inlineMarkEnd
416
+ //const firstCharIsAsterisk = memo.inlineMarkStart
417
+
418
+ //console.log('openPrevChar: ' + openPrevChar + ', openNextChar: ' + openNextChar + ', closePrevChar: ' + closePrevChar + ', closeNextChar: ' + closeNextChar + ', lastCharIsAsterisk: ' + lastCharIsAsterisk + ', firstCharIsAsterisk: ' + firstCharIsAsterisk + ', next condition: ' + ((openNextChar || closePrevChar) && !closeNextChar))
419
+ //if ((openNextChar || closePrevChar) && !closeNextChar) {
420
+ if ((openNextChar || closePrevChar) && !closeNextChar) {
421
+ return true
422
+ } else {
423
+ return false
424
+ }
425
+ }
426
+
427
+ const setEm = (state, inlines, marks, n, memo, opt, sNest) => {
315
428
  let i = n + 1
316
429
  let nest = 0
317
430
  let strongPNum = 0
318
431
  let insideTagsIsClose = 1
319
432
  while (i < inlines.length) {
320
- if (inlines[i].len === 0) { i++; continue }
321
- if (memo.isEm && memo.html) {
322
- if (inlines[i].type === 'html_inline') {
323
- insideTagsIsClose = isJumpTag(inlines, i, memo)
324
- //console.log('insideTagsIsClose: ' + insideTagsIsClose )
325
- if (insideTagsIsClose === -1) return n, nest, memo
326
- if (insideTagsIsClose === 0) { i++; continue }
327
- }
433
+ //console.log('[em] i: ' + i + ', src: ' + state.src.slice(inlines[i].sp, inlines[i].ep + 1) + ', inlines[i]: ' + JSON.stringify(inlines[i]))
434
+ //console.log(inlines[i].type, JSON.stringify(memo.htmlTags))
435
+ if (inlines[i].len === 0 || inlines[i].check) { i++; continue }
436
+ if (!sNest && inlines[i].type === 'html_inline') {
437
+ inlines.check = true
438
+ insideTagsIsClose = checkInsideTags(inlines, i, memo)
439
+ //console.log(' i: ' + i + ', insideTagsIsClose: ' + insideTagsIsClose)
440
+ if (insideTagsIsClose === -1) return n, nest
441
+ if (insideTagsIsClose === 0) { i++; continue }
328
442
  }
329
443
  if (inlines[i].type !== '') { i++; continue }
330
444
 
331
445
  const emNum = Math.min(inlines[n].len, inlines[i].len)
332
- if (memo.isEm && emNum !== 1) return n, sNest, memo
333
- //console.log('n: ' + n + ' [em]: inlines[n].len: ' + inlines[n].len + ', i: ' + i, ', inlines[i].len: ' + inlines[i].len + ', isEm: ' + memo.isEm)
334
- //console.log(marks)
335
446
 
336
- if (memo.isEm && inlines[i].len === 2) {
447
+ //console.log('sNest: ' + sNest + ', emNum: ' + emNum)
448
+ if (!sNest && emNum !== 1) return n, sNest, memo
449
+
450
+ const hasMarkersAtStartAndEnd = (i) => {
451
+ let flag = memo.inlineMarkStart
452
+ if (!flag) return false
453
+ inlines.length - 1 === i ? flag = true : flag = false
454
+ if (!flag) return false
455
+ inlines[i].len > 1 ? flag = true : flag = false
456
+ return flag
457
+ }
458
+ if (!sNest && inlines[i].len === 2 && !hasMarkersAtStartAndEnd(i)) {
337
459
  strongPNum++
338
460
  i++
339
461
  continue
@@ -344,47 +466,83 @@ const setEm = (inlines, marks, n, memo, sNest) => {
344
466
  } else {
345
467
  nest = checkNest(inlines, marks, n, i)
346
468
  }
347
- //console.log('n: ' + n + ' [em]: nest: ' + nest)
348
- if (nest === -1) return n, nest, memo
469
+ //console.log(' nest: ' + nest + ', emNum: ' + emNum)
470
+ if (nest === -1) return n, nest
349
471
 
350
472
  if (emNum === 1) {
351
- //console.log(n, i, 'insideTagsIsClose: ' + insideTagsIsClose)
352
- if (memo.html && !insideTagsIsClose && inlines[i].len !== 2) {
473
+ //console.log(' hasPunctuation: ' + hasPunctuation(state, inlines, n, i) + ', memo.inlineMarkEnd: ' + memo.inlineMarkEnd)
474
+ if (hasPunctuation(state, inlines, n, i)) {
475
+ if (memo.inlineMarkEnd) {
476
+ //console.log('check nest em.')
477
+ //console.log('~~~~~~~~~~~~~~~~~')
478
+ marks.push(...createMarks(state, inlines, i, inlines.length - 1, memo, opt))
479
+ //console.log('~~~~~~~~~~~~~~~~~')
480
+
481
+ if (inlines[i].len === 0) { i++; continue }
482
+ } else {
483
+ return n, nest
484
+ }
485
+ }
486
+ //console.log('inlines[i].len: ' + inlines[i].len)
487
+ if (inlines[i].len < 1) { // memo.html
353
488
  i++; continue;
354
489
  }
355
- //console.log('n: ' + n + ' [em]: normal push, nest: ' + nest)
356
- //console.log('strongPNum: ' + strongPNum)
357
- //console.log(inlines[n].ep, inlines[n].sp, inlines[n].s)
358
490
 
359
- marksPush(marks, nest, inlines[n].ep, inlines[n].ep, 1, inlines[n].len - 1, 'em_open')
491
+ //console.log(' ===> em Normal push. n: ' + n + ', i: ' + i + ', nest: ' + nest, ', strongPNum: ' + strongPNum)
492
+ //console.log(inlines[n].ep, inlines[n].sp, inlines[n].s)
493
+ pushMark(marks, {
494
+ nest: nest,
495
+ s: inlines[n].ep,
496
+ e: inlines[n].ep,
497
+ len: 1,
498
+ oLen: inlines[n].len - 1,
499
+ type: 'em_open'
500
+ })
360
501
  inlines[n].ep -= 1
361
502
  inlines[n].len -= 1
362
503
 
363
504
  if (strongPNum % 2 === 0 || inlines[i].len < 2) {
364
- marksPush(marks, nest, inlines[i].sp, inlines[i].sp, 1, inlines[i].len - 1, 'em_close')
505
+ pushMark(marks, {
506
+ nest: nest,
507
+ s: inlines[i].sp,
508
+ e: inlines[i].sp,
509
+ len: 1,
510
+ oLen: inlines[i].len - 1,
511
+ type: 'em_close'
512
+ })
365
513
  inlines[i].sp += 1
366
514
  } else {
367
- marksPush(marks, nest, inlines[i].ep, inlines[i].ep, 1, inlines[i].len - 1, 'em_close')
515
+ pushMark(marks, {
516
+ nest: nest,
517
+ s: inlines[i].ep,
518
+ e: inlines[i].ep,
519
+ len: 1,
520
+ oLen: inlines[i].len - 1,
521
+ type: 'em_close'
522
+ })
368
523
  inlines[i].sp = inlines[i].ep - 1
369
524
  inlines[i].ep -= 1
370
-
371
525
  }
372
526
  inlines[i].len -= 1
373
527
  //console.log(marks)
374
- if (!memo.isEm) memo.hasEmThatWrapStrong = true
375
- if (inlines[n].len === 0) return n, nest, memo
528
+ if (inlines[n].len === 0) return n, nest
376
529
  }
377
530
 
378
531
  i++
379
532
  }
380
- return n, nest, memo
533
+ return n, nest
381
534
  }
382
535
 
383
536
  const setText = (inlines, marks, n, nest) => {
384
537
  //console.log('n: ' + n + ' [text]: inlines[n].len: ' + inlines[n].len)
385
- //marksPush(marks, -1, inlines[n].sp + 1, inlines[n].ep, inlines[n].len, -1, 'text')
386
- marksPush(marks, nest, inlines[n].sp, inlines[n].ep, inlines[n].len, -1, 'text')
387
- //inlines[n].sp += 1
538
+ pushMark(marks, {
539
+ nest: nest,
540
+ s: inlines[n].sp,
541
+ e: inlines[n].ep,
542
+ len: inlines[n].len,
543
+ oLen: -1,
544
+ type: 'text'
545
+ })
388
546
  inlines[n].len = 0
389
547
  }
390
548
 
@@ -413,7 +571,6 @@ const checkNest = (inlines, marks, n, i) => {
413
571
  if (parentCloseN < marks.length) {
414
572
  while (parentCloseN < marks.length) {
415
573
  if (marks[parentCloseN].nest === parentNest) break
416
- //if (marks.length - 1 == parentCloseN) break
417
574
  parentCloseN++
418
575
  }
419
576
  //console.log('parentCloseN: ' + parentCloseN)
@@ -434,121 +591,127 @@ const checkNest = (inlines, marks, n, i) => {
434
591
  return nest
435
592
  }
436
593
 
437
- const createMarks = (inlines, start, end, memo) => {
594
+ const createMarks = (state, inlines, start, end, memo, opt) => {
438
595
  let marks = []
439
596
  let n = start
440
597
  while (n < end) {
441
- if (inlines[n].type !== '' || inlines[n].len === 0) { n++; continue }
442
- memo.isEm = inlines[n].len === 1 ? true : false
443
- memo.wrapEm = 0
598
+ if (inlines[n].type !== '') { n++; continue }
444
599
  let nest = 0
445
- //console.log('n: ' + n + ' ----- inlines.length: ' + inlines.length + ', memo.isEm: ' + memo.isEm)
446
- if (!memo.isEm) {
447
- n, nest, memo = setStrong(inlines, marks, n, memo)
600
+ //console.log('n: ' + n + ' ----- inlines:: src: ' + state.src.slice(inlines[n].sp, inlines[n].ep + 1) + ', inlines[n].sp: ' + inlines[n].sp + ', inlines[n].len: ' + inlines[n].len + ', memo.isEm: ' + memo.isEm)
601
+ if (inlines[n].len > 1) {
602
+ n, nest = setStrong(state, inlines, marks, n, memo, opt)
603
+ }
604
+ if (inlines[n].len !== 0) {
605
+ n, nest = setEm(state, inlines, marks, n, memo, opt)
606
+ }
607
+ if (inlines[n].len !== 0) {
608
+ setText(inlines, marks, n, nest)
448
609
  }
449
- n, nest, memo = setEm(inlines, marks, n, memo)
450
- if (inlines[n].len !== 0) setText(inlines, marks, n, nest)
451
- //console.log(marks)
452
610
  n++
453
611
  }
454
612
  return marks
455
613
  }
456
614
 
457
- const fixInlines = (inlines, marks) => {
458
- let n = 0
459
- while (n < inlines.length) {
460
- if (inlines[n].type !== '') { n++; continue }
461
- let i = 0
462
- //console.log('n: ' + n + ', inlines[n].s: ' + inlines[n].s + ', inlines[n].e: ' + inlines[n].e)
463
- while (i < marks.length) {
464
- //console.log(marks[i].type, marks[i].s, inlines[n].e, marks[i].e, inlines[n].e)
465
- //console.log(marks[i].s >= inlines[n].s , marks[i].e <= inlines[n].e)
466
- if (marks[i].s >= inlines[n].s && marks[i].e <= inlines[n].e) {
467
- //console.log('n: ' + n + ', i: ' + i + ', marks[i].type: ' + marks[i].type)
468
- inlines.splice(n + i + 1, 0, marks[i])
469
- i++
470
- continue
615
+
616
+ const mergeInlinesAndMarks = (inlines, marks) => {
617
+ marks.sort((a, b) => a.s - b.s)
618
+ const merged = []
619
+ let markIndex = 0
620
+ for (const token of inlines) {
621
+ if (token.type === '') {
622
+ while (markIndex < marks.length && marks[markIndex].s >= token.s && marks[markIndex].e <= token.e) {
623
+ merged.push(marks[markIndex])
624
+ markIndex++
471
625
  }
472
- break
473
- }
474
- if (marks.length) {
475
- marks.splice(0, i)
476
- inlines.splice(n, 1)
477
- n += i
478
626
  } else {
479
- //if (inlines[n].type === '') inlines[n].type = 'text'
480
- n++
627
+ merged.push(token)
481
628
  }
482
629
  }
630
+ while (markIndex < marks.length) {
631
+ merged.push(marks[markIndex++])
632
+ }
633
+ return merged
483
634
  }
484
635
 
485
636
  const strongJa = (state, silent, opt) => {
486
637
  if (silent) return false
487
638
  const start = state.pos
488
639
  let max = state.posMax
640
+ const src = state.src
489
641
  let attributesSrc
490
- if (opt.hasCurlyAttributes) {
491
- attributesSrc = state.src.match(/( *){.*?}$/)
492
- if (attributesSrc) {
493
- max = state.src.slice(0, attributesSrc.index).length
642
+ if (start > max) return false
643
+ if (src.charCodeAt(start) !== 0x2A) return false
644
+ if (hasBackslash(state, start)) return false
645
+
646
+ if (opt.mditAttrs) {
647
+ attributesSrc = src.match(/((\n)? *){([^{}\n!@#%^&*()]+?)} *$/)
648
+ if (attributesSrc && attributesSrc[3] !== '.') {
649
+ max = src.slice(0, attributesSrc.index).length
650
+ if (attributesSrc[2] === '\n') {
651
+ max = src.slice(0, attributesSrc.index - 1).length
652
+ }
653
+ if(hasBackslash(state, attributesSrc.index) && attributesSrc[2] === '' && attributesSrc[1].length === 0) {
654
+ max = state.posMax
655
+ }
656
+ } else {
657
+ let endCurlyKet = src.match(/(\n *){([^{}\n!@#%^&*()]*?)}.*(} *?)$/)
658
+ if (endCurlyKet) {
659
+ max -= endCurlyKet[3].length
660
+ }
494
661
  }
495
662
  }
496
- if (start > max) return false
497
- if (state.src.charCodeAt(start) !== 0x2A) return false
498
663
 
499
- if (hasBackslash(state, start)) return false
500
- //console.log('state.src.length: ' + state.src.length + ', start: ' + start + ', state.src: ' + state.src)
664
+ //console.log('state.src.length(max): ' + state.src.length + (state.src.length === max ? '' : '(' + max + ')') + ', start: ' + start + ', state.src: ' + state.src)
501
665
  let inlines = createInlines(state, start, max, opt)
502
666
  //console.log('inlines: ')
503
667
  //console.log(inlines)
504
668
 
505
669
  const memo = {
506
- isEm: false,
507
- hasEmThatWrapStrong: false,
508
- noSetStrongEnd: false,
509
670
  html: state.md.options.html,
510
671
  htmlTags: {},
511
- inlineMarkStart: state.src.charCodeAt(0) === 0x2A ? true : false,
512
- inlineMarkEnd: state.src.charCodeAt(max - 1) === 0x2A ? true : false,
672
+ inlineMarkStart: src.charCodeAt(0) === 0x2A ? true : false,
673
+ inlineMarkEnd: src.charCodeAt(max - 1) === 0x2A ? true : false,
513
674
  }
514
- let marks = createMarks(inlines, 0, inlines.length, memo)
675
+
676
+ let marks = createMarks(state, inlines, 0, inlines.length, memo, opt)
515
677
  //console.log('marks: ')
516
678
  //console.log(marks)
517
679
 
518
- fixInlines(inlines, marks)
680
+ inlines = mergeInlinesAndMarks(inlines, marks)
519
681
  //console.log('fix inlines:')
520
682
  //console.log(inlines)
521
683
 
522
- setToken(state, inlines)
684
+ setToken(state, inlines, opt)
685
+
686
+ //console.log ('End process:: max:' + max + ', state.posMax: ' + state.posMax + ', opt.mditAttrs: ' + opt.mditAttrs)
523
687
 
524
- if (attributesSrc) {
525
- //console.log('attributesSrc[1].length: ' + attributesSrc[1].length)
688
+ if (opt.mditAttrs && max !== state.posMax) {
689
+ if (!attributesSrc) {
690
+ state.pos = max
691
+ return true
692
+ }
693
+ //console.log('start: ' + start + ', attributesSrc[0]::' + attributesSrc[0] + ', attributesSrc[1].length: ' + attributesSrc[1].length)
526
694
  if (attributesSrc[1].length > 1) {
527
695
  state.pos = max + attributesSrc[1].length
528
696
  } else {
529
697
  state.pos = max
530
698
  }
531
699
  } else {
532
- state.pos = max + 1
700
+ state.pos = max
533
701
  }
702
+ //console.log(state.tokens)
534
703
  return true
535
704
  }
536
705
 
537
706
  const mditStrongJa = (md, option) => {
538
707
  const opt = {
539
- dollarMath: true,
540
- hasCurlyAttributes: false,
541
- }
542
- opt.hasCurlyAttributes = md.core.ruler.__rules__.filter(rule => {
543
- rule.name === 'curly_attributes' // markdown-it-attrs
544
- })
545
- if (option !== undefined) {
546
- for (let o in option) {
547
- opt[o] = option[o]
548
- }
708
+ dollarMath: true, //inline math $...$
709
+ mditAttrs: true, //markdown-it-attrs
549
710
  }
711
+ if (option) Object.assign(opt, option)
712
+
550
713
  md.inline.ruler.before('emphasis', 'strong_ja', (state, silent) => {
551
714
  return strongJa(state, silent, opt)
552
715
  })
553
716
  }
554
- export default mditStrongJa
717
+ export default mditStrongJa