@peaceroad/markdown-it-strong-ja 0.8.1 → 0.9.1
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 +4 -4
- package/index.js +9 -17
- package/package.json +5 -5
- package/src/token-compat.js +13 -17
- package/src/token-core.js +148 -56
- package/src/token-link-utils.js +13 -16
- package/src/token-postprocess/broken-ref.js +123 -27
- package/src/token-postprocess/emphasis-balance.js +50 -0
- package/src/token-postprocess/fastpaths.js +1 -5
- package/src/token-postprocess/guards.js +121 -107
- package/src/token-postprocess/orchestrator.js +110 -169
- package/src/token-utils.js +182 -139
package/src/token-utils.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
const CHAR_ASTERISK = 0x2A // *
|
|
2
|
-
const CHAR_SPACE = 0x20 // ' '
|
|
3
|
-
const CHAR_TAB = 0x09 // '\t'
|
|
4
|
-
const CHAR_NEWLINE = 0x0A // '\n'
|
|
5
|
-
const CHAR_IDEOGRAPHIC_SPACE = 0x3000 // fullwidth space
|
|
6
|
-
const MODE_FLAG_COMPATIBLE = 1 << 0
|
|
7
|
-
const MODE_FLAG_AGGRESSIVE = 1 << 1
|
|
1
|
+
const CHAR_ASTERISK = 0x2A // *
|
|
2
|
+
const CHAR_SPACE = 0x20 // ' '
|
|
3
|
+
const CHAR_TAB = 0x09 // '\t'
|
|
4
|
+
const CHAR_NEWLINE = 0x0A // '\n'
|
|
5
|
+
const CHAR_IDEOGRAPHIC_SPACE = 0x3000 // fullwidth space
|
|
6
|
+
const MODE_FLAG_COMPATIBLE = 1 << 0
|
|
7
|
+
const MODE_FLAG_AGGRESSIVE = 1 << 1
|
|
8
8
|
const MODE_FLAG_JAPANESE_BASE = 1 << 2
|
|
9
9
|
const MODE_FLAG_JAPANESE_PLUS = 1 << 3
|
|
10
10
|
const MODE_FLAG_JAPANESE_ANY = MODE_FLAG_JAPANESE_BASE | MODE_FLAG_JAPANESE_PLUS
|
|
11
|
+
const HAS_OWN = Object.prototype.hasOwnProperty
|
|
11
12
|
const REG_CJK_BREAKS_RULE_NAME = /(^|[_-])cjk_breaks([_-]|$)/
|
|
12
13
|
const VALID_CANONICAL_MODES = new Set([
|
|
13
14
|
'compatible',
|
|
@@ -15,25 +16,40 @@ const VALID_CANONICAL_MODES = new Set([
|
|
|
15
16
|
'japanese-boundary',
|
|
16
17
|
'japanese-boundary-guard'
|
|
17
18
|
])
|
|
18
|
-
const REG_JAPANESE = /[\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Han}\u3000-\u303F\uFF00-\uFFEF]/u
|
|
19
|
-
const REG_ATTRS = /{[^{}\n!@#%^&*()]+?}$/
|
|
20
|
-
|
|
19
|
+
const REG_JAPANESE = /[\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Han}\u3000-\u303F\uFF00-\uFFEF]/u
|
|
20
|
+
const REG_ATTRS = /{[^{}\n!@#%^&*()]+?}$/
|
|
21
|
+
|
|
21
22
|
const isJapaneseChar = (ch) => {
|
|
22
|
-
if (!ch) return false
|
|
23
|
-
const code = typeof ch === 'string' ? ch.charCodeAt(0) : ch
|
|
24
|
-
if (code < 128) return false
|
|
25
|
-
if (code >= 0x3040 && code <= 0x309F) return true
|
|
26
|
-
if (code >= 0x30A0 && code <= 0x30FF) return true
|
|
27
|
-
// Han + CJK punctuation/fullwidth ranges are common hot-path hits.
|
|
28
|
-
// Keep these as cheap numeric checks before the fallback regex.
|
|
29
|
-
if (code >= 0x3400 && code <= 0x4DBF) return true
|
|
30
|
-
if (code >= 0x4E00 && code <= 0x9FFF) return true
|
|
31
|
-
if (code >= 0xF900 && code <= 0xFAFF) return true
|
|
32
|
-
if (code >= 0x3000 && code <= 0x303F) return true
|
|
33
|
-
if (code >= 0xFF00 && code <= 0xFFEF) return true
|
|
23
|
+
if (!ch) return false
|
|
24
|
+
const code = typeof ch === 'string' ? ch.charCodeAt(0) : ch
|
|
25
|
+
if (code < 128) return false
|
|
26
|
+
if (code >= 0x3040 && code <= 0x309F) return true
|
|
27
|
+
if (code >= 0x30A0 && code <= 0x30FF) return true
|
|
28
|
+
// Han + CJK punctuation/fullwidth ranges are common hot-path hits.
|
|
29
|
+
// Keep these as cheap numeric checks before the fallback regex.
|
|
30
|
+
if (code >= 0x3400 && code <= 0x4DBF) return true
|
|
31
|
+
if (code >= 0x4E00 && code <= 0x9FFF) return true
|
|
32
|
+
if (code >= 0xF900 && code <= 0xFAFF) return true
|
|
33
|
+
if (code >= 0x3000 && code <= 0x303F) return true
|
|
34
|
+
if (code >= 0xFF00 && code <= 0xFFEF) return true
|
|
34
35
|
return REG_JAPANESE.test(String.fromCharCode(code))
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
const isAsciiWordCode = (code) => {
|
|
39
|
+
return (code >= 0x30 && code <= 0x39) ||
|
|
40
|
+
(code >= 0x41 && code <= 0x5A) ||
|
|
41
|
+
(code >= 0x61 && code <= 0x7A)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const isSoftSpaceCode = (code) => {
|
|
45
|
+
return code === CHAR_SPACE || code === CHAR_TAB || code === CHAR_IDEOGRAPHIC_SPACE
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const cloneMap = (map) => {
|
|
49
|
+
if (!map || !Array.isArray(map)) return null
|
|
50
|
+
return [map[0], map[1]]
|
|
51
|
+
}
|
|
52
|
+
|
|
37
53
|
const hasCjkBreaksRule = (md) => {
|
|
38
54
|
if (!md || !md.core || !md.core.ruler || !Array.isArray(md.core.ruler.__rules__)) return false
|
|
39
55
|
if (md.__strongJaHasCjkBreaks === true) return true
|
|
@@ -58,7 +74,7 @@ const hasCjkBreaksRule = (md) => {
|
|
|
58
74
|
const isCjkBreaksRuleName = (name) => {
|
|
59
75
|
return typeof name === 'string' && REG_CJK_BREAKS_RULE_NAME.test(name)
|
|
60
76
|
}
|
|
61
|
-
|
|
77
|
+
|
|
62
78
|
const resolveMode = (opt) => {
|
|
63
79
|
const raw = opt && typeof opt.mode === 'string' ? opt.mode : 'japanese'
|
|
64
80
|
const normalized = raw.toLowerCase()
|
|
@@ -69,9 +85,9 @@ const resolveMode = (opt) => {
|
|
|
69
85
|
`mditStrongJa: unknown mode "${raw}". Valid modes: japanese, japanese-boundary, japanese-boundary-guard, aggressive, compatible`
|
|
70
86
|
)
|
|
71
87
|
}
|
|
72
|
-
|
|
73
|
-
const getModeFlags = (mode) => {
|
|
74
|
-
switch (mode) {
|
|
88
|
+
|
|
89
|
+
const getModeFlags = (mode) => {
|
|
90
|
+
switch (mode) {
|
|
75
91
|
case 'compatible':
|
|
76
92
|
return MODE_FLAG_COMPATIBLE
|
|
77
93
|
case 'aggressive':
|
|
@@ -80,26 +96,26 @@ const getModeFlags = (mode) => {
|
|
|
80
96
|
return MODE_FLAG_JAPANESE_BASE
|
|
81
97
|
case 'japanese-boundary-guard':
|
|
82
98
|
return MODE_FLAG_JAPANESE_PLUS
|
|
83
|
-
default:
|
|
84
|
-
return 0
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const deriveModeInfo = (opt) => {
|
|
89
|
-
if (!opt || typeof opt !== 'object') return opt
|
|
90
|
-
const rawMode = opt.mode
|
|
91
|
-
if (opt.__strongJaModeRaw === rawMode &&
|
|
92
|
-
typeof opt.__strongJaMode === 'string' &&
|
|
93
|
-
typeof opt.__strongJaModeFlags === 'number') {
|
|
94
|
-
return opt
|
|
95
|
-
}
|
|
96
|
-
const mode = resolveMode(opt)
|
|
97
|
-
opt.__strongJaModeRaw = rawMode
|
|
98
|
-
opt.__strongJaMode = mode
|
|
99
|
-
opt.__strongJaModeFlags = getModeFlags(mode)
|
|
100
|
-
return opt
|
|
101
|
-
}
|
|
102
|
-
|
|
99
|
+
default:
|
|
100
|
+
return 0
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const deriveModeInfo = (opt) => {
|
|
105
|
+
if (!opt || typeof opt !== 'object') return opt
|
|
106
|
+
const rawMode = opt.mode
|
|
107
|
+
if (opt.__strongJaModeRaw === rawMode &&
|
|
108
|
+
typeof opt.__strongJaMode === 'string' &&
|
|
109
|
+
typeof opt.__strongJaModeFlags === 'number') {
|
|
110
|
+
return opt
|
|
111
|
+
}
|
|
112
|
+
const mode = resolveMode(opt)
|
|
113
|
+
opt.__strongJaModeRaw = rawMode
|
|
114
|
+
opt.__strongJaMode = mode
|
|
115
|
+
opt.__strongJaModeFlags = getModeFlags(mode)
|
|
116
|
+
return opt
|
|
117
|
+
}
|
|
118
|
+
|
|
103
119
|
const deriveOptionInfo = (opt) => {
|
|
104
120
|
if (!opt || typeof opt !== 'object') return opt
|
|
105
121
|
deriveModeInfo(opt)
|
|
@@ -126,114 +142,141 @@ const deriveOptionInfo = (opt) => {
|
|
|
126
142
|
return opt
|
|
127
143
|
}
|
|
128
144
|
|
|
129
|
-
const
|
|
130
|
-
if (!
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
state
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
145
|
+
const hasRuntimeOverride = (override) => {
|
|
146
|
+
if (!override || typeof override !== 'object') return false
|
|
147
|
+
return (HAS_OWN.call(override, 'mode') && override.mode !== undefined) ||
|
|
148
|
+
(HAS_OWN.call(override, 'postprocess') && override.postprocess !== undefined)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const getRuntimeOpt = (state, baseOpt) => {
|
|
152
|
+
const override = state && state.env ? state.env.__strongJaTokenOpt : null
|
|
153
|
+
const hasOverride = hasRuntimeOverride(override)
|
|
154
|
+
if (state &&
|
|
155
|
+
state.__strongJaTokenRuntimeOpt &&
|
|
156
|
+
state.__strongJaTokenRuntimeBase === baseOpt &&
|
|
157
|
+
state.__strongJaTokenRuntimeOverride === override &&
|
|
158
|
+
state.__strongJaTokenRuntimeHasOverride === hasOverride) {
|
|
159
|
+
return state.__strongJaTokenRuntimeOpt
|
|
160
|
+
}
|
|
161
|
+
let resolved = deriveOptionInfo(baseOpt)
|
|
162
|
+
if (hasOverride) {
|
|
163
|
+
const merged = baseOpt && typeof baseOpt === 'object' ? { ...baseOpt } : {}
|
|
164
|
+
if (HAS_OWN.call(override, 'mode') && override.mode !== undefined) merged.mode = override.mode
|
|
165
|
+
if (HAS_OWN.call(override, 'postprocess') && override.postprocess !== undefined) merged.postprocess = override.postprocess
|
|
166
|
+
resolved = deriveOptionInfo(merged)
|
|
167
|
+
}
|
|
168
|
+
if (!state) return resolved
|
|
169
|
+
state.__strongJaTokenRuntimeOpt = resolved
|
|
170
|
+
state.__strongJaTokenRuntimeBase = baseOpt
|
|
171
|
+
state.__strongJaTokenRuntimeOverride = override
|
|
172
|
+
state.__strongJaTokenRuntimeHasOverride = hasOverride
|
|
173
|
+
return resolved
|
|
174
|
+
}
|
|
175
|
+
|
|
144
176
|
const getReferenceCount = (state) => {
|
|
145
177
|
if (!state) return 0
|
|
146
178
|
let referenceCount = state.__strongJaReferenceCount
|
|
147
179
|
if (referenceCount !== undefined) return referenceCount
|
|
148
180
|
const references = state.env && state.env.references
|
|
149
|
-
|
|
181
|
+
if (!references) {
|
|
182
|
+
state.__strongJaReferenceCount = 0
|
|
183
|
+
return 0
|
|
184
|
+
}
|
|
185
|
+
referenceCount = 0
|
|
186
|
+
for (const key in references) {
|
|
187
|
+
if (HAS_OWN.call(references, key)) referenceCount++
|
|
188
|
+
}
|
|
150
189
|
state.__strongJaReferenceCount = referenceCount
|
|
151
190
|
return referenceCount
|
|
152
191
|
}
|
|
153
192
|
|
|
154
|
-
function normalizeCoreRulesBeforePostprocess(value) {
|
|
155
|
-
if (!value) return []
|
|
156
|
-
const list = Array.isArray(value) ? value : [value]
|
|
157
|
-
const normalized = []
|
|
158
|
-
const seen = new Set()
|
|
159
|
-
for (let idx = 0; idx < list.length; idx++) {
|
|
160
|
-
const raw = list[idx]
|
|
161
|
-
if (typeof raw !== 'string') continue
|
|
162
|
-
const trimmed = raw.trim()
|
|
163
|
-
if (!trimmed || seen.has(trimmed)) continue
|
|
164
|
-
seen.add(trimmed)
|
|
165
|
-
normalized.push(trimmed)
|
|
166
|
-
}
|
|
167
|
-
return normalized
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function ensureCoreRuleOrder(md, ruleNames, targetRuleName) {
|
|
171
|
-
if (!md || !md.core || !md.core.ruler) return
|
|
172
|
-
if (!ruleNames || ruleNames.length === 0) return
|
|
173
|
-
for (let idx = 0; idx < ruleNames.length; idx++) {
|
|
174
|
-
moveRuleBefore(md.core.ruler, ruleNames[idx], targetRuleName)
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
function moveRuleBefore(ruler, ruleName, beforeName) {
|
|
179
|
-
if (!ruler || !ruler.__rules__) return
|
|
180
|
-
const rules = ruler.__rules__
|
|
181
|
-
let fromIdx = -1
|
|
182
|
-
let beforeIdx = -1
|
|
183
|
-
for (let idx = 0; idx < rules.length; idx++) {
|
|
184
|
-
if (rules[idx].name === ruleName) fromIdx = idx
|
|
185
|
-
if (rules[idx].name === beforeName) beforeIdx = idx
|
|
186
|
-
if (fromIdx !== -1 && beforeIdx !== -1) break
|
|
187
|
-
}
|
|
188
|
-
// Ensure ruleName is before beforeName; keep existing order if already earlier.
|
|
189
|
-
if (fromIdx === -1 || beforeIdx === -1 || fromIdx < beforeIdx) return
|
|
190
|
-
|
|
191
|
-
const rule = rules.splice(fromIdx, 1)[0]
|
|
192
|
-
rules.splice(beforeIdx, 0, rule)
|
|
193
|
-
ruler.__cache__ = null
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function moveRuleAfter(ruler, ruleName, afterName) {
|
|
197
|
-
if (!ruler || !ruler.__rules__) return
|
|
198
|
-
const rules = ruler.__rules__
|
|
199
|
-
let fromIdx = -1
|
|
200
|
-
let afterIdx = -1
|
|
201
|
-
for (let idx = 0; idx < rules.length; idx++) {
|
|
202
|
-
if (rules[idx].name === ruleName) fromIdx = idx
|
|
203
|
-
if (rules[idx].name === afterName) afterIdx = idx
|
|
204
|
-
if (fromIdx !== -1 && afterIdx !== -1) break
|
|
205
|
-
}
|
|
206
|
-
if (fromIdx === -1 || afterIdx === -1 || fromIdx === afterIdx + 1) return
|
|
207
|
-
|
|
208
|
-
const rule = rules.splice(fromIdx, 1)[0]
|
|
209
|
-
const targetIdx = fromIdx < afterIdx ? afterIdx - 1 : afterIdx
|
|
210
|
-
rules.splice(targetIdx + 1, 0, rule)
|
|
211
|
-
ruler.__cache__ = null
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
export {
|
|
215
|
-
CHAR_ASTERISK,
|
|
216
|
-
CHAR_SPACE,
|
|
217
|
-
CHAR_TAB,
|
|
218
|
-
CHAR_NEWLINE,
|
|
219
|
-
CHAR_IDEOGRAPHIC_SPACE,
|
|
193
|
+
function normalizeCoreRulesBeforePostprocess(value) {
|
|
194
|
+
if (!value) return []
|
|
195
|
+
const list = Array.isArray(value) ? value : [value]
|
|
196
|
+
const normalized = []
|
|
197
|
+
const seen = new Set()
|
|
198
|
+
for (let idx = 0; idx < list.length; idx++) {
|
|
199
|
+
const raw = list[idx]
|
|
200
|
+
if (typeof raw !== 'string') continue
|
|
201
|
+
const trimmed = raw.trim()
|
|
202
|
+
if (!trimmed || seen.has(trimmed)) continue
|
|
203
|
+
seen.add(trimmed)
|
|
204
|
+
normalized.push(trimmed)
|
|
205
|
+
}
|
|
206
|
+
return normalized
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function ensureCoreRuleOrder(md, ruleNames, targetRuleName) {
|
|
210
|
+
if (!md || !md.core || !md.core.ruler) return
|
|
211
|
+
if (!ruleNames || ruleNames.length === 0) return
|
|
212
|
+
for (let idx = 0; idx < ruleNames.length; idx++) {
|
|
213
|
+
moveRuleBefore(md.core.ruler, ruleNames[idx], targetRuleName)
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function moveRuleBefore(ruler, ruleName, beforeName) {
|
|
218
|
+
if (!ruler || !ruler.__rules__) return
|
|
219
|
+
const rules = ruler.__rules__
|
|
220
|
+
let fromIdx = -1
|
|
221
|
+
let beforeIdx = -1
|
|
222
|
+
for (let idx = 0; idx < rules.length; idx++) {
|
|
223
|
+
if (rules[idx].name === ruleName) fromIdx = idx
|
|
224
|
+
if (rules[idx].name === beforeName) beforeIdx = idx
|
|
225
|
+
if (fromIdx !== -1 && beforeIdx !== -1) break
|
|
226
|
+
}
|
|
227
|
+
// Ensure ruleName is before beforeName; keep existing order if already earlier.
|
|
228
|
+
if (fromIdx === -1 || beforeIdx === -1 || fromIdx < beforeIdx) return
|
|
229
|
+
|
|
230
|
+
const rule = rules.splice(fromIdx, 1)[0]
|
|
231
|
+
rules.splice(beforeIdx, 0, rule)
|
|
232
|
+
ruler.__cache__ = null
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function moveRuleAfter(ruler, ruleName, afterName) {
|
|
236
|
+
if (!ruler || !ruler.__rules__) return
|
|
237
|
+
const rules = ruler.__rules__
|
|
238
|
+
let fromIdx = -1
|
|
239
|
+
let afterIdx = -1
|
|
240
|
+
for (let idx = 0; idx < rules.length; idx++) {
|
|
241
|
+
if (rules[idx].name === ruleName) fromIdx = idx
|
|
242
|
+
if (rules[idx].name === afterName) afterIdx = idx
|
|
243
|
+
if (fromIdx !== -1 && afterIdx !== -1) break
|
|
244
|
+
}
|
|
245
|
+
if (fromIdx === -1 || afterIdx === -1 || fromIdx === afterIdx + 1) return
|
|
246
|
+
|
|
247
|
+
const rule = rules.splice(fromIdx, 1)[0]
|
|
248
|
+
const targetIdx = fromIdx < afterIdx ? afterIdx - 1 : afterIdx
|
|
249
|
+
rules.splice(targetIdx + 1, 0, rule)
|
|
250
|
+
ruler.__cache__ = null
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export {
|
|
254
|
+
CHAR_ASTERISK,
|
|
255
|
+
CHAR_SPACE,
|
|
256
|
+
CHAR_TAB,
|
|
257
|
+
CHAR_NEWLINE,
|
|
258
|
+
CHAR_IDEOGRAPHIC_SPACE,
|
|
220
259
|
REG_ATTRS,
|
|
221
260
|
isJapaneseChar,
|
|
261
|
+
isAsciiWordCode,
|
|
262
|
+
isSoftSpaceCode,
|
|
263
|
+
cloneMap,
|
|
222
264
|
hasCjkBreaksRule,
|
|
223
265
|
isCjkBreaksRuleName,
|
|
224
266
|
resolveMode,
|
|
225
267
|
getModeFlags,
|
|
226
|
-
deriveModeInfo,
|
|
227
|
-
deriveOptionInfo,
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
268
|
+
deriveModeInfo,
|
|
269
|
+
deriveOptionInfo,
|
|
270
|
+
hasRuntimeOverride,
|
|
271
|
+
MODE_FLAG_COMPATIBLE,
|
|
272
|
+
MODE_FLAG_AGGRESSIVE,
|
|
273
|
+
MODE_FLAG_JAPANESE_BASE,
|
|
274
|
+
MODE_FLAG_JAPANESE_PLUS,
|
|
232
275
|
MODE_FLAG_JAPANESE_ANY,
|
|
233
276
|
getRuntimeOpt,
|
|
234
277
|
getReferenceCount,
|
|
235
|
-
normalizeCoreRulesBeforePostprocess,
|
|
236
|
-
ensureCoreRuleOrder,
|
|
237
|
-
moveRuleBefore,
|
|
238
|
-
moveRuleAfter
|
|
239
|
-
}
|
|
278
|
+
normalizeCoreRulesBeforePostprocess,
|
|
279
|
+
ensureCoreRuleOrder,
|
|
280
|
+
moveRuleBefore,
|
|
281
|
+
moveRuleAfter
|
|
282
|
+
}
|