@peaceroad/markdown-it-strong-ja 0.4.2 → 0.4.4
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/README.md +19 -0
- package/index.js +220 -153
- package/package.json +6 -1
- package/test/example-complex.txt +0 -506
- package/test/example-em.txt +0 -205
- package/test/example-strong.txt +0 -219
- package/test/example-with-linebreak.txt +0 -282
- package/test/mditNoAttrs/example-complex.txt +0 -512
- package/test/mditNoAttrs/example-em.txt +0 -205
- package/test/mditNoAttrs/example-mdit-linebrek.txt +0 -46
- package/test/mditNoAttrs/example-strong.txt +0 -219
- package/test/mditNoAttrs/example-with-linebreak.txt +0 -289
- package/test/test.js +0 -146
package/index.js
CHANGED
|
@@ -1,14 +1,27 @@
|
|
|
1
|
+
// Character code constants
|
|
2
|
+
const CHAR_ASTERISK = 0x2A // *
|
|
3
|
+
const CHAR_UNDERSCORE = 0x5F // _
|
|
4
|
+
const CHAR_BACKSLASH = 0x5C // \
|
|
5
|
+
const CHAR_BACKTICK = 0x60 // `
|
|
6
|
+
const CHAR_DOLLAR = 0x24 // $
|
|
7
|
+
const CHAR_LT = 0x3C // <
|
|
8
|
+
const CHAR_GT = 0x3E // >
|
|
9
|
+
const CHAR_SLASH = 0x2F // /
|
|
10
|
+
const CHAR_SPACE = 0x20 // ' ' (space)
|
|
11
|
+
|
|
1
12
|
const REG_ASTERISKS = /^\*+$/
|
|
2
13
|
const REG_ATTRS = /{[^{}\n!@#%^&*()]+?}$/
|
|
3
14
|
const REG_PUNCTUATION = /[!-/:-@[-`{-~ ]/
|
|
4
|
-
const REG_JAPANESE =
|
|
15
|
+
const REG_JAPANESE = /\p{Script=Hiragana}|\p{Script=Katakana}|\p{Script=Han}|\p{General_Category=Punctuation}|\p{General_Category=Symbol}|\p{General_Category=Format}|\p{Emoji}/u // ひらがな|カタカナ|漢字|句読点|記号|フォーマット文字|絵文字
|
|
16
|
+
|
|
17
|
+
const REG_MARKDOWN_HTML = /^\[[^\[\]]+\]\([^)]+\)$|^<([a-zA-Z][a-zA-Z0-9]*)[^>]*>([^<]+<\/\1>)$|^`[^`]+`$|^\$[^$]+\$$/ // for mixed-language context detection
|
|
5
18
|
|
|
6
19
|
const hasBackslash = (state, start) => {
|
|
7
20
|
let slashNum = 0
|
|
8
21
|
let i = start - 1
|
|
9
22
|
const src = state.src
|
|
10
23
|
while(i >= 0) {
|
|
11
|
-
if (src.charCodeAt(i) ===
|
|
24
|
+
if (src.charCodeAt(i) === CHAR_BACKSLASH) { slashNum++; i--; continue }
|
|
12
25
|
break
|
|
13
26
|
}
|
|
14
27
|
return slashNum % 2 === 1
|
|
@@ -23,7 +36,6 @@ const setToken = (state, inlines, opt) => {
|
|
|
23
36
|
}
|
|
24
37
|
while (i < inlines.length) {
|
|
25
38
|
let type = inlines[i].type
|
|
26
|
-
//console.log(i, type)
|
|
27
39
|
const tag = type.replace(/(?:_open|_close)$/, '')
|
|
28
40
|
|
|
29
41
|
if (/_open$/.test(type)) {
|
|
@@ -40,9 +52,7 @@ const setToken = (state, inlines, opt) => {
|
|
|
40
52
|
}
|
|
41
53
|
if (type === 'text') {
|
|
42
54
|
let content = src.slice(inlines[i].s, inlines[i].e + 1)
|
|
43
|
-
//console.log('content: ' + content)
|
|
44
55
|
if (REG_ASTERISKS.test(content)) {
|
|
45
|
-
//console.log('asterisk process::')
|
|
46
56
|
const asteriskToken = state.push(type, '', 0)
|
|
47
57
|
asteriskToken.content = content
|
|
48
58
|
i++
|
|
@@ -50,7 +60,6 @@ const setToken = (state, inlines, opt) => {
|
|
|
50
60
|
}
|
|
51
61
|
if (opt.mditAttrs && attrsIsText.val && i + 1 < inlines.length) {
|
|
52
62
|
const hasImmediatelyAfterAsteriskClose = inlines[i+1].type === attrsIsText.tag + '_close'
|
|
53
|
-
//console.log(hasImmediatelyAfterAsteriskClose, inlines[i+1].type, /^[\s\S]*{[^{}\n!@#%^&*()]+?}$/.test(content))
|
|
54
63
|
if (hasImmediatelyAfterAsteriskClose && REG_ATTRS.test(content)) {
|
|
55
64
|
const attrsToken = state.push(type, '', 0)
|
|
56
65
|
|
|
@@ -66,7 +75,6 @@ const setToken = (state, inlines, opt) => {
|
|
|
66
75
|
backSlash += '\\'
|
|
67
76
|
k++
|
|
68
77
|
}
|
|
69
|
-
//console.log(backSlashNum, backSlash)
|
|
70
78
|
attrsToken.content = content.replace(/\\+{/, backSlash + '{')
|
|
71
79
|
}
|
|
72
80
|
} else {
|
|
@@ -79,8 +87,6 @@ const setToken = (state, inlines, opt) => {
|
|
|
79
87
|
}
|
|
80
88
|
|
|
81
89
|
const childTokens = state.md.parseInline(content, state.env)
|
|
82
|
-
//console.log(childTokens)
|
|
83
|
-
//console.log(childTokens[0].children)
|
|
84
90
|
if (childTokens[0] && childTokens[0].children) {
|
|
85
91
|
let j = 0
|
|
86
92
|
while (j < childTokens[0].children.length) {
|
|
@@ -131,7 +137,7 @@ const pushInlines = (inlines, s, e, len, type, tag, tagType) => {
|
|
|
131
137
|
ep: e,
|
|
132
138
|
len: len,
|
|
133
139
|
type: type,
|
|
134
|
-
check: type === 'text'
|
|
140
|
+
check: type === 'text',
|
|
135
141
|
}
|
|
136
142
|
if (tag) inline.tag = [tag, tagType]
|
|
137
143
|
inlines.push(inline)
|
|
@@ -141,16 +147,13 @@ const hasNextSymbol = (state, n, max, symbol, noMark) => {
|
|
|
141
147
|
let nextSymbolPos = -1
|
|
142
148
|
const src = state.src
|
|
143
149
|
if (src.charCodeAt(n) === symbol && !hasBackslash(state, n)) {
|
|
144
|
-
let i = n + 1
|
|
145
|
-
|
|
146
|
-
while (i < max) {
|
|
147
|
-
tempNoMark += src[i]
|
|
150
|
+
for (let i = n + 1; i < max; i++) {
|
|
151
|
+
noMark += src[i]
|
|
148
152
|
if (src.charCodeAt(i) === symbol && !hasBackslash(state, i)) {
|
|
149
153
|
noMark += src.substring(n, i + 1)
|
|
150
154
|
nextSymbolPos = i
|
|
151
155
|
break
|
|
152
156
|
}
|
|
153
|
-
i++
|
|
154
157
|
}
|
|
155
158
|
}
|
|
156
159
|
return [nextSymbolPos, noMark]
|
|
@@ -158,25 +161,34 @@ const hasNextSymbol = (state, n, max, symbol, noMark) => {
|
|
|
158
161
|
|
|
159
162
|
const createInlines = (state, start, max, opt) => {
|
|
160
163
|
const src = state.src
|
|
161
|
-
const srcLen = max
|
|
164
|
+
const srcLen = max
|
|
165
|
+
const htmlEnabled = state.md.options.html
|
|
162
166
|
let n = start
|
|
163
167
|
let inlines = []
|
|
164
168
|
let noMark = ''
|
|
165
169
|
let textStart = n
|
|
170
|
+
|
|
171
|
+
// Infinite loop prevention
|
|
172
|
+
const maxIterations = srcLen * 2 // Safe upper bound
|
|
173
|
+
let iterations = 0
|
|
174
|
+
|
|
166
175
|
while (n < srcLen) {
|
|
167
|
-
//
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
if (
|
|
172
|
-
pushInlines(inlines, textStart,
|
|
173
|
-
break
|
|
176
|
+
// Prevent infinite loops
|
|
177
|
+
iterations++
|
|
178
|
+
if (iterations > maxIterations) {
|
|
179
|
+
// Add remaining text as-is and exit safely
|
|
180
|
+
if (textStart < srcLen) {
|
|
181
|
+
pushInlines(inlines, textStart, srcLen - 1, srcLen - textStart, 'text')
|
|
174
182
|
}
|
|
175
|
-
|
|
176
|
-
continue
|
|
183
|
+
break
|
|
177
184
|
}
|
|
178
|
-
|
|
179
|
-
|
|
185
|
+
|
|
186
|
+
const currentChar = src.charCodeAt(n)
|
|
187
|
+
let nextSymbolPos = -1
|
|
188
|
+
|
|
189
|
+
// Inline code (backticks)
|
|
190
|
+
if (currentChar === CHAR_BACKTICK && !hasBackslash(state, n)) {
|
|
191
|
+
[nextSymbolPos, noMark] = hasNextSymbol(state, n, srcLen, CHAR_BACKTICK, noMark)
|
|
180
192
|
if (nextSymbolPos !== -1) {
|
|
181
193
|
if (nextSymbolPos === srcLen - 1) {
|
|
182
194
|
pushInlines(inlines, textStart, nextSymbolPos, nextSymbolPos - textStart + 1, 'text')
|
|
@@ -187,58 +199,74 @@ const createInlines = (state, start, max, opt) => {
|
|
|
187
199
|
}
|
|
188
200
|
}
|
|
189
201
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
202
|
+
// Inline math ($...$)
|
|
203
|
+
if (opt.dollarMath && currentChar === CHAR_DOLLAR && !hasBackslash(state, n)) {
|
|
204
|
+
[nextSymbolPos, noMark] = hasNextSymbol(state, n, srcLen, CHAR_DOLLAR, noMark)
|
|
205
|
+
if (nextSymbolPos !== -1) {
|
|
206
|
+
if (nextSymbolPos === srcLen - 1) {
|
|
207
|
+
pushInlines(inlines, textStart, nextSymbolPos, nextSymbolPos - textStart + 1, 'text')
|
|
208
|
+
break
|
|
209
|
+
}
|
|
210
|
+
n = nextSymbolPos + 1
|
|
211
|
+
continue
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// HTML tags
|
|
216
|
+
if (htmlEnabled && currentChar === CHAR_LT && !hasBackslash(state, n)) {
|
|
217
|
+
let foundClosingTag = false
|
|
218
|
+
for (let i = n + 1; i < srcLen; i++) {
|
|
219
|
+
if (src.charCodeAt(i) === CHAR_GT && !hasBackslash(state, i)) {
|
|
220
|
+
if (noMark.length !== 0) {
|
|
221
|
+
pushInlines(inlines, textStart, n - 1, n - textStart, 'text')
|
|
222
|
+
noMark = ''
|
|
210
223
|
}
|
|
211
|
-
i
|
|
224
|
+
let tag = src.slice(n + 1, i)
|
|
225
|
+
let tagType
|
|
226
|
+
if (tag.charCodeAt(0) === CHAR_SLASH) {
|
|
227
|
+
tag = tag.slice(1)
|
|
228
|
+
tagType = 'close'
|
|
229
|
+
} else {
|
|
230
|
+
tagType = 'open'
|
|
231
|
+
}
|
|
232
|
+
pushInlines(inlines, n, i, i - n + 1, 'html_inline', tag, tagType)
|
|
233
|
+
textStart = i + 1
|
|
234
|
+
n = i + 1
|
|
235
|
+
foundClosingTag = true
|
|
236
|
+
break
|
|
212
237
|
}
|
|
213
|
-
|
|
238
|
+
}
|
|
239
|
+
if (foundClosingTag) {
|
|
214
240
|
continue
|
|
215
241
|
}
|
|
242
|
+
// If no closing tag found, treat as regular character to prevent infinite loops
|
|
216
243
|
}
|
|
217
244
|
|
|
218
|
-
|
|
245
|
+
// Asterisk handling
|
|
246
|
+
if (currentChar === CHAR_ASTERISK && !hasBackslash(state, n)) {
|
|
219
247
|
if (n !== 0 && noMark.length !== 0) {
|
|
220
248
|
pushInlines(inlines, textStart, n - 1, n - textStart, 'text')
|
|
221
249
|
noMark = ''
|
|
222
250
|
}
|
|
223
251
|
if (n === srcLen - 1) {
|
|
224
|
-
pushInlines(inlines, n,
|
|
252
|
+
pushInlines(inlines, n, n, 1, '')
|
|
225
253
|
break
|
|
226
254
|
}
|
|
227
255
|
let i = n + 1
|
|
228
|
-
while (i < srcLen) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
pushInlines(inlines, n,
|
|
256
|
+
while (i < srcLen && src.charCodeAt(i) === CHAR_ASTERISK) {
|
|
257
|
+
i++
|
|
258
|
+
}
|
|
259
|
+
if (i === srcLen) {
|
|
260
|
+
pushInlines(inlines, n, i - 1, i - n, '')
|
|
261
|
+
} else {
|
|
262
|
+
pushInlines(inlines, n, i - 1, i - n, '')
|
|
235
263
|
textStart = i
|
|
236
|
-
break
|
|
237
264
|
}
|
|
238
265
|
n = i
|
|
239
266
|
continue
|
|
240
267
|
}
|
|
241
268
|
|
|
269
|
+
// Regular character
|
|
242
270
|
noMark += src[n]
|
|
243
271
|
if (n === srcLen - 1) {
|
|
244
272
|
pushInlines(inlines, textStart, n, n - textStart + 1, 'text')
|
|
@@ -250,7 +278,6 @@ const createInlines = (state, start, max, opt) => {
|
|
|
250
278
|
}
|
|
251
279
|
|
|
252
280
|
const pushMark = (marks, opts) => {
|
|
253
|
-
//binary search
|
|
254
281
|
let left = 0, right = marks.length
|
|
255
282
|
while (left < right) {
|
|
256
283
|
const mid = (left + right) >> 1
|
|
@@ -264,28 +291,43 @@ const pushMark = (marks, opts) => {
|
|
|
264
291
|
}
|
|
265
292
|
|
|
266
293
|
const setStrong = (state, inlines, marks, n, memo, opt) => {
|
|
294
|
+
if (opt.disallowMixed === true) {
|
|
295
|
+
let i = n + 1
|
|
296
|
+
const inlinesLength = inlines.length
|
|
297
|
+
while (i < inlinesLength) {
|
|
298
|
+
if (inlines[i].len === 0 || inlines[i].check) { i++; continue }
|
|
299
|
+
if (inlines[i].type !== '') { i++; continue }
|
|
300
|
+
|
|
301
|
+
if (inlines[i].len > 1) {
|
|
302
|
+
const mixedCheck = checkMixedLanguagePattern(state, inlines, n, i, opt)
|
|
303
|
+
if (mixedCheck.shouldBlock) {
|
|
304
|
+
return [n, 0]
|
|
305
|
+
}
|
|
306
|
+
break
|
|
307
|
+
}
|
|
308
|
+
i++
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
267
312
|
let i = n + 1
|
|
268
313
|
let j = 0
|
|
269
314
|
let nest = 0
|
|
270
|
-
let insideTagsIsClose = 1
|
|
271
|
-
|
|
272
|
-
|
|
315
|
+
let insideTagsIsClose = 1
|
|
316
|
+
const inlinesLength = inlines.length
|
|
317
|
+
while (i < inlinesLength) {
|
|
318
|
+
if (inlines[i].type !== '') { i++; continue }
|
|
273
319
|
if (inlines[i].len === 0 || inlines[i].check) { i++; continue }
|
|
274
320
|
if (inlines[i].type === 'html_inline') {
|
|
275
321
|
inlines[i].check = true
|
|
276
322
|
insideTagsIsClose = checkInsideTags(inlines, i, memo)
|
|
277
|
-
|
|
278
|
-
if (insideTagsIsClose === -1) return n, nest
|
|
323
|
+
if (insideTagsIsClose === -1) return [n, nest]
|
|
279
324
|
if (insideTagsIsClose === 0) { i++; continue }
|
|
280
325
|
}
|
|
281
|
-
if (inlines[i].type !== '') { i++; continue }
|
|
282
326
|
|
|
283
327
|
nest = checkNest(inlines, marks, n, i)
|
|
284
|
-
|
|
285
|
-
if (nest === -1) return n, nest
|
|
328
|
+
if (nest === -1) return [n, nest]
|
|
286
329
|
|
|
287
330
|
if (inlines[i].len === 1 && inlines[n].len > 2) {
|
|
288
|
-
//console.log(' check em inside strong:: i: ' + i)
|
|
289
331
|
pushMark(marks, {
|
|
290
332
|
nest: nest,
|
|
291
333
|
s: inlines[n].ep,
|
|
@@ -307,32 +349,25 @@ const setStrong = (state, inlines, marks, n, memo, opt) => {
|
|
|
307
349
|
inlines[i].len -= 1
|
|
308
350
|
if (inlines[i].len > 0) inlines[i].sp += 1
|
|
309
351
|
if (insideTagsIsClose === 1) {
|
|
310
|
-
|
|
352
|
+
const [newN, newNest] = setEm(state, inlines, marks, n, memo, opt)
|
|
353
|
+
n = newN
|
|
354
|
+
nest = newNest
|
|
311
355
|
}
|
|
312
|
-
//console.log(marks)
|
|
313
356
|
}
|
|
314
|
-
//console.log(' check len:: inlines[n].len: ' + inlines[n].len + ', inlines[i].len: ' + inlines[i].len)
|
|
315
357
|
let strongNum = Math.trunc(Math.min(inlines[n].len, inlines[i].len) / 2)
|
|
316
358
|
|
|
317
359
|
if (inlines[i].len > 1) {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
if (hasPunctuationOrNonJapanese(state, inlines, n, i)) {
|
|
360
|
+
if (hasPunctuationOrNonJapanese(state, inlines, n, i, opt)) {
|
|
321
361
|
if (memo.inlineMarkEnd) {
|
|
322
|
-
|
|
323
|
-
//console.log('~~~~~~~~~~~~~~~~~')
|
|
324
|
-
marks.push(...createMarks(state, inlines, i, inlines.length - 1, memo, opt))
|
|
325
|
-
//console.log('~~~~~~~~~~~~~~~~~')
|
|
362
|
+
marks.push(...createMarks(state, inlines, i, inlinesLength - 1, memo, opt))
|
|
326
363
|
if (inlines[i].len === 0) { i++; continue }
|
|
327
364
|
} else {
|
|
328
|
-
return n, nest
|
|
365
|
+
return [n, nest]
|
|
329
366
|
}
|
|
330
367
|
}
|
|
331
|
-
//console.log(' ===> strong normal push. n: ' + n + ', i: ' + i + ' , nest: ' + nest + ',strongNum: ' + strongNum)
|
|
332
368
|
|
|
333
369
|
j = 0
|
|
334
370
|
while (j < strongNum) {
|
|
335
|
-
//console.log(' - j: ' + j + ', inlines[i].sp: ' + inlines[i].sp)
|
|
336
371
|
pushMark(marks, {
|
|
337
372
|
nest: nest + strongNum - 1 - j,
|
|
338
373
|
s: inlines[n].ep - 1,
|
|
@@ -355,47 +390,40 @@ const setStrong = (state, inlines, marks, n, memo, opt) => {
|
|
|
355
390
|
inlines[i].len -= 2
|
|
356
391
|
j++
|
|
357
392
|
}
|
|
358
|
-
if (inlines[n].len === 0) return n, nest
|
|
393
|
+
if (inlines[n].len === 0) return [n, nest]
|
|
359
394
|
}
|
|
360
395
|
|
|
361
396
|
if (inlines[n].len === 1 && inlines[i].len > 0) {
|
|
362
|
-
//console.log(' check em that warp strong.')
|
|
363
397
|
nest++
|
|
364
|
-
|
|
398
|
+
const [newN, newNest] = setEm(state, inlines, marks, n, memo, opt, nest)
|
|
399
|
+
n = newN
|
|
400
|
+
nest = newNest
|
|
365
401
|
}
|
|
366
402
|
|
|
367
403
|
i++
|
|
368
404
|
}
|
|
369
405
|
|
|
370
406
|
if (n == 0 && memo.inlineMarkEnd) {
|
|
371
|
-
|
|
372
|
-
//console.log('===============================')
|
|
373
|
-
marks.push(...createMarks(state, inlines, n + 1 , inlines.length - 1, memo, opt))
|
|
374
|
-
//console.log(marks)
|
|
375
|
-
//console.log('===============================')
|
|
407
|
+
marks.push(...createMarks(state, inlines, n + 1, inlinesLength - 1, memo, opt))
|
|
376
408
|
}
|
|
377
|
-
return n, nest
|
|
409
|
+
return [n, nest]
|
|
378
410
|
}
|
|
379
411
|
|
|
380
412
|
const checkInsideTags = (inlines, i, memo) => {
|
|
381
|
-
//console.log('isJumTag before::memo.htmlTags: ' + JSON.stringify(memo.htmlTags))
|
|
382
413
|
if (inlines[i].tag === undefined) return 0
|
|
383
414
|
const tagName = inlines[i].tag[0].toLowerCase()
|
|
384
415
|
if (memo.htmlTags[tagName] === undefined) {
|
|
385
416
|
memo.htmlTags[tagName] = 0
|
|
386
417
|
}
|
|
387
|
-
//console.log('memo.htmlTags: ' + JSON.stringify(memo.htmlTags) + ', inlines[i]: ' + JSON.stringify(inlines[i]) + ', inlines[i]')
|
|
388
418
|
if (inlines[i].tag[1] === 'open') {
|
|
389
419
|
memo.htmlTags[tagName] += 1
|
|
390
420
|
}
|
|
391
421
|
if (inlines[i].tag[1] === 'close') {
|
|
392
422
|
memo.htmlTags[tagName] -= 1
|
|
393
423
|
}
|
|
394
|
-
//console.log(' i: ' + i + ', tagName: ' + tagName + ', memo.htmlTags[tagName]: ' + memo.htmlTags[tagName] + ', prevHtmlTags[tagName]: ' + prevHtmlTags[tagName])
|
|
395
424
|
if (memo.htmlTags[tagName] < 0) {
|
|
396
425
|
return -1
|
|
397
426
|
}
|
|
398
|
-
//console.log('isJumTag after::memo.htmlTags: ' + JSON.stringify(memo.htmlTags))
|
|
399
427
|
const closeAllTags = Object.values(memo.htmlTags).every(val => val === 0)
|
|
400
428
|
if (closeAllTags) return 1
|
|
401
429
|
return 0
|
|
@@ -408,47 +436,107 @@ const isJapanese = (ch) => {
|
|
|
408
436
|
return REG_JAPANESE.test(ch)
|
|
409
437
|
}
|
|
410
438
|
|
|
411
|
-
const
|
|
439
|
+
const isEnglish = (ch) => {
|
|
440
|
+
if (!ch) return false
|
|
441
|
+
const code = ch.charCodeAt(0)
|
|
442
|
+
if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122) || (code >= 48 && code <= 57)) {
|
|
443
|
+
return true
|
|
444
|
+
}
|
|
445
|
+
if (code < 128) {
|
|
446
|
+
return code === CHAR_SPACE || (code > 126)
|
|
447
|
+
}
|
|
448
|
+
return !REG_JAPANESE.test(ch) && !REG_PUNCTUATION.test(ch)
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const checkMixedLanguagePattern = (state, inlines, n, i, opt) => {
|
|
452
|
+
const src = state.src
|
|
453
|
+
const openPrevChar = src[inlines[n].s - 1] || ''
|
|
454
|
+
const closeNextChar = src[inlines[i].e + 1] || ''
|
|
455
|
+
|
|
456
|
+
const isEnglishPrefix = isEnglish(openPrevChar)
|
|
457
|
+
const isEnglishSuffix = isEnglish(closeNextChar)
|
|
458
|
+
if (!isEnglishPrefix && !isEnglishSuffix) {
|
|
459
|
+
return { hasEnglishContext: false, hasMarkdownOrHtml: false, shouldBlock: false }
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
const contentBetween = src.slice(inlines[n].e + 1, inlines[i].s)
|
|
463
|
+
const hasMarkdownOrHtml = REG_MARKDOWN_HTML.test(contentBetween)
|
|
464
|
+
|
|
465
|
+
return {
|
|
466
|
+
hasEnglishContext: true,
|
|
467
|
+
hasMarkdownOrHtml,
|
|
468
|
+
shouldBlock: hasMarkdownOrHtml
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
const hasPunctuationOrNonJapanese = (state, inlines, n, i, opt) => {
|
|
412
473
|
const src = state.src
|
|
413
474
|
const openPrevChar = src[inlines[n].s - 1] || ''
|
|
414
|
-
//const checkOpenPrevChar =
|
|
415
475
|
const openNextChar = src[inlines[n].e + 1] || ''
|
|
416
476
|
const checkOpenNextChar = isPunctuation(openNextChar)
|
|
417
477
|
const closePrevChar = src[inlines[i].s - 1] || ''
|
|
418
478
|
const checkClosePrevChar = isPunctuation(closePrevChar)
|
|
419
479
|
const closeNextChar = src[inlines[i].e + 1] || ''
|
|
420
|
-
const checkCloseNextChar = (isPunctuation(closeNextChar) || i === inlines.length - 1)
|
|
421
|
-
|
|
422
|
-
|
|
480
|
+
const checkCloseNextChar = (isPunctuation(closeNextChar) || i === inlines.length - 1)
|
|
481
|
+
|
|
482
|
+
if (opt.disallowMixed === false) {
|
|
483
|
+
const openPrevChar = src[inlines[n].s - 1] || ''
|
|
484
|
+
const closeNextChar = src[inlines[i].e + 1] || ''
|
|
485
|
+
|
|
486
|
+
if (isEnglish(openPrevChar) || isEnglish(closeNextChar)) {
|
|
487
|
+
const contentBetween = src.slice(inlines[n].e + 1, inlines[i].s)
|
|
488
|
+
if (REG_MARKDOWN_HTML.test(contentBetween)) {
|
|
489
|
+
return false
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
const result = (checkOpenNextChar || checkClosePrevChar) && !checkCloseNextChar && !(isJapanese(openPrevChar) || isJapanese(closeNextChar))
|
|
495
|
+
return result
|
|
423
496
|
}
|
|
424
497
|
|
|
425
498
|
const setEm = (state, inlines, marks, n, memo, opt, sNest) => {
|
|
499
|
+
if (opt.disallowMixed === true && !sNest) {
|
|
500
|
+
let i = n + 1
|
|
501
|
+
const inlinesLength = inlines.length
|
|
502
|
+
while (i < inlinesLength) {
|
|
503
|
+
if (inlines[i].len === 0 || inlines[i].check) { i++; continue }
|
|
504
|
+
if (inlines[i].type !== '') { i++; continue }
|
|
505
|
+
|
|
506
|
+
if (inlines[i].len > 0) {
|
|
507
|
+
const mixedCheck = checkMixedLanguagePattern(state, inlines, n, i, opt)
|
|
508
|
+
if (mixedCheck.shouldBlock) {
|
|
509
|
+
return [n, 0]
|
|
510
|
+
}
|
|
511
|
+
break
|
|
512
|
+
}
|
|
513
|
+
i++
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
426
517
|
let i = n + 1
|
|
427
518
|
let nest = 0
|
|
428
519
|
let strongPNum = 0
|
|
429
520
|
let insideTagsIsClose = 1
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
//console.log(inlines[i].type, JSON.stringify(memo.htmlTags))
|
|
521
|
+
const inlinesLength = inlines.length
|
|
522
|
+
while (i < inlinesLength) {
|
|
433
523
|
if (inlines[i].len === 0 || inlines[i].check) { i++; continue }
|
|
434
524
|
if (!sNest && inlines[i].type === 'html_inline') {
|
|
435
525
|
inlines.check = true
|
|
436
526
|
insideTagsIsClose = checkInsideTags(inlines, i, memo)
|
|
437
|
-
|
|
438
|
-
if (insideTagsIsClose === -1) return n, nest
|
|
527
|
+
if (insideTagsIsClose === -1) return [n, nest]
|
|
439
528
|
if (insideTagsIsClose === 0) { i++; continue }
|
|
440
529
|
}
|
|
441
530
|
if (inlines[i].type !== '') { i++; continue }
|
|
442
531
|
|
|
443
532
|
const emNum = Math.min(inlines[n].len, inlines[i].len)
|
|
444
533
|
|
|
445
|
-
|
|
446
|
-
if (!sNest && emNum !== 1) return n, sNest, memo
|
|
534
|
+
if (!sNest && emNum !== 1) return [n, sNest, memo]
|
|
447
535
|
|
|
448
536
|
const hasMarkersAtStartAndEnd = (i) => {
|
|
449
537
|
let flag = memo.inlineMarkStart
|
|
450
538
|
if (!flag) return false
|
|
451
|
-
|
|
539
|
+
inlinesLength - 1 === i ? flag = true : flag = false
|
|
452
540
|
if (!flag) return false
|
|
453
541
|
inlines[i].len > 1 ? flag = true : flag = false
|
|
454
542
|
return flag
|
|
@@ -464,30 +552,22 @@ const setEm = (state, inlines, marks, n, memo, opt, sNest) => {
|
|
|
464
552
|
} else {
|
|
465
553
|
nest = checkNest(inlines, marks, n, i)
|
|
466
554
|
}
|
|
467
|
-
|
|
468
|
-
if (nest === -1) return n, nest
|
|
555
|
+
if (nest === -1) return [n, nest]
|
|
469
556
|
|
|
470
557
|
if (emNum === 1) {
|
|
471
|
-
|
|
472
|
-
if (hasPunctuationOrNonJapanese(state, inlines, n, i)) {
|
|
558
|
+
if (hasPunctuationOrNonJapanese(state, inlines, n, i, opt)) {
|
|
473
559
|
if (memo.inlineMarkEnd) {
|
|
474
|
-
|
|
475
|
-
//console.log('~~~~~~~~~~~~~~~~~')
|
|
476
|
-
marks.push(...createMarks(state, inlines, i, inlines.length - 1, memo, opt))
|
|
477
|
-
//console.log('~~~~~~~~~~~~~~~~~')
|
|
560
|
+
marks.push(...createMarks(state, inlines, i, inlinesLength - 1, memo, opt))
|
|
478
561
|
|
|
479
562
|
if (inlines[i].len === 0) { i++; continue }
|
|
480
563
|
} else {
|
|
481
|
-
return n, nest
|
|
564
|
+
return [n, nest]
|
|
482
565
|
}
|
|
483
566
|
}
|
|
484
|
-
|
|
485
|
-
if (inlines[i].len < 1) { // memo.html
|
|
567
|
+
if (inlines[i].len < 1) {
|
|
486
568
|
i++; continue;
|
|
487
569
|
}
|
|
488
570
|
|
|
489
|
-
//console.log(' ===> em Normal push. n: ' + n + ', i: ' + i + ', nest: ' + nest, ', strongPNum: ' + strongPNum)
|
|
490
|
-
//console.log(inlines[n].ep, inlines[n].sp, inlines[n].s)
|
|
491
571
|
pushMark(marks, {
|
|
492
572
|
nest: nest,
|
|
493
573
|
s: inlines[n].ep,
|
|
@@ -522,17 +602,15 @@ const setEm = (state, inlines, marks, n, memo, opt, sNest) => {
|
|
|
522
602
|
inlines[i].ep -= 1
|
|
523
603
|
}
|
|
524
604
|
inlines[i].len -= 1
|
|
525
|
-
|
|
526
|
-
if (inlines[n].len === 0) return n, nest
|
|
605
|
+
if (inlines[n].len === 0) return [n, nest]
|
|
527
606
|
}
|
|
528
607
|
|
|
529
608
|
i++
|
|
530
609
|
}
|
|
531
|
-
return n, nest
|
|
610
|
+
return [n, nest]
|
|
532
611
|
}
|
|
533
612
|
|
|
534
613
|
const setText = (inlines, marks, n, nest) => {
|
|
535
|
-
//console.log('n: ' + n + ' [text]: inlines[n].len: ' + inlines[n].len)
|
|
536
614
|
pushMark(marks, {
|
|
537
615
|
nest: nest,
|
|
538
616
|
s: inlines[n].sp,
|
|
@@ -551,10 +629,8 @@ const checkNest = (inlines, marks, n, i) => {
|
|
|
551
629
|
let strongNest = 0
|
|
552
630
|
let emNest = 0
|
|
553
631
|
let j = 0
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
//console.log('n: ' + n + ', i: ' + i + ', inlines[n].s: ' + inlines[n].s + ', inlines[i].s: ' + inlines[i].s)
|
|
557
|
-
while (j < marks.length) {
|
|
632
|
+
const marksLength = marks.length
|
|
633
|
+
while (j < marksLength) {
|
|
558
634
|
if (marks[j].s <= inlines[n].s) {
|
|
559
635
|
if (marks[j].type === 'strong_open') strongNest++
|
|
560
636
|
if (marks[j].type === 'strong_close') strongNest--
|
|
@@ -565,21 +641,17 @@ const checkNest = (inlines, marks, n, i) => {
|
|
|
565
641
|
}
|
|
566
642
|
let parentNest = strongNest + emNest
|
|
567
643
|
let parentCloseN = j
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
while (parentCloseN < marks.length) {
|
|
644
|
+
if (parentCloseN < marksLength) {
|
|
645
|
+
while (parentCloseN < marksLength) {
|
|
571
646
|
if (marks[parentCloseN].nest === parentNest) break
|
|
572
647
|
parentCloseN++
|
|
573
648
|
}
|
|
574
|
-
|
|
575
|
-
if (parentCloseN > marks.length - 1) {
|
|
649
|
+
if (parentCloseN > marksLength - 1) {
|
|
576
650
|
isRange = true
|
|
577
651
|
} else {
|
|
578
|
-
//console.log(marks[parentCloseN].s, i, inlines[i].s)
|
|
579
652
|
if (marks[parentCloseN].s < inlines[i].s) isRange = false
|
|
580
653
|
}
|
|
581
654
|
}
|
|
582
|
-
//console.log('isRange: ' + isRange)
|
|
583
655
|
|
|
584
656
|
if (isRange) {
|
|
585
657
|
nest = parentNest + 1
|
|
@@ -592,15 +664,20 @@ const checkNest = (inlines, marks, n, i) => {
|
|
|
592
664
|
const createMarks = (state, inlines, start, end, memo, opt) => {
|
|
593
665
|
let marks = []
|
|
594
666
|
let n = start
|
|
667
|
+
|
|
595
668
|
while (n < end) {
|
|
596
669
|
if (inlines[n].type !== '') { n++; continue }
|
|
597
670
|
let nest = 0
|
|
598
|
-
|
|
671
|
+
|
|
599
672
|
if (inlines[n].len > 1) {
|
|
600
|
-
|
|
673
|
+
const [newN, newNest] = setStrong(state, inlines, marks, n, memo, opt)
|
|
674
|
+
n = newN
|
|
675
|
+
nest = newNest
|
|
601
676
|
}
|
|
602
677
|
if (inlines[n].len !== 0) {
|
|
603
|
-
|
|
678
|
+
const [newN2, newNest2] = setEm(state, inlines, marks, n, memo, opt)
|
|
679
|
+
n = newN2
|
|
680
|
+
nest = newNest2
|
|
604
681
|
}
|
|
605
682
|
if (inlines[n].len !== 0) {
|
|
606
683
|
setText(inlines, marks, n, nest)
|
|
@@ -638,7 +715,7 @@ const strongJa = (state, silent, opt) => {
|
|
|
638
715
|
const src = state.src
|
|
639
716
|
let attributesSrc
|
|
640
717
|
if (start > max) return false
|
|
641
|
-
if (src.charCodeAt(start) !==
|
|
718
|
+
if (src.charCodeAt(start) !== CHAR_ASTERISK) return false
|
|
642
719
|
if (hasBackslash(state, start)) return false
|
|
643
720
|
|
|
644
721
|
if (opt.mditAttrs) {
|
|
@@ -659,36 +736,26 @@ const strongJa = (state, silent, opt) => {
|
|
|
659
736
|
}
|
|
660
737
|
}
|
|
661
738
|
|
|
662
|
-
//console.log('state.src.length(max): ' + state.src.length + (state.src.length === max ? '' : '(' + max + ')') + ', start: ' + start + ', state.src: ' + state.src)
|
|
663
739
|
let inlines = createInlines(state, start, max, opt)
|
|
664
|
-
//console.log('inlines: ')
|
|
665
|
-
//console.log(inlines)
|
|
666
740
|
|
|
667
741
|
const memo = {
|
|
668
742
|
html: state.md.options.html,
|
|
669
743
|
htmlTags: {},
|
|
670
|
-
inlineMarkStart: src.charCodeAt(0) ===
|
|
671
|
-
inlineMarkEnd: src.charCodeAt(max - 1) ===
|
|
744
|
+
inlineMarkStart: src.charCodeAt(0) === CHAR_ASTERISK,
|
|
745
|
+
inlineMarkEnd: src.charCodeAt(max - 1) === CHAR_ASTERISK,
|
|
672
746
|
}
|
|
673
747
|
|
|
674
748
|
let marks = createMarks(state, inlines, 0, inlines.length, memo, opt)
|
|
675
|
-
//console.log('marks: ')
|
|
676
|
-
//console.log(marks)
|
|
677
749
|
|
|
678
750
|
inlines = mergeInlinesAndMarks(inlines, marks)
|
|
679
|
-
//console.log('fix inlines:')
|
|
680
|
-
//console.log(inlines)
|
|
681
751
|
|
|
682
752
|
setToken(state, inlines, opt)
|
|
683
753
|
|
|
684
|
-
//console.log ('End process:: max:' + max + ', state.posMax: ' + state.posMax + ', opt.mditAttrs: ' + opt.mditAttrs)
|
|
685
|
-
|
|
686
754
|
if (opt.mditAttrs && max !== state.posMax) {
|
|
687
755
|
if (!attributesSrc) {
|
|
688
756
|
state.pos = max
|
|
689
757
|
return true
|
|
690
758
|
}
|
|
691
|
-
//console.log('start: ' + start + ', attributesSrc[0]::' + attributesSrc[0] + ', attributesSrc[1].length: ' + attributesSrc[1].length)
|
|
692
759
|
if (attributesSrc[1].length > 1) {
|
|
693
760
|
state.pos = max + attributesSrc[1].length
|
|
694
761
|
} else {
|
|
@@ -697,7 +764,6 @@ const strongJa = (state, silent, opt) => {
|
|
|
697
764
|
} else {
|
|
698
765
|
state.pos = max
|
|
699
766
|
}
|
|
700
|
-
//console.log(state.tokens)
|
|
701
767
|
return true
|
|
702
768
|
}
|
|
703
769
|
|
|
@@ -706,6 +772,7 @@ const mditStrongJa = (md, option) => {
|
|
|
706
772
|
dollarMath: true, //inline math $...$
|
|
707
773
|
mditAttrs: true, //markdown-it-attrs
|
|
708
774
|
mdBreaks: md.options.breaks,
|
|
775
|
+
disallowMixed: false, //Non-Japanese text handling
|
|
709
776
|
}
|
|
710
777
|
if (option) Object.assign(opt, option)
|
|
711
778
|
|