@peaceroad/markdown-it-strong-ja 0.5.2 → 0.5.3

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.
Files changed (3) hide show
  1. package/README.md +15 -0
  2. package/index.js +160 -22
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -172,3 +172,18 @@ md.render('string**[text](url)**')
172
172
  // <p>string**<a href="url">text</a>**</p>
173
173
  ```
174
174
 
175
+ ### coreRulesBeforePostprocess
176
+
177
+ `strong_ja_postprocess` runs inside the markdown-it core pipeline. When other plugins register core rules, you can keep their rules ahead of `strong_ja_postprocess` by listing them in `coreRulesBeforePostprocess`. Each name is normalized, deduplicated, and re-ordered once during plugin setup.
178
+
179
+ ```js
180
+ const md = mdit()
181
+ .use(cjkBreaks)
182
+ .use(mditStrongJa, {
183
+ coreRulesBeforePostprocess: ['cjk_breaks', 'my_custom_rule']
184
+ })
185
+ ```
186
+
187
+ - Default: `[]`
188
+ - Specify `['cjk_breaks']` (or other rule names) when you rely on plugins such as `@peaceroad/markdown-it-cjk-breaks-mod` and need them to run first.
189
+ - Pass an empty array if you do not want `mditStrongJa` to reorder any core rules.
package/index.js CHANGED
@@ -15,6 +15,10 @@ const CHAR_OPEN_BRACKET = 0x5B // [
15
15
  const CHAR_CLOSE_BRACKET = 0x5D // ]
16
16
  const CHAR_OPEN_PAREN = 0x28 // (
17
17
  const CHAR_CLOSE_PAREN = 0x29 // )
18
+ const CHAR_NEWLINE = 0x0A // \n
19
+ const CHAR_TAB = 0x09 // tab
20
+ //const CHAR_OPEN_CURLY = 0x7B // {
21
+ const CHAR_CLOSE_CURLY = 0x7D // }
18
22
 
19
23
  const REG_ASTERISKS = /^\*+$/
20
24
  const REG_ATTRS = /{[^{}\n!@#%^&*()]+?}$/
@@ -1104,6 +1108,7 @@ const strongJa = (state, silent, opt) => {
1104
1108
  if (silent) return false
1105
1109
  const start = state.pos
1106
1110
  let max = state.posMax
1111
+ const originalMax = max
1107
1112
  const src = state.src
1108
1113
  let attributesSrc
1109
1114
  if (start > max) return false
@@ -1117,19 +1122,37 @@ const strongJa = (state, silent, opt) => {
1117
1122
  }
1118
1123
 
1119
1124
  if (opt.mditAttrs) {
1120
- attributesSrc = src.match(/((\n)? *){([^{}\n!@#%^&*()]+?)} *$/)
1121
- if (attributesSrc && attributesSrc[3] !== '.') {
1122
- max = src.slice(0, attributesSrc.index).length
1123
- if (attributesSrc[2] === '\n') {
1124
- max = src.slice(0, attributesSrc.index - 1).length
1125
+ let attrCandidate = false
1126
+ let probe = originalMax - 1
1127
+ while (probe >= start) {
1128
+ const code = src.charCodeAt(probe)
1129
+ if (code === CHAR_CLOSE_CURLY) {
1130
+ attrCandidate = true
1131
+ break
1125
1132
  }
1126
- if(hasBackslash(state, attributesSrc.index) && attributesSrc[2] === '' && attributesSrc[1].length === 0) {
1127
- max = state.posMax
1133
+ if (code === CHAR_SPACE || code === CHAR_TAB || code === CHAR_NEWLINE) {
1134
+ probe--
1135
+ continue
1128
1136
  }
1129
- } else {
1130
- let endCurlyKet = src.match(/(\n *){([^{}\n!@#%^&*()]*?)}.*(} *?)$/)
1131
- if (endCurlyKet) {
1132
- max -= endCurlyKet[3].length
1137
+ break
1138
+ }
1139
+
1140
+ if (attrCandidate) {
1141
+ const attrScanTarget = originalMax === src.length ? src : src.slice(0, originalMax)
1142
+ attributesSrc = attrScanTarget.match(/((\n)? *){([^{}\n!@#%^&*()]+?)} *$/)
1143
+ if (attributesSrc && attributesSrc[3] !== '.') {
1144
+ max = attrScanTarget.slice(0, attributesSrc.index).length
1145
+ if (attributesSrc[2] === '\n') {
1146
+ max = attrScanTarget.slice(0, attributesSrc.index - 1).length
1147
+ }
1148
+ if (hasBackslash(state, attributesSrc.index) && attributesSrc[2] === '' && attributesSrc[1].length === 0) {
1149
+ max = state.posMax
1150
+ }
1151
+ } else {
1152
+ const endCurlyKet = attrScanTarget.match(/(\n *){([^{}\n!@#%^&*()]*?)}.*(} *?)$/)
1153
+ if (endCurlyKet) {
1154
+ max -= endCurlyKet[3].length
1155
+ }
1133
1156
  }
1134
1157
  }
1135
1158
  }
@@ -1143,13 +1166,16 @@ const strongJa = (state, silent, opt) => {
1143
1166
  state.__strongJaReferenceCount = references ? Object.keys(references).length : 0
1144
1167
  }
1145
1168
 
1146
- let refRanges
1147
- const refCache = state.__strongJaRefRangeCache
1148
- if (refCache && refCache.max === max && refCache.start <= start) {
1149
- refRanges = refCache.ranges
1150
- } else {
1151
- refRanges = computeReferenceRanges(state, start, max)
1152
- state.__strongJaRefRangeCache = { start, max, ranges: refRanges }
1169
+ let refRanges = []
1170
+ const hasReferenceDefinitions = state.__strongJaReferenceCount > 0
1171
+ if (hasReferenceDefinitions) {
1172
+ const refCache = state.__strongJaRefRangeCache
1173
+ if (refCache && refCache.max === max && refCache.start <= start) {
1174
+ refRanges = refCache.ranges
1175
+ } else {
1176
+ refRanges = computeReferenceRanges(state, start, max)
1177
+ state.__strongJaRefRangeCache = { start, max, ranges: refRanges }
1178
+ }
1153
1179
  }
1154
1180
  if (refRanges.length > 0) {
1155
1181
  state.__strongJaHasCollapsedRefs = true
@@ -1243,11 +1269,17 @@ const normalizeReferenceCandidate = (state, text, { useClean = false } = {}) =>
1243
1269
  return normalizeRefKey(state, source)
1244
1270
  }
1245
1271
 
1246
- const normalizeRefKey = (state, label) => {
1272
+ const getNormalizeRef = (state) => {
1273
+ if (state.__strongJaNormalizeRef) return state.__strongJaNormalizeRef
1247
1274
  const normalize = state.md && state.md.utils && state.md.utils.normalizeReference
1248
1275
  ? state.md.utils.normalizeReference
1249
1276
  : (str) => str.trim().replace(/\s+/g, ' ').toUpperCase()
1250
- return normalize(label)
1277
+ state.__strongJaNormalizeRef = normalize
1278
+ return normalize
1279
+ }
1280
+
1281
+ const normalizeRefKey = (state, label) => {
1282
+ return getNormalizeRef(state)(label)
1251
1283
  }
1252
1284
 
1253
1285
  const adjustTokenLevels = (tokens, startIdx, endIdx, delta) => {
@@ -1272,10 +1304,22 @@ const cloneTextToken = (source, content) => {
1272
1304
  const splitBracketToken = (tokens, index, options) => {
1273
1305
  const token = tokens[index]
1274
1306
  if (!token || token.type !== 'text') return false
1307
+ if (token.__strongJaBracketAtomic) return false
1308
+ if (token.__strongJaHasBracket === false) return false
1275
1309
  const content = token.content
1276
- if (!content || (content.indexOf('[') === -1 && content.indexOf(']') === -1)) {
1310
+ if (!content) {
1311
+ token.__strongJaHasBracket = false
1312
+ token.__strongJaBracketAtomic = false
1277
1313
  return false
1278
1314
  }
1315
+ if (token.__strongJaHasBracket !== true) {
1316
+ if (content.indexOf('[') === -1 && content.indexOf(']') === -1) {
1317
+ token.__strongJaHasBracket = false
1318
+ token.__strongJaBracketAtomic = false
1319
+ return false
1320
+ }
1321
+ token.__strongJaHasBracket = true
1322
+ }
1279
1323
  const splitEmptyPair = options && options.splitEmptyPair
1280
1324
  const segments = []
1281
1325
  let buffer = ''
@@ -1304,11 +1348,49 @@ const splitBracketToken = (tokens, index, options) => {
1304
1348
  pos++
1305
1349
  }
1306
1350
  if (buffer) segments.push(buffer)
1307
- if (segments.length <= 1) return false
1351
+ if (segments.length <= 1) {
1352
+ if (segments.length === 0) {
1353
+ token.__strongJaHasBracket = false
1354
+ token.__strongJaBracketAtomic = false
1355
+ } else {
1356
+ const seg = segments[0]
1357
+ if (seg === '[' || seg === ']') {
1358
+ token.__strongJaHasBracket = true
1359
+ token.__strongJaBracketAtomic = true
1360
+ } else if (seg === '[]') {
1361
+ token.__strongJaHasBracket = true
1362
+ token.__strongJaBracketAtomic = false
1363
+ } else {
1364
+ token.__strongJaHasBracket = false
1365
+ token.__strongJaBracketAtomic = false
1366
+ }
1367
+ }
1368
+ return false
1369
+ }
1308
1370
  token.content = segments[0]
1371
+ if (token.content === '[' || token.content === ']') {
1372
+ token.__strongJaHasBracket = true
1373
+ token.__strongJaBracketAtomic = true
1374
+ } else if (token.content === '[]') {
1375
+ token.__strongJaHasBracket = true
1376
+ token.__strongJaBracketAtomic = false
1377
+ } else {
1378
+ token.__strongJaHasBracket = false
1379
+ token.__strongJaBracketAtomic = false
1380
+ }
1309
1381
  let insertIdx = index + 1
1310
1382
  for (let s = 1; s < segments.length; s++) {
1311
1383
  const newToken = cloneTextToken(token, segments[s])
1384
+ if (segments[s] === '[' || segments[s] === ']') {
1385
+ newToken.__strongJaHasBracket = true
1386
+ newToken.__strongJaBracketAtomic = true
1387
+ } else if (segments[s] === '[]') {
1388
+ newToken.__strongJaHasBracket = true
1389
+ newToken.__strongJaBracketAtomic = false
1390
+ } else {
1391
+ newToken.__strongJaHasBracket = false
1392
+ newToken.__strongJaBracketAtomic = false
1393
+ }
1312
1394
  tokens.splice(insertIdx, 0, newToken)
1313
1395
  insertIdx++
1314
1396
  }
@@ -1787,8 +1869,16 @@ const mditStrongJa = (md, option) => {
1787
1869
  mditAttrs: true, //markdown-it-attrs
1788
1870
  mdBreaks: md.options.breaks,
1789
1871
  disallowMixed: false, //Non-Japanese text handling
1872
+ coreRulesBeforePostprocess: [] // e.g. ['cjk_breaks'] when CJK line-break plugins are active
1790
1873
  }
1791
1874
  if (option) Object.assign(opt, option)
1875
+ const rawCoreRules = opt.coreRulesBeforePostprocess
1876
+ const hasCoreRuleConfig = Array.isArray(rawCoreRules)
1877
+ ? rawCoreRules.length > 0
1878
+ : !!rawCoreRules
1879
+ const coreRulesBeforePostprocess = hasCoreRuleConfig
1880
+ ? normalizeCoreRulesBeforePostprocess(rawCoreRules)
1881
+ : []
1792
1882
 
1793
1883
  md.inline.ruler.before('emphasis', 'strong_ja', (state, silent) => {
1794
1884
  return strongJa(state, silent, opt)
@@ -1808,6 +1898,54 @@ const mditStrongJa = (md, option) => {
1808
1898
  delete state.env.__strongJaPostProcessTargets
1809
1899
  delete state.env.__strongJaPostProcessTargetSet
1810
1900
  })
1901
+
1902
+ if (coreRulesBeforePostprocess.length > 0) {
1903
+ ensureCoreRuleOrder(md, coreRulesBeforePostprocess)
1904
+ }
1811
1905
  }
1812
1906
 
1813
1907
  export default mditStrongJa
1908
+
1909
+
1910
+ function normalizeCoreRulesBeforePostprocess(value) {
1911
+ if (!value) return []
1912
+ const list = Array.isArray(value) ? value : [value]
1913
+ const normalized = []
1914
+ const seen = new Set()
1915
+ for (let idx = 0; idx < list.length; idx++) {
1916
+ const raw = list[idx]
1917
+ if (typeof raw !== 'string') continue
1918
+ const trimmed = raw.trim()
1919
+ if (!trimmed || seen.has(trimmed)) continue
1920
+ seen.add(trimmed)
1921
+ normalized.push(trimmed)
1922
+ }
1923
+ return normalized
1924
+ }
1925
+
1926
+
1927
+ function ensureCoreRuleOrder(md, ruleNames) {
1928
+ if (!md || !md.core || !md.core.ruler) return
1929
+ if (!ruleNames || ruleNames.length === 0) return
1930
+ for (let idx = 0; idx < ruleNames.length; idx++) {
1931
+ moveRuleBefore(md.core.ruler, ruleNames[idx], 'strong_ja_postprocess')
1932
+ }
1933
+ }
1934
+
1935
+
1936
+ function moveRuleBefore(ruler, ruleName, beforeName) {
1937
+ if (!ruler || !ruler.__rules__) return
1938
+ const rules = ruler.__rules__
1939
+ let fromIdx = -1
1940
+ let beforeIdx = -1
1941
+ for (let idx = 0; idx < rules.length; idx++) {
1942
+ if (rules[idx].name === ruleName) fromIdx = idx
1943
+ if (rules[idx].name === beforeName) beforeIdx = idx
1944
+ if (fromIdx !== -1 && beforeIdx !== -1) break
1945
+ }
1946
+ if (fromIdx === -1 || beforeIdx === -1 || fromIdx < beforeIdx) return
1947
+
1948
+ const rule = rules.splice(fromIdx, 1)[0]
1949
+ rules.splice(beforeIdx, 0, rule)
1950
+ ruler.__cache__ = null
1951
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@peaceroad/markdown-it-strong-ja",
3
3
  "description": "This is a plugin for markdown-it. It is an alternative to the standard `**` (strong) and `*` (em) processing. It also processes strings that cannot be converted by the standard.",
4
- "version": "0.5.2",
4
+ "version": "0.5.3",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "files": [