@peaceroad/markdown-it-cjk-breaks-mod 0.1.0 → 0.1.2
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 +2 -2
- package/index.js +193 -77
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
### Punctuation spacing options
|
|
6
6
|
|
|
7
|
-
Fine-tune the trigger list with `spaceAfterPunctuationTargets`. Provide either a single string or an array and every exact match becomes eligible for automatic spacing. Defaults remain `['!', '?', '⁉', '!?', '?!', '!?', '?!']`.
|
|
7
|
+
Fine-tune the trigger list with `spaceAfterPunctuationTargets`. Provide either a single string or an array and every exact match becomes eligible for automatic spacing; this option replaces the defaults. Defaults remain `['!', '?', '⁉', '!?', '?!', '!?', '?!', '.', ':']`. 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.
|
|
8
8
|
|
|
9
9
|
Use `spaceAfterPunctuation` to inject a space every time this plugin suppresses a line break after punctuation. Accepts `'half'` for ASCII space, `'full'` for an ideographic space, or any custom string via a literal value.
|
|
10
10
|
|
|
@@ -125,4 +125,4 @@ ui
|
|
|
125
125
|
|
|
126
126
|
- markdown-it/markdown-it-cjk-breaks: [MIT](https://github.com/markdown-it/markdown-it-cjk-breaks/blob/master/LICENSE)
|
|
127
127
|
- @sup39/markdown-it-cjk-breaks: [MIT](https://www.npmjs.com/package/@sup39/markdown-it-cjk-breaks?activeTab=code)
|
|
128
|
-
- @peaceroad/markdown-it-cjk-breaks-mod: [MIT](https://github.com/peaceroad/p7d-markdown-it-cjk-breaks-mod/blob/main/LICENSE
|
|
128
|
+
- @peaceroad/markdown-it-cjk-breaks-mod: [MIT](https://github.com/peaceroad/p7d-markdown-it-cjk-breaks-mod/blob/main/LICENSE)
|
package/index.js
CHANGED
|
@@ -4,7 +4,7 @@ const { eastAsianWidth } = eastAsianWidthModule;
|
|
|
4
4
|
const ASCII_PRINTABLE_MIN = 0x21;
|
|
5
5
|
const ASCII_PRINTABLE_MAX = 0x7E;
|
|
6
6
|
const IDEOGRAPHIC_SPACE = '\u3000';
|
|
7
|
-
const DEFAULT_PUNCTUATION_TARGETS = ['!', '?', '⁉', '!?', '?!', '!?', '?!'];
|
|
7
|
+
const DEFAULT_PUNCTUATION_TARGETS = ['!', '?', '⁉', '!?', '?!', '!?', '?!', '.', ':'];
|
|
8
8
|
const DEFAULT_PUNCTUATION_CONFIG = create_punctuation_config(DEFAULT_PUNCTUATION_TARGETS);
|
|
9
9
|
|
|
10
10
|
|
|
@@ -48,14 +48,60 @@ function resolve_punctuation_space_option(opts) {
|
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
function resolve_punctuation_targets(opts) {
|
|
51
|
-
if (!opts
|
|
51
|
+
if (!opts) return DEFAULT_PUNCTUATION_CONFIG;
|
|
52
|
+
|
|
53
|
+
var hasCustomTargets = Object.prototype.hasOwnProperty.call(opts, 'spaceAfterPunctuationTargets');
|
|
54
|
+
var baseTargets;
|
|
55
|
+
|
|
56
|
+
if (!hasCustomTargets) {
|
|
57
|
+
baseTargets = DEFAULT_PUNCTUATION_TARGETS.slice();
|
|
58
|
+
} else {
|
|
59
|
+
var customTargets = opts.spaceAfterPunctuationTargets;
|
|
60
|
+
if (customTargets === null || customTargets === false) return null;
|
|
61
|
+
if (typeof customTargets === 'string') {
|
|
62
|
+
if (customTargets.length === 0) return null;
|
|
63
|
+
baseTargets = [ customTargets ];
|
|
64
|
+
} else if (Array.isArray(customTargets)) {
|
|
65
|
+
if (customTargets.length === 0) return null;
|
|
66
|
+
baseTargets = customTargets.slice();
|
|
67
|
+
} else {
|
|
68
|
+
baseTargets = DEFAULT_PUNCTUATION_TARGETS.slice();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
var addTargets = opts.spaceAfterPunctuationTargetsAdd;
|
|
73
|
+
if (addTargets !== undefined) {
|
|
74
|
+
var addList = [];
|
|
75
|
+
if (typeof addTargets === 'string') {
|
|
76
|
+
if (addTargets.length > 0) addList = [ addTargets ];
|
|
77
|
+
} else if (Array.isArray(addTargets)) {
|
|
78
|
+
addList = addTargets;
|
|
79
|
+
}
|
|
80
|
+
if (addList.length > 0) {
|
|
81
|
+
baseTargets = baseTargets.concat(addList);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
52
84
|
|
|
53
|
-
var
|
|
54
|
-
if (
|
|
55
|
-
|
|
85
|
+
var removeTargets = opts.spaceAfterPunctuationTargetsRemove;
|
|
86
|
+
if (removeTargets !== undefined) {
|
|
87
|
+
var removeList = [];
|
|
88
|
+
if (typeof removeTargets === 'string') {
|
|
89
|
+
if (removeTargets.length > 0) removeList = [ removeTargets ];
|
|
90
|
+
} else if (Array.isArray(removeTargets)) {
|
|
91
|
+
removeList = removeTargets;
|
|
92
|
+
}
|
|
93
|
+
if (removeList.length > 0) {
|
|
94
|
+
var removeConfig = create_punctuation_config(removeList);
|
|
95
|
+
if (removeConfig.sequences.size > 0) {
|
|
96
|
+
baseTargets = baseTargets.filter(function (target) {
|
|
97
|
+
return !removeConfig.sequences.has(target);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
56
102
|
|
|
57
|
-
var config = create_punctuation_config(
|
|
58
|
-
return config.sequences.size === 0 ?
|
|
103
|
+
var config = create_punctuation_config(baseTargets);
|
|
104
|
+
return config.sequences.size === 0 ? null : config;
|
|
59
105
|
}
|
|
60
106
|
|
|
61
107
|
|
|
@@ -94,96 +140,153 @@ function get_cjk_width_class(ch) {
|
|
|
94
140
|
return width === 'F' || width === 'W' || width === 'H' ? width : '';
|
|
95
141
|
}
|
|
96
142
|
|
|
143
|
+
function build_next_text_info(tokens) {
|
|
144
|
+
var nextTextIndex = new Array(tokens.length);
|
|
145
|
+
var nextSkippedEmpty = new Array(tokens.length);
|
|
146
|
+
var nextNonEmpty = -1;
|
|
147
|
+
var sawEmpty = false;
|
|
148
|
+
|
|
149
|
+
for (var idx = tokens.length - 1; idx >= 0; idx--) {
|
|
150
|
+
nextTextIndex[idx] = nextNonEmpty;
|
|
151
|
+
nextSkippedEmpty[idx] = sawEmpty;
|
|
152
|
+
|
|
153
|
+
var token = tokens[idx];
|
|
154
|
+
if (!token || token.type !== 'text') continue;
|
|
155
|
+
|
|
156
|
+
if (!token.content) {
|
|
157
|
+
sawEmpty = true;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
nextNonEmpty = idx;
|
|
162
|
+
sawEmpty = false;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
nextTextIndex: nextTextIndex,
|
|
167
|
+
nextSkippedEmpty: nextSkippedEmpty
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
97
171
|
|
|
98
172
|
function process_inlines(tokens, state, ctx, inlineToken) {
|
|
99
|
-
var i,
|
|
173
|
+
var i, last, trailing, next, c1, c2, remove_break;
|
|
100
174
|
var either = ctx.either;
|
|
101
175
|
var normalizeSoftBreaks = ctx.normalizeSoftBreaks;
|
|
102
176
|
var punctuationSpace = ctx.punctuationSpace;
|
|
103
177
|
var punctuationConfig = ctx.punctuationConfig;
|
|
104
178
|
var maxPunctuationLength = ctx.maxPunctuationLength;
|
|
105
179
|
var considerInlineBoundaries = ctx.considerInlineBoundaries;
|
|
180
|
+
var needsPunctuation = punctuationSpace && punctuationConfig && maxPunctuationLength > 0;
|
|
106
181
|
|
|
107
182
|
if (normalizeSoftBreaks) normalize_text_tokens(tokens);
|
|
108
183
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
184
|
+
var nextInfo = build_next_text_info(tokens);
|
|
185
|
+
var nextTextIndex = nextInfo.nextTextIndex;
|
|
186
|
+
var nextSkippedEmpty = nextInfo.nextSkippedEmpty;
|
|
187
|
+
|
|
188
|
+
var widthCache = Object.create(null);
|
|
189
|
+
function get_cached_width_class(ch) {
|
|
190
|
+
if (!ch) return '';
|
|
191
|
+
var cached = widthCache[ch];
|
|
192
|
+
if (cached !== undefined) return cached;
|
|
193
|
+
var width = get_cjk_width_class(ch);
|
|
194
|
+
widthCache[ch] = width;
|
|
195
|
+
return width;
|
|
196
|
+
}
|
|
121
197
|
|
|
122
|
-
|
|
123
|
-
|
|
198
|
+
var lastTextContent = '';
|
|
199
|
+
var hasLastText = false;
|
|
200
|
+
var sawEmptySinceLast = false;
|
|
124
201
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
202
|
+
for (i = 0; i < tokens.length; i++) {
|
|
203
|
+
var token = tokens[i];
|
|
204
|
+
var isSoftbreakToken = token.type === 'softbreak';
|
|
205
|
+
var isTextBreakToken = token.type === 'text' && token.content === '\n';
|
|
206
|
+
if (isSoftbreakToken || isTextBreakToken) {
|
|
207
|
+
// default last/next character to space
|
|
208
|
+
last = next = ' ';
|
|
209
|
+
trailing = '';
|
|
210
|
+
var trailingMatchesPunctuation = false;
|
|
211
|
+
|
|
212
|
+
var skippedEmptyBefore = sawEmptySinceLast;
|
|
213
|
+
var skippedEmptyAfter = nextSkippedEmpty[i];
|
|
214
|
+
|
|
215
|
+
if (hasLastText) {
|
|
216
|
+
c1 = lastTextContent.charCodeAt(lastTextContent.length - 2);
|
|
217
|
+
c2 = lastTextContent.charCodeAt(lastTextContent.length - 1);
|
|
218
|
+
last = lastTextContent.slice(is_surrogate(c1, c2) ? -2 : -1);
|
|
219
|
+
if (needsPunctuation) {
|
|
220
|
+
trailing = lastTextContent.slice(-maxPunctuationLength);
|
|
221
|
+
trailingMatchesPunctuation = matches_punctuation_sequence(trailing, punctuationConfig);
|
|
222
|
+
}
|
|
139
223
|
}
|
|
140
|
-
break;
|
|
141
|
-
}
|
|
142
224
|
|
|
143
|
-
|
|
144
|
-
if (
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
225
|
+
var nextIdx = nextTextIndex[i];
|
|
226
|
+
if (nextIdx !== -1) {
|
|
227
|
+
var nextContent = tokens[nextIdx].content || '';
|
|
228
|
+
if (nextContent) {
|
|
229
|
+
c1 = nextContent.charCodeAt(0);
|
|
230
|
+
c2 = nextContent.charCodeAt(1);
|
|
231
|
+
next = nextContent.slice(0, is_surrogate(c1, c2) ? 2 : 1);
|
|
232
|
+
}
|
|
149
233
|
}
|
|
150
234
|
|
|
151
|
-
|
|
152
|
-
c2 = tokens[j].content.charCodeAt(1);
|
|
235
|
+
remove_break = false;
|
|
153
236
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
237
|
+
// remove newline if it's adjacent to ZWSP
|
|
238
|
+
if (last === '\u200b' || next === '\u200b') remove_break = true;
|
|
157
239
|
|
|
158
|
-
|
|
240
|
+
var lastWidthClass = '';
|
|
241
|
+
var nextWidthClass = '';
|
|
159
242
|
|
|
160
|
-
|
|
161
|
-
|
|
243
|
+
// remove newline if both characters AND/OR fullwidth (F), wide (W) or
|
|
244
|
+
// halfwidth (H), but not Hangul
|
|
245
|
+
var tLast = false;
|
|
246
|
+
var tNext = false;
|
|
162
247
|
|
|
163
|
-
|
|
164
|
-
|
|
248
|
+
var needsWidthForRemoval = !remove_break;
|
|
249
|
+
var needsWidthForPunctuation = punctuationSpace && trailingMatchesPunctuation && last && next && next !== '\u200b';
|
|
165
250
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
251
|
+
if (needsWidthForRemoval || needsWidthForPunctuation) {
|
|
252
|
+
if (needsWidthForRemoval) {
|
|
253
|
+
lastWidthClass = get_cached_width_class(last);
|
|
254
|
+
}
|
|
255
|
+
nextWidthClass = get_cached_width_class(next);
|
|
256
|
+
|
|
257
|
+
if (needsWidthForRemoval) {
|
|
258
|
+
tLast = lastWidthClass !== '';
|
|
259
|
+
tNext = nextWidthClass !== '';
|
|
260
|
+
|
|
261
|
+
if (considerInlineBoundaries && (skippedEmptyBefore || skippedEmptyAfter) && tLast && tNext) {
|
|
262
|
+
tLast = false;
|
|
263
|
+
tNext = false;
|
|
264
|
+
}
|
|
265
|
+
if (either ? tLast || tNext : tLast && tNext) {
|
|
266
|
+
if (!is_hangul(last) && !is_hangul(next)) remove_break = true;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
170
270
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
271
|
+
if (remove_break) {
|
|
272
|
+
var insertPunctuationSpace = false;
|
|
273
|
+
if (punctuationSpace && punctuationConfig && trailingMatchesPunctuation && last && next && next !== '\u200b') {
|
|
274
|
+
var nextIsFullwidthOrWide = nextWidthClass === 'F' || nextWidthClass === 'W';
|
|
275
|
+
if (is_printable_ascii(next) || nextIsFullwidthOrWide) insertPunctuationSpace = true;
|
|
276
|
+
}
|
|
277
|
+
token.type = 'text';
|
|
278
|
+
token.content = insertPunctuationSpace ? punctuationSpace : '';
|
|
279
|
+
}
|
|
177
280
|
}
|
|
178
281
|
|
|
179
|
-
if (
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
282
|
+
if (token.type === 'text') {
|
|
283
|
+
if (!token.content) {
|
|
284
|
+
sawEmptySinceLast = true;
|
|
285
|
+
} else {
|
|
286
|
+
lastTextContent = token.content;
|
|
287
|
+
hasLastText = true;
|
|
288
|
+
sawEmptySinceLast = false;
|
|
184
289
|
}
|
|
185
|
-
tokens[i].type = 'text';
|
|
186
|
-
tokens[i].content = insertPunctuationSpace ? punctuationSpace : '';
|
|
187
290
|
}
|
|
188
291
|
}
|
|
189
292
|
|
|
@@ -194,16 +297,29 @@ function process_inlines(tokens, state, ctx, inlineToken) {
|
|
|
194
297
|
|
|
195
298
|
|
|
196
299
|
function normalize_text_tokens(tokens) {
|
|
300
|
+
var normalized = null;
|
|
301
|
+
|
|
197
302
|
for (var idx = 0; idx < tokens.length; idx++) {
|
|
198
303
|
var token = tokens[idx];
|
|
199
|
-
if (token.type !== 'text')
|
|
200
|
-
|
|
304
|
+
if (token.type !== 'text' || !token.content || token.content.indexOf('\n') === -1) {
|
|
305
|
+
if (normalized) normalized.push(token);
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (!normalized) {
|
|
310
|
+
normalized = tokens.slice(0, idx);
|
|
311
|
+
}
|
|
201
312
|
|
|
202
313
|
var replacement = split_text_token(token);
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
314
|
+
for (var r = 0; r < replacement.length; r++) {
|
|
315
|
+
normalized.push(replacement[r]);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (normalized) {
|
|
320
|
+
tokens.length = 0;
|
|
321
|
+
for (var j = 0; j < normalized.length; j++) {
|
|
322
|
+
tokens.push(normalized[j]);
|
|
207
323
|
}
|
|
208
324
|
}
|
|
209
325
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peaceroad/markdown-it-cjk-breaks-mod",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Suppress linebreaks between east asian (Especially Japanese) characters",
|
|
6
|
-
"repository":
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/peaceroad/p7d-markdown-it-cjk-breaks-mod.git"
|
|
9
|
+
},
|
|
7
10
|
"license": "MIT",
|
|
11
|
+
"author": "peaceroad <peaceroad@gmail.com>",
|
|
8
12
|
"scripts": {
|
|
9
13
|
"test": "node test/test.js"
|
|
10
14
|
},
|
|
@@ -13,11 +17,12 @@
|
|
|
13
17
|
"README.md",
|
|
14
18
|
"LICENSE"
|
|
15
19
|
],
|
|
20
|
+
"main": "index.js",
|
|
16
21
|
"dependencies": {
|
|
17
22
|
"eastasianwidth": "^0.3.0"
|
|
18
23
|
},
|
|
19
24
|
"devDependencies": {
|
|
20
|
-
"@peaceroad/markdown-it-strong-ja": "^0.5.
|
|
25
|
+
"@peaceroad/markdown-it-strong-ja": "^0.5.5",
|
|
21
26
|
"markdown-it": "^14.1.0"
|
|
22
27
|
}
|
|
23
28
|
}
|