@peaceroad/markdown-it-cjk-breaks-mod 0.1.7 → 0.1.8

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 +86 -94
  2. package/index.js +54 -48
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,133 +1,125 @@
1
- # markdown-it-cjk-breaks
1
+ # @peaceroad/markdown-it-cjk-breaks-mod
2
2
 
3
- ## k_taka's additional features
3
+ `@peaceroad/markdown-it-cjk-breaks-mod` is a markdown-it plugin that suppresses line breaks between CJK text and optionally injects spacing after configured punctuation when a break is removed. It is designed for mixed Japanese/CJK + ASCII documents where default newline handling often produces unwanted spaces or breaks.
4
4
 
5
- ### Punctuation spacing options
5
+ This package is a fork lineage of [`markdown-it-cjk-breaks`](https://github.com/markdown-it/markdown-it-cjk-breaks) and [`@sup39/markdown-it-cjk-breaks`](https://www.npmjs.com/package/@sup39/markdown-it-cjk-breaks). It keeps the original CJK break suppression behavior, adds the `either` mode introduced by `@sup39`, and extends it with punctuation-spacing controls and softbreak normalization for plugin-heavy markdown-it pipelines.
6
6
 
7
- `spaceAfterPunctuation` inserts spacing only when this plugin suppresses a line break after punctuation. The second-pass matcher also covers inline markup starts (inline code, links/autolinks, images, inline HTML) as long as the raw source contains a visible newline boundary; if a `softbreak` remains, no spacing is injected.
7
+ ## Install
8
8
 
9
- `spaceAfterPunctuationTargets` lets you replace the default trigger list with a custom string or array. Defaults are `['!', '?', '⁉', '!?', '?!', '!?', '?!', '.', ':']`. To disable punctuation spacing while still setting `spaceAfterPunctuation`, pass `spaceAfterPunctuationTargets: []` (or `null`/`false`). Use `spaceAfterPunctuationTargetsAdd` to append triggers and `spaceAfterPunctuationTargetsRemove` to drop items from the resolved list.
9
+ ```
10
+ npm i @peaceroad/markdown-it-cjk-breaks-mod
11
+ ```
10
12
 
11
- `spaceAfterPunctuation` accepts `'half'` for ASCII space, `'full'` for an ideographic space, or any custom string via a literal value. Raw matching is strict, so escapes or entities (e.g. `&`) right before the newline can prevent a match and skip spacing (safe-fail behavior).
13
+ ## Quick Start
12
14
 
13
15
  ```js
14
16
  import MarkdownIt from 'markdown-it';
15
17
  import cjkBreaks from '@peaceroad/markdown-it-cjk-breaks-mod';
16
18
 
17
- // Full-width spacing after default punctuation
18
- const mdFull = MarkdownIt({ html: true }).use(cjkBreaks, {
19
- spaceAfterPunctuation: 'full',
20
- either: true
21
- });
22
- mdFull.render('こんにちは!\nWorld');
23
- // <p>こんにちは! World</p>
19
+ const md = MarkdownIt({ html: true }).use(cjkBreaks);
20
+
21
+ md.render('あおえ\nうい');
22
+ // <p>あおえうい</p>
23
+ ```
24
+
25
+ ## Options
26
+
27
+ - `either`
28
+ Type: `boolean`
29
+ Default: `false`
30
+ Remove a break when either side (instead of both sides) is CJK-width (`F/W/H`), still excluding Hangul.
31
+ Origin: inherited from `@sup39/markdown-it-cjk-breaks`.
32
+
33
+ The options below are extensions added by this project:
34
+
35
+ - `normalizeSoftBreaks`
36
+ Type: `boolean`
37
+ Default: `false`
38
+ Split newline-containing `text` tokens into explicit `softbreak` tokens before processing. Useful with plugins that rewrite inline tokens.
39
+ - `spaceAfterPunctuation`
40
+ Type: `'half' | 'full' | string`
41
+ Default: disabled
42
+ Insert spacing only when this plugin removes a break after a target sequence. `'half'` => `' '`, `'full'` => `\u3000`.
43
+ - `spaceAfterPunctuationTargets`
44
+ Type: `string | string[] | [] | null | false`
45
+ Default: `['!', '?', '⁉', '!?', '?!', '!?', '?!', '.', ':']`
46
+ Replace the target sequence set. `[]`, `null`, or `false` explicitly disable target matching.
47
+ - `spaceAfterPunctuationTargetsAdd`
48
+ Type: `string | string[]`
49
+ Default: unset
50
+ Append target sequences after base resolution.
51
+ - `spaceAfterPunctuationTargetsRemove`
52
+ Type: `string | string[]`
53
+ Default: unset
54
+ Remove sequences from the resolved target list.
55
+
56
+ ## Punctuation Spacing Examples
57
+
58
+ ```js
59
+ import MarkdownIt from 'markdown-it';
60
+ import cjkBreaks from '@peaceroad/markdown-it-cjk-breaks-mod';
24
61
 
25
- // Half-width spacing for ASCII-friendly mixes
26
62
  const mdHalf = MarkdownIt({ html: true }).use(cjkBreaks, {
27
- spaceAfterPunctuation: 'half',
28
- either: true
63
+ either: true,
64
+ spaceAfterPunctuation: 'half'
29
65
  });
66
+
30
67
  mdHalf.render('こんにちは!\nWorld');
31
68
  // <p>こんにちは! World</p>
32
69
 
33
- // Inline code and links are supported when a raw newline is present
34
- mdHalf.render('漢!\n`code`');
35
- // <p>漢! <code>code</code></p>
36
- mdHalf.render('漢!\n[link](url)');
37
- // <p>漢! <a href="url">link</a></p>
70
+ const mdFull = MarkdownIt({ html: true }).use(cjkBreaks, {
71
+ either: true,
72
+ spaceAfterPunctuation: 'full'
73
+ });
74
+
75
+ mdFull.render('こんにちは!\nWorld');
76
+ // <p>こんにちは! World</p>
38
77
 
39
- // Custom punctuation triggers (replaces defaults)
40
78
  const mdCustom = MarkdownIt({ html: true }).use(cjkBreaks, {
79
+ either: true,
41
80
  spaceAfterPunctuation: 'half',
42
81
  spaceAfterPunctuationTargets: ['??']
43
82
  });
83
+
44
84
  mdCustom.render('Hello??\nWorld');
45
85
  // <p>Hello?? World</p>
46
86
  ```
47
87
 
48
- ### Softbreak normalization for other plugins
49
- Even with stock markdown-it, emphasis markers can leave inline `text` tokens that still embed `\n`. When `normalizeSoftBreaks: true`, those tokens are split back into proper `softbreak` entries before CJK suppression runs, so a trailing `***漢***\n字` behaves the same way regardless of how markdown-it represented it internally.
88
+ ## Softbreak Normalization Example
50
89
 
51
90
  ```js
52
- // Normalize softbreaks emitted by other plugins first
53
- const mdStrongJaFriendly = MarkdownIt({ html: true }).use(cjkBreaks, {
54
- normalizeSoftBreaks: true,
55
- either: true
56
- });
57
- mdStrongJaFriendly.render('**漢**\nb');
58
- // <p><strong>漢</strong>b</p>
59
- ```
60
-
61
- `@peaceroad/markdown-it-strong-ja` also emit newline-containing `text` nodes after their own rewrites. The same option keeps behavior consistent no matter which order you register plugins.
62
-
63
- ## sup39's additional features
64
-
65
- - [@sup39/markdown-it-cjk-breaks](https://npmjs.com/package/@sup39/markdown-it-cjk-breaks)
91
+ import MarkdownIt from 'markdown-it';
92
+ import cjkBreaks from '@peaceroad/markdown-it-cjk-breaks-mod';
66
93
 
67
- Provide an optional option `either`(default: false, which works as original version) to determine whether allowing removing linebreak when either the character before **OR** after the linebreak is east asian character.
94
+ const md = MarkdownIt({ html: true }).use(cjkBreaks, {
95
+ either: true,
96
+ normalizeSoftBreaks: true
97
+ });
68
98
 
69
- ```js
70
- var md = require('markdown-it')();
71
- var cjk_breaks = require('markdown-it-cjk-breaks');
72
-
73
- md.use(cjk_breaks, {either: true}); // << set either to true
74
-
75
- md.render(`
76
- あおえ
77
- うい
78
- aoe
79
- ui
80
- `);
81
-
82
- // returns:
83
- //
84
- //<p>あおえういaoe <!-- linebreak between `い` and `a` is removed -->
85
- //ui</p>
99
+ md.render('**漢**\nb');
100
+ // <p><strong>漢</strong>b</p>
86
101
  ```
87
102
 
88
- ## Original
103
+ ## Behavior Notes
89
104
 
90
- - [markdown-it-cjk-breaks](https://github.com/markdown-it/markdown-it-cjk-breaks)
105
+ - Break suppression follows CSS Text Level 3 style rules used by upstream: ZWSP-adjacent breaks are removed first; otherwise width-class checks are applied with Hangul exclusion.
106
+ - Punctuation spacing is never global formatting. It only runs when this plugin actually removes the break.
107
+ - The second punctuation pass handles inline markup boundaries (inline code, links/autolinks, images, inline HTML) when a raw newline boundary is verifiably present.
108
+ - Matching is fail-closed: if raw boundary reconstruction cannot be proven, no space is inserted.
109
+ - If a `softbreak` is still active between candidate tokens, spacing insertion is skipped.
91
110
 
92
- > Plugin for [markdown-it](https://github.com/markdown-it/markdown-it) that suppresses linebreaks between east asian characters.
111
+ ## Compatibility
93
112
 
94
- Normally newlines in a markdown text get rendered as newlines in output html text. Then browsers will usually render those newlines as whitespace (more smart behavior is included in w3c drafts, but not actually implemented by vendors).
113
+ - Module format: ESM (`"type": "module"`).
114
+ - Runtime: works in Node.js ESM environments and browser/VSCode bundling setups that support ESM dependencies.
115
+ - Runtime plugin code uses no Node-only APIs (`fs`, `path`, etc.); those are confined to tests.
116
+ - For plugin chains that rewrite inline text (for example `@peaceroad/markdown-it-strong-ja`), prefer `normalizeSoftBreaks: true` for stable behavior.
95
117
 
96
- This plugin finds and removes newlines that cannot be converted to space, algorithm matches [CSS Text Module Level 3](https://www.w3.org/TR/css-text-3/#line-break-transform):
97
-
98
- - If the character immediately before or immediately after the segment break is the zero-width space character (U+200B), then the break is removed, leaving behind the zero-width space.
99
- - Otherwise, if the East Asian Width property [UAX11] of both the character before and after the segment break is F, W, or H (not A), and neither side is Hangul, then the segment break is removed.
100
- - Otherwise, the segment break is converted to a space (U+0020).
101
-
102
- ## Install
103
-
104
- ```bash
105
- yarn add markdown-it-cjk-breaks
106
- ```
107
-
108
-
109
- ## Usage
110
-
111
- ```js
112
- var md = require('markdown-it')();
113
- var cjk_breaks = require('markdown-it-cjk-breaks');
114
-
115
- md.use(cjk_breaks);
116
-
117
- md.render(`
118
- あおえ
119
- うい
120
- aoe
121
- ui
122
- `);
123
-
124
- // returns:
125
- //
126
- //<p>あおえうい
127
- //aoe
128
- //ui</p>
129
- ```
118
+ ## Upstream And Credits
130
119
 
120
+ - Original: [markdown-it/markdown-it-cjk-breaks](https://github.com/markdown-it/markdown-it-cjk-breaks)
121
+ - Fork enhancement (`either`): [@sup39/markdown-it-cjk-breaks](https://www.npmjs.com/package/@sup39/markdown-it-cjk-breaks)
122
+ - Current package: [@peaceroad/markdown-it-cjk-breaks-mod](https://github.com/peaceroad/p7d-markdown-it-cjk-breaks-mod)
131
123
 
132
124
  ## License
133
125
 
package/index.js CHANGED
@@ -11,7 +11,6 @@ const DEFAULT_PUNCTUATION_CONFIG = create_punctuation_config(DEFAULT_PUNCTUATION
11
11
  const HANGUL_RE = /[\u1100-\u11FF\u302E\u302F\u3131-\u318E\u3200-\u321E\u3260-\u327E\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uFFA0-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/;
12
12
  /* eslint-enable max-len */
13
13
  const WHITESPACE_RE = /\s/;
14
- const WHITESPACE_LEAD_RE = /^\s/;
15
14
 
16
15
 
17
16
  function is_surrogate(c1, c2) {
@@ -34,6 +33,7 @@ function create_punctuation_config(targets) {
34
33
  for (var i = 0; i < targets.length; i++) {
35
34
  var value = targets[i];
36
35
  if (typeof value !== 'string' || value.length === 0) continue;
36
+ if (sequences.has(value)) continue;
37
37
  sequences.add(value);
38
38
  var valueLength = value.length;
39
39
  if (valueLength > maxLength) maxLength = valueLength;
@@ -45,7 +45,9 @@ function create_punctuation_config(targets) {
45
45
  if (endChar) endCharMap[endChar] = true;
46
46
  }
47
47
 
48
- lengths.sort(function (a, b) { return b - a; });
48
+ if (lengths.length > 1) {
49
+ lengths.sort(function (a, b) { return b - a; });
50
+ }
49
51
  return { sequences: sequences, maxLength: maxLength, endCharMap: endCharMap, lengths: lengths };
50
52
  }
51
53
 
@@ -126,9 +128,9 @@ function matches_punctuation_sequence(trailing, punctuationConfig, skipEndCharCh
126
128
  if (!trailing || !punctuationConfig || punctuationConfig.maxLength === 0) return false;
127
129
 
128
130
  var sequences = punctuationConfig.sequences;
129
- var endCharMap = punctuationConfig.endCharMap;
130
131
  var lengths = punctuationConfig.lengths;
131
132
  if (!skipEndCharCheck) {
133
+ var endCharMap = punctuationConfig.endCharMap;
132
134
  var endChar = get_last_char(trailing);
133
135
  if (!endCharMap[endChar]) return false;
134
136
  }
@@ -136,7 +138,7 @@ function matches_punctuation_sequence(trailing, punctuationConfig, skipEndCharCh
136
138
  for (var i = 0; i < lengths.length; i++) {
137
139
  var len = lengths[i];
138
140
  if (len > trailingLength) continue;
139
- var fragment = trailing.slice(-len);
141
+ var fragment = len === trailingLength ? trailing : trailing.slice(-len);
140
142
  if (sequences.has(fragment)) return true;
141
143
  }
142
144
  return false;
@@ -160,6 +162,12 @@ function is_printable_ascii(ch) {
160
162
  }
161
163
 
162
164
 
165
+ function has_leading_whitespace(text) {
166
+ if (!text) return false;
167
+ return WHITESPACE_RE.test(text.charAt(0));
168
+ }
169
+
170
+
163
171
  function is_fullwidth_or_wide(ch) {
164
172
  var width = get_cjk_width_class(ch);
165
173
  return width === 'F' || width === 'W';
@@ -208,9 +216,8 @@ function process_inlines(tokens, ctx, inlineToken) {
208
216
  var normalizeSoftBreaks = ctx.normalizeSoftBreaks;
209
217
  var punctuationSpace = ctx.punctuationSpace;
210
218
  var punctuationConfig = ctx.punctuationConfig;
211
- var maxPunctuationLength = ctx.maxPunctuationLength;
212
219
  var considerInlineBoundaries = ctx.considerInlineBoundaries;
213
- var needsPunctuation = punctuationSpace && punctuationConfig && maxPunctuationLength > 0;
220
+ var needsPunctuation = punctuationSpace && punctuationConfig && ctx.maxPunctuationLength > 0;
214
221
  var punctuationEndCharMap = punctuationConfig ? punctuationConfig.endCharMap : null;
215
222
 
216
223
  if (!tokens || tokens.length === 0) return;
@@ -225,7 +232,8 @@ function process_inlines(tokens, ctx, inlineToken) {
225
232
  if (!widthCache) widthCache = Object.create(null);
226
233
  var cached = widthCache[ch];
227
234
  if (cached !== undefined) return cached;
228
- var width = get_cjk_width_class(ch);
235
+ var width = eastAsianWidth(ch);
236
+ width = width === 'F' || width === 'W' || width === 'H' ? width : '';
229
237
  widthCache[ch] = width;
230
238
  return width;
231
239
  }
@@ -261,12 +269,10 @@ function process_inlines(tokens, ctx, inlineToken) {
261
269
 
262
270
  var nextIdx = nextTextIndex[i];
263
271
  if (nextIdx !== -1) {
264
- var nextContent = tokens[nextIdx].content || '';
265
- if (nextContent) {
266
- c1 = nextContent.charCodeAt(0);
267
- c2 = nextContent.charCodeAt(1);
268
- next = nextContent.slice(0, is_surrogate(c1, c2) ? 2 : 1);
269
- }
272
+ var nextContent = tokens[nextIdx].content;
273
+ c1 = nextContent.charCodeAt(0);
274
+ c2 = nextContent.charCodeAt(1);
275
+ next = nextContent.slice(0, is_surrogate(c1, c2) ? 2 : 1);
270
276
  }
271
277
 
272
278
  remove_break = false;
@@ -299,10 +305,9 @@ function process_inlines(tokens, ctx, inlineToken) {
299
305
 
300
306
  if (remove_break) {
301
307
  var insertPunctuationSpace = false;
302
- if (needsPunctuation && hasLastText && last && next && next !== '\u200b') {
308
+ if (needsPunctuation && hasLastText && nextIdx !== -1 && next !== '\u200b') {
303
309
  if (punctuationEndCharMap[last]) {
304
- var trailing = lastTextContent.slice(-maxPunctuationLength);
305
- if (matches_punctuation_sequence(trailing, punctuationConfig, true)) {
310
+ if (matches_punctuation_sequence(lastTextContent, punctuationConfig, true)) {
306
311
  if (!nextWidthComputed) {
307
312
  nextWidthClass = get_cached_width_class(next);
308
313
  }
@@ -422,10 +427,14 @@ function apply_missing_punctuation_spacing(tokens, inlineToken, punctuationSpace
422
427
  if (!inlineToken || !inlineToken.content) return;
423
428
  if (inlineToken.content.indexOf('\n') === -1) return;
424
429
  if (!tokens || tokens.length === 0) return;
425
- var maxPunctuationLength = punctuationConfig.maxLength;
426
- if (maxPunctuationLength <= 0) return;
430
+ if (punctuationConfig.maxLength <= 0) return;
427
431
  var endCharMap = punctuationConfig.endCharMap;
428
432
 
433
+ if (tokens.length === 1) {
434
+ apply_single_text_token_spacing(tokens, inlineToken, punctuationSpace, punctuationConfig);
435
+ return;
436
+ }
437
+
429
438
  var rawSearchState = { pos: 0 };
430
439
 
431
440
  for (var idx = 0; idx < tokens.length; idx++) {
@@ -434,13 +443,12 @@ function apply_missing_punctuation_spacing(tokens, inlineToken, punctuationSpace
434
443
 
435
444
  var endChar = get_last_char(current.content);
436
445
  if (!endCharMap[endChar]) continue;
437
- var trailing = current.content.slice(-maxPunctuationLength);
438
- if (!matches_punctuation_sequence(trailing, punctuationConfig, true)) continue;
446
+ if (!matches_punctuation_sequence(current.content, punctuationConfig, true)) continue;
439
447
 
440
448
  var nextInfo = find_next_visible_token(tokens, idx + 1);
441
449
  if (!nextInfo) continue;
442
- if (nextInfo.token.type === 'text' && WHITESPACE_LEAD_RE.test(nextInfo.token.content || '')) continue;
443
- if (has_active_break(tokens, idx, nextInfo.index)) continue;
450
+ if (nextInfo.token.type === 'text' && has_leading_whitespace(nextInfo.token.content)) continue;
451
+ if (nextInfo.hasActiveBreak) continue;
444
452
 
445
453
  if (!raw_boundary_includes_newline(inlineToken.content, tokens, idx, nextInfo.index, nextInfo.fragment, rawSearchState)) {
446
454
  continue;
@@ -450,50 +458,48 @@ function apply_missing_punctuation_spacing(tokens, inlineToken, punctuationSpace
450
458
  idx = nextInfo.index;
451
459
  }
452
460
 
453
- if (tokens.length === 1) {
454
- apply_single_text_token_spacing(tokens, inlineToken, punctuationSpace, punctuationConfig);
455
- }
456
- }
457
-
458
- function has_active_break(tokens, fromIdx, nextIdx) {
459
- for (var idx = fromIdx + 1; idx < nextIdx; idx++) {
460
- var token = tokens[idx];
461
- if (!token) continue;
462
- if (token.type === 'softbreak') return true;
463
- if (token.type === 'text' && token.content === '\n') return true;
464
- }
465
- return false;
466
461
  }
467
462
 
468
-
469
463
  function raw_boundary_includes_newline(source, tokens, fromIdx, nextIdx, afterFragment, state) {
470
464
  if (!source || !afterFragment) return false;
471
- var fragments = Array.isArray(afterFragment) ? afterFragment : [afterFragment];
472
465
  var beforeFragment = tokens[fromIdx].content || '';
473
466
  var betweenFragment = '';
474
467
  for (var k = fromIdx + 1; k < nextIdx; k++) {
475
468
  if (tokens[k].markup) betweenFragment += tokens[k].markup;
476
469
  }
477
- for (var i = 0; i < fragments.length; i++) {
478
- var fragment = fragments[i];
479
- if (!fragment) continue;
480
- var candidate = beforeFragment + betweenFragment + '\n' + fragment;
481
- var startPos = source.indexOf(candidate, state.pos);
482
- if (startPos === -1) continue;
483
- state.pos = startPos + candidate.length - fragment.length;
484
- return true;
470
+ if (Array.isArray(afterFragment)) {
471
+ for (var i = 0; i < afterFragment.length; i++) {
472
+ var fragment = afterFragment[i];
473
+ if (!fragment) continue;
474
+ var candidate = beforeFragment + betweenFragment + '\n' + fragment;
475
+ var startPos = source.indexOf(candidate, state.pos);
476
+ if (startPos === -1) continue;
477
+ state.pos = startPos + candidate.length - fragment.length;
478
+ return true;
479
+ }
480
+ return false;
485
481
  }
486
- return false;
482
+ var fragment = afterFragment;
483
+ if (!fragment) return false;
484
+ var candidate = beforeFragment + betweenFragment + '\n' + fragment;
485
+ var startPos = source.indexOf(candidate, state.pos);
486
+ if (startPos === -1) return false;
487
+ state.pos = startPos + candidate.length - fragment.length;
488
+ return true;
487
489
  }
488
490
 
489
491
 
490
492
  function find_next_visible_token(tokens, startIdx) {
493
+ var hasActiveBreak = false;
491
494
  for (var idx = startIdx; idx < tokens.length; idx++) {
492
495
  var token = tokens[idx];
493
496
  if (!token) continue;
497
+ if (!hasActiveBreak && (token.type === 'softbreak' || (token.type === 'text' && token.content === '\n'))) {
498
+ hasActiveBreak = true;
499
+ }
494
500
  var fragment = derive_after_fragment(token);
495
501
  if (!fragment) continue;
496
- return { index: idx, token: token, fragment: fragment };
502
+ return { index: idx, token: token, fragment: fragment, hasActiveBreak: hasActiveBreak };
497
503
  }
498
504
  return null;
499
505
  }
@@ -509,7 +515,7 @@ function derive_after_fragment(token) {
509
515
  if (markup && content) fragments.push(markup + content);
510
516
  if (markup) fragments.push(markup);
511
517
  if (content) fragments.push(content);
512
- return fragments;
518
+ return fragments.length > 0 ? fragments : '';
513
519
  }
514
520
  if (token.type === 'image') return '![';
515
521
  if (token.type === 'link_open') return token.markup || '[';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peaceroad/markdown-it-cjk-breaks-mod",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "type": "module",
5
5
  "description": "Suppress linebreaks between east asian (Especially Japanese) characters",
6
6
  "repository": {
@@ -22,7 +22,7 @@
22
22
  "eastasianwidth": "^0.3.0"
23
23
  },
24
24
  "devDependencies": {
25
- "@peaceroad/markdown-it-strong-ja": "^0.7.2",
25
+ "@peaceroad/markdown-it-strong-ja": "^0.8.0",
26
26
  "markdown-it": "^14.1.0"
27
27
  }
28
28
  }