@peaceroad/markdown-it-table-ex 0.3.0 → 0.3.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/index.js +316 -182
- package/package.json +3 -3
package/index.js
CHANGED
|
@@ -34,15 +34,17 @@ const isStrongWrappedInline = (inline, allowFallback) => {
|
|
|
34
34
|
if (!inline || typeof inline.content !== 'string') return false;
|
|
35
35
|
const content = inline.content;
|
|
36
36
|
if (!content.startsWith('**') || !content.endsWith('**')) return false;
|
|
37
|
-
if (
|
|
38
|
-
if (
|
|
39
|
-
return
|
|
37
|
+
if (allowFallback) return true;
|
|
38
|
+
if (!Array.isArray(inline.children)) return false;
|
|
39
|
+
return getLeadingStrongCloseIndex(inline) !== -1;
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
const hasLeadingStrongMarker = (inline, allowFallback) => {
|
|
43
|
-
if (
|
|
44
|
-
if (!
|
|
45
|
-
|
|
43
|
+
if (!inline || typeof inline.content !== 'string') return false;
|
|
44
|
+
if (!inline.content.startsWith('**')) return false;
|
|
45
|
+
if (allowFallback) return true;
|
|
46
|
+
if (!Array.isArray(inline.children)) return false;
|
|
47
|
+
return getLeadingStrongCloseIndex(inline) !== -1;
|
|
46
48
|
};
|
|
47
49
|
|
|
48
50
|
const hasInlineRule = (md, name) => {
|
|
@@ -54,6 +56,84 @@ const hasInlineRule = (md, name) => {
|
|
|
54
56
|
return false;
|
|
55
57
|
};
|
|
56
58
|
|
|
59
|
+
const createNewlineToken = (Token) => {
|
|
60
|
+
const token = new Token('text', '', 0);
|
|
61
|
+
token.content = '\n';
|
|
62
|
+
return token;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const setInlineText = (inline, Token, text) => {
|
|
66
|
+
inline.content = text;
|
|
67
|
+
const textToken = new Token('text', '', 0);
|
|
68
|
+
textToken.content = text;
|
|
69
|
+
textToken.level = 0;
|
|
70
|
+
inline.children = [textToken];
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const removeHeaderCellAt = (tokens, openIdx) => {
|
|
74
|
+
if (!tokens[openIdx] || tokens[openIdx].type !== 'th_open') return;
|
|
75
|
+
let deleteCount = 3;
|
|
76
|
+
const next = tokens[openIdx + 3];
|
|
77
|
+
if (next && next.type === 'text' && next.content === '\n') {
|
|
78
|
+
deleteCount += 1;
|
|
79
|
+
}
|
|
80
|
+
tokens.splice(openIdx, deleteCount);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const findFirstHeaderThPos = (tokens, tableOpenIdx, allowFallback) => {
|
|
84
|
+
let inThead = false;
|
|
85
|
+
for (let i = tableOpenIdx + 1; i < tokens.length; i++) {
|
|
86
|
+
const type = tokens[i].type;
|
|
87
|
+
if (type === 'table_close') break;
|
|
88
|
+
if (type === 'thead_open') {
|
|
89
|
+
inThead = true;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (!inThead) continue;
|
|
93
|
+
if (type === 'thead_close') break;
|
|
94
|
+
if (type !== 'th_open') continue;
|
|
95
|
+
const inline = tokens[i + 1];
|
|
96
|
+
if (inline && (inline.content === '' || isStrongWrappedInline(inline, allowFallback))) {
|
|
97
|
+
return i;
|
|
98
|
+
}
|
|
99
|
+
return -1;
|
|
100
|
+
}
|
|
101
|
+
return -1;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const findFirstHeaderCellPos = (tokens, tableOpenIdx) => {
|
|
105
|
+
let inThead = false;
|
|
106
|
+
for (let i = tableOpenIdx + 1; i < tokens.length; i++) {
|
|
107
|
+
const type = tokens[i].type;
|
|
108
|
+
if (type === 'table_close') break;
|
|
109
|
+
if (type === 'thead_open') {
|
|
110
|
+
inThead = true;
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (!inThead) continue;
|
|
114
|
+
if (type === 'thead_close') break;
|
|
115
|
+
if (type === 'th_open') return i;
|
|
116
|
+
}
|
|
117
|
+
return -1;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const createColgroupRegexes = (colgroupWithNoAsterisk) => {
|
|
121
|
+
if (colgroupWithNoAsterisk) {
|
|
122
|
+
return {
|
|
123
|
+
singleHeaderGroup: /^([^::]+)(?::\s*|: +)/,
|
|
124
|
+
singleHeaderStrip: /^[^::]+(?::\s*|: +)(.*)$/,
|
|
125
|
+
multiHeaderGroup: /^([^::]+)(?::\s*|: +)/,
|
|
126
|
+
multiHeaderStrip: /^[^::]+(?::\s*|: +)(.*)$/
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
singleHeaderGroup: /^\*\*([^*::]+)[::]\*\*\s*/,
|
|
131
|
+
singleHeaderStrip: /^\*\*[^*::]+[::]\*\*\s*(.*)$/,
|
|
132
|
+
multiHeaderGroup: /^\*\*([^*::]+)[::]\*\*/,
|
|
133
|
+
multiHeaderStrip: /^\*\*[^*::]+[::]\*\*\s*(.*)$/
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
|
|
57
137
|
const createTokenTemplate = (tokenType, tag, nesting, level) => ({
|
|
58
138
|
type: tokenType,
|
|
59
139
|
tag: tag,
|
|
@@ -211,24 +291,28 @@ const removeStrongWrappers = (inline, allowFallback) => {
|
|
|
211
291
|
|
|
212
292
|
const addTheadThScope = (state, theadVar, allowFallback) => {
|
|
213
293
|
const tokens = state.tokens;
|
|
214
|
-
let firstThPos = theadVar.
|
|
215
|
-
let j = theadVar.i +
|
|
216
|
-
|
|
294
|
+
let firstThPos = theadVar.firstThPos;
|
|
295
|
+
let j = theadVar.i + 1;
|
|
296
|
+
let isFirstRow = true;
|
|
297
|
+
let firstRowFirstThSeen = false;
|
|
217
298
|
while (j < tokens.length) {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
299
|
+
const tokenType = tokens[j].type;
|
|
300
|
+
if (tokenType === 'th_open') {
|
|
301
|
+
tokens[j].attrSet('scope', 'col');
|
|
302
|
+
if (isFirstRow && !firstRowFirstThSeen) {
|
|
303
|
+
firstRowFirstThSeen = true;
|
|
221
304
|
const inline = tokens[j + 1];
|
|
222
|
-
const content = inline.content;
|
|
305
|
+
const content = inline && typeof inline.content === 'string' ? inline.content : '';
|
|
223
306
|
if (content === '' || isStrongWrappedInline(inline, allowFallback)) {
|
|
224
|
-
firstThPos = j
|
|
225
|
-
// Only remove strong tags from the first th content for matrix processing
|
|
226
|
-
// The actual removal will be done in changeTdToTh if matrix conditions are met
|
|
307
|
+
firstThPos = j;
|
|
227
308
|
}
|
|
228
309
|
}
|
|
310
|
+
} else if (tokenType === 'tr_close' && isFirstRow) {
|
|
311
|
+
isFirstRow = false;
|
|
312
|
+
} else if (tokenType === 'thead_close') {
|
|
313
|
+
break;
|
|
229
314
|
}
|
|
230
|
-
|
|
231
|
-
j++
|
|
315
|
+
j++;
|
|
232
316
|
}
|
|
233
317
|
return {i: j, firstThPos: firstThPos}
|
|
234
318
|
}
|
|
@@ -276,7 +360,7 @@ const checkTbody = (state, tbodyVar, allowFallback) => {
|
|
|
276
360
|
return { i: j, isAllFirstTh: isAllFirstTh, tbodyFirstThPoses: tbodyFirstThPoses}
|
|
277
361
|
}
|
|
278
362
|
|
|
279
|
-
const setColgroup = (state, tableOpenIdx, opt, allowFallback) => {
|
|
363
|
+
const setColgroup = (state, tableOpenIdx, opt, allowFallback, regexes) => {
|
|
280
364
|
const tokens = state.tokens;
|
|
281
365
|
const Token = state.Token;
|
|
282
366
|
|
|
@@ -308,22 +392,24 @@ const setColgroup = (state, tableOpenIdx, opt, allowFallback) => {
|
|
|
308
392
|
headerCount: 0
|
|
309
393
|
};
|
|
310
394
|
|
|
311
|
-
const colgroupMatchReg =
|
|
312
|
-
|
|
313
|
-
: /^\*\*([^*::]+)[::]\*\*\s*/;
|
|
314
|
-
const origColgroupMatchReg = opt.colgroupWithNoAsterisk
|
|
315
|
-
? /^[^::]+(?::|:)\s*(.*)$/
|
|
316
|
-
: /^\*\*[^*::]+[::]\*\*\s*(.*)$/;
|
|
395
|
+
const colgroupMatchReg = regexes.singleHeaderGroup;
|
|
396
|
+
const origColgroupMatchReg = regexes.singleHeaderStrip;
|
|
317
397
|
|
|
318
398
|
let thIdx = tr1 + 1;
|
|
319
|
-
const
|
|
399
|
+
const origThInfos = [];
|
|
320
400
|
let trCloseIdx = -1;
|
|
321
401
|
|
|
322
402
|
while (thIdx < tokens.length) {
|
|
323
403
|
const tokenType = tokens[thIdx].type;
|
|
324
404
|
if (tokenType === 'th_open') {
|
|
325
405
|
const inline = tokens[thIdx + 1];
|
|
326
|
-
|
|
406
|
+
let map = null;
|
|
407
|
+
if (Array.isArray(tokens[thIdx].map)) {
|
|
408
|
+
map = tokens[thIdx].map.slice();
|
|
409
|
+
} else if (inline && Array.isArray(inline.map)) {
|
|
410
|
+
map = inline.map.slice();
|
|
411
|
+
}
|
|
412
|
+
origThInfos.push({ inline, map });
|
|
327
413
|
const content = inline.content;
|
|
328
414
|
const hasLeadingStrong = hasLeadingStrongMarker(inline, allowFallback);
|
|
329
415
|
let match = null;
|
|
@@ -367,7 +453,7 @@ const setColgroup = (state, tableOpenIdx, opt, allowFallback) => {
|
|
|
367
453
|
if (hasSpan) {
|
|
368
454
|
const insertTokens = [
|
|
369
455
|
new Token('colgroup_open', 'colgroup', 1),
|
|
370
|
-
|
|
456
|
+
createNewlineToken(Token)
|
|
371
457
|
];
|
|
372
458
|
|
|
373
459
|
for (let i = 0; i < groupData.spans.length; i++) {
|
|
@@ -377,13 +463,13 @@ const setColgroup = (state, tableOpenIdx, opt, allowFallback) => {
|
|
|
377
463
|
}
|
|
378
464
|
insertTokens.push(
|
|
379
465
|
colOpen,
|
|
380
|
-
|
|
466
|
+
createNewlineToken(Token)
|
|
381
467
|
);
|
|
382
468
|
}
|
|
383
469
|
|
|
384
470
|
insertTokens.push(
|
|
385
471
|
new Token('colgroup_close', 'colgroup', -1),
|
|
386
|
-
|
|
472
|
+
createNewlineToken(Token)
|
|
387
473
|
);
|
|
388
474
|
|
|
389
475
|
tokens.splice(tableOpenIdx + 1, 0, ...insertTokens);
|
|
@@ -391,7 +477,6 @@ const setColgroup = (state, tableOpenIdx, opt, allowFallback) => {
|
|
|
391
477
|
// Update indices
|
|
392
478
|
const offset = insertTokens.length;
|
|
393
479
|
tr1 += offset;
|
|
394
|
-
theadClose += offset;
|
|
395
480
|
trCloseIdx += offset;
|
|
396
481
|
}
|
|
397
482
|
|
|
@@ -399,41 +484,44 @@ const setColgroup = (state, tableOpenIdx, opt, allowFallback) => {
|
|
|
399
484
|
|
|
400
485
|
// Create new rows more efficiently
|
|
401
486
|
const newTr1 = [
|
|
402
|
-
|
|
487
|
+
createNewlineToken(Token),
|
|
403
488
|
new Token('tr_open', 'tr', 1),
|
|
404
|
-
|
|
489
|
+
createNewlineToken(Token)
|
|
405
490
|
];
|
|
406
491
|
|
|
407
492
|
const newTr2 = [
|
|
408
493
|
new Token('tr_open', 'tr', 1),
|
|
409
|
-
|
|
494
|
+
createNewlineToken(Token)
|
|
410
495
|
];
|
|
411
496
|
|
|
412
497
|
let thPtr = 0;
|
|
413
498
|
for (let i = 0; i < groupData.spans.length; i++) {
|
|
499
|
+
const origInfo = origThInfos[thPtr];
|
|
500
|
+
const cellMap = origInfo && origInfo.map ? origInfo.map : null;
|
|
414
501
|
if (groupNames[i] === null) {
|
|
415
502
|
// Leftmost cell: rowspan=2
|
|
416
503
|
const thOpen = new Token('th_open', 'th', 1);
|
|
417
504
|
thOpen.attrSet('rowspan', '2');
|
|
418
505
|
thOpen.attrSet('scope', 'col');
|
|
506
|
+
if (cellMap) thOpen.map = cellMap;
|
|
419
507
|
|
|
420
508
|
const thInline = new Token('inline', '', 0);
|
|
421
|
-
const origInline =
|
|
509
|
+
const origInline = origInfo ? origInfo.inline : null;
|
|
422
510
|
|
|
423
511
|
if (origInline) {
|
|
424
512
|
removeStrongWrappers(origInline, allowFallback);
|
|
425
513
|
thInline.content = origInline.content;
|
|
426
514
|
thInline.children = Array.isArray(origInline.children) ? origInline.children : [];
|
|
515
|
+
if (cellMap) thInline.map = cellMap;
|
|
427
516
|
} else {
|
|
428
|
-
thInline
|
|
429
|
-
thInline.children = [];
|
|
517
|
+
setInlineText(thInline, Token, '');
|
|
430
518
|
}
|
|
431
519
|
|
|
432
520
|
newTr1.push(
|
|
433
521
|
thOpen,
|
|
434
522
|
thInline,
|
|
435
523
|
new Token('th_close', 'th', -1),
|
|
436
|
-
|
|
524
|
+
createNewlineToken(Token)
|
|
437
525
|
);
|
|
438
526
|
thPtr++;
|
|
439
527
|
} else {
|
|
@@ -443,25 +531,29 @@ const setColgroup = (state, tableOpenIdx, opt, allowFallback) => {
|
|
|
443
531
|
thOpen.attrSet('colspan', groupData.spans[i].toString());
|
|
444
532
|
}
|
|
445
533
|
thOpen.attrSet('scope', 'col');
|
|
534
|
+
if (cellMap) thOpen.map = cellMap;
|
|
446
535
|
|
|
447
536
|
const thInline = new Token('inline', '', 0);
|
|
448
|
-
thInline
|
|
449
|
-
thInline.
|
|
537
|
+
setInlineText(thInline, Token, groupNames[i]);
|
|
538
|
+
if (cellMap) thInline.map = cellMap;
|
|
450
539
|
|
|
451
540
|
newTr1.push(
|
|
452
541
|
thOpen,
|
|
453
542
|
thInline,
|
|
454
543
|
new Token('th_close', 'th', -1),
|
|
455
|
-
|
|
544
|
+
createNewlineToken(Token)
|
|
456
545
|
);
|
|
457
546
|
|
|
458
547
|
// Second row: each item in the group
|
|
459
548
|
for (let j = 0; j < groupData.spans[i]; j++) {
|
|
549
|
+
const subInfo = origThInfos[thPtr];
|
|
550
|
+
const subMap = subInfo && subInfo.map ? subInfo.map : null;
|
|
460
551
|
const th2Open = new Token('th_open', 'th', 1);
|
|
461
552
|
th2Open.attrSet('scope', 'col');
|
|
553
|
+
if (subMap) th2Open.map = subMap;
|
|
462
554
|
|
|
463
555
|
const th2Inline = new Token('inline', '', 0);
|
|
464
|
-
const origInline =
|
|
556
|
+
const origInline = subInfo ? subInfo.inline : null;
|
|
465
557
|
const orig = origInline?.content || '';
|
|
466
558
|
let match = null;
|
|
467
559
|
if (opt.colgroupWithNoAsterisk) {
|
|
@@ -471,14 +563,14 @@ const setColgroup = (state, tableOpenIdx, opt, allowFallback) => {
|
|
|
471
563
|
} else if (hasLeadingStrongMarker(origInline, allowFallback)) {
|
|
472
564
|
match = orig.match(origColgroupMatchReg);
|
|
473
565
|
}
|
|
474
|
-
th2Inline
|
|
475
|
-
|
|
566
|
+
setInlineText(th2Inline, Token, match ? match[1] : orig);
|
|
567
|
+
if (subMap) th2Inline.map = subMap;
|
|
476
568
|
|
|
477
569
|
newTr2.push(
|
|
478
570
|
th2Open,
|
|
479
571
|
th2Inline,
|
|
480
572
|
new Token('th_close', 'th', -1),
|
|
481
|
-
|
|
573
|
+
createNewlineToken(Token)
|
|
482
574
|
);
|
|
483
575
|
thPtr++;
|
|
484
576
|
}
|
|
@@ -487,12 +579,12 @@ const setColgroup = (state, tableOpenIdx, opt, allowFallback) => {
|
|
|
487
579
|
|
|
488
580
|
newTr1.push(
|
|
489
581
|
new Token('tr_close', 'tr', -1),
|
|
490
|
-
|
|
582
|
+
createNewlineToken(Token)
|
|
491
583
|
);
|
|
492
584
|
|
|
493
585
|
newTr2.push(
|
|
494
586
|
new Token('tr_close', 'tr', -1),
|
|
495
|
-
|
|
587
|
+
createNewlineToken(Token)
|
|
496
588
|
);
|
|
497
589
|
|
|
498
590
|
// Clean up newlines before insertion
|
|
@@ -507,40 +599,6 @@ const setColgroup = (state, tableOpenIdx, opt, allowFallback) => {
|
|
|
507
599
|
|
|
508
600
|
tokens.splice(tr1, trCloseIdx - tr1 + 1, ...newTr1, ...newTr2);
|
|
509
601
|
|
|
510
|
-
// Handle tbody th conversion
|
|
511
|
-
let tbodyOpen = -1, tbodyClose = -1;
|
|
512
|
-
for (let i = theadClose + 1; i < tokens.length; i++) {
|
|
513
|
-
if (tokens[i].type === 'tbody_open') {
|
|
514
|
-
tbodyOpen = i;
|
|
515
|
-
} else if (tbodyOpen >= 0 && tokens[i].type === 'tbody_close') {
|
|
516
|
-
tbodyClose = i;
|
|
517
|
-
break;
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
if (tbodyOpen >= 0 && tbodyClose > tbodyOpen) {
|
|
522
|
-
let j = tbodyOpen + 1;
|
|
523
|
-
while (j < tbodyClose) {
|
|
524
|
-
if (tokens[j].type === 'tr_open') {
|
|
525
|
-
const tdIdx = j + 1;
|
|
526
|
-
if (tokens[tdIdx].type === 'td_open') {
|
|
527
|
-
const inline = tokens[tdIdx + 1];
|
|
528
|
-
if (inline && typeof inline.content === 'string' &&
|
|
529
|
-
isStrongWrappedInline(inline, allowFallback)) {
|
|
530
|
-
tokens[tdIdx].type = 'th_open';
|
|
531
|
-
tokens[tdIdx].tag = 'th';
|
|
532
|
-
tokens[tdIdx].attrSet('scope', 'row');
|
|
533
|
-
removeStrongWrappers(inline, allowFallback);
|
|
534
|
-
if (tokens[tdIdx + 2].type === 'td_close') {
|
|
535
|
-
tokens[tdIdx + 2].type = 'th_close';
|
|
536
|
-
tokens[tdIdx + 2].tag = 'th';
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
j++;
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
602
|
return;
|
|
545
603
|
}
|
|
546
604
|
|
|
@@ -549,116 +607,169 @@ const setColgroup = (state, tableOpenIdx, opt, allowFallback) => {
|
|
|
549
607
|
// Calculate group names and colspan for multi-row case
|
|
550
608
|
const groupData = {
|
|
551
609
|
spans: [],
|
|
552
|
-
rawNames: []
|
|
610
|
+
rawNames: [],
|
|
611
|
+
headerCount: 0
|
|
553
612
|
};
|
|
554
|
-
const groupMatchReg =
|
|
613
|
+
const groupMatchReg = regexes.multiHeaderGroup;
|
|
614
|
+
const groupStripReg = regexes.multiHeaderStrip;
|
|
555
615
|
|
|
616
|
+
const firstRowCells = [];
|
|
617
|
+
let firstRowClose = -1;
|
|
556
618
|
let thIdx = tr1 + 1;
|
|
557
|
-
while (thIdx < tokens.length
|
|
619
|
+
while (thIdx < tokens.length) {
|
|
558
620
|
if (tokens[thIdx].type === 'th_open') {
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
621
|
+
firstRowCells.push(thIdx);
|
|
622
|
+
} else if (tokens[thIdx].type === 'tr_close') {
|
|
623
|
+
firstRowClose = thIdx;
|
|
624
|
+
break;
|
|
625
|
+
}
|
|
626
|
+
thIdx++;
|
|
627
|
+
}
|
|
628
|
+
if (firstRowClose < 0 || firstRowCells.length === 0) return;
|
|
629
|
+
|
|
630
|
+
const secondRowCells = [];
|
|
631
|
+
let secondRowClose = -1;
|
|
632
|
+
thIdx = tr2 + 1;
|
|
633
|
+
while (thIdx < tokens.length) {
|
|
634
|
+
if (tokens[thIdx].type === 'th_open') {
|
|
635
|
+
secondRowCells.push(thIdx);
|
|
636
|
+
} else if (tokens[thIdx].type === 'tr_close') {
|
|
637
|
+
secondRowClose = thIdx;
|
|
638
|
+
break;
|
|
639
|
+
}
|
|
640
|
+
thIdx++;
|
|
641
|
+
}
|
|
642
|
+
if (secondRowClose < 0 || secondRowCells.length === 0) return;
|
|
643
|
+
|
|
644
|
+
for (let i = 0; i < firstRowCells.length; i++) {
|
|
645
|
+
const inline = tokens[firstRowCells[i] + 1];
|
|
646
|
+
const content = inline && typeof inline.content === 'string' ? inline.content : '';
|
|
647
|
+
let match = null;
|
|
648
|
+
if (opt.colgroupWithNoAsterisk) {
|
|
649
|
+
if (content.indexOf(':') !== -1 || content.indexOf(':') !== -1) {
|
|
564
650
|
match = content.match(groupMatchReg);
|
|
565
651
|
}
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
groupData.spans.push(1);
|
|
576
|
-
}
|
|
652
|
+
} else if (hasLeadingStrongMarker(inline, allowFallback)) {
|
|
653
|
+
match = content.match(groupMatchReg);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
if (match) {
|
|
657
|
+
const group = match[1].trim();
|
|
658
|
+
const lastGroup = groupData.rawNames[groupData.rawNames.length - 1];
|
|
659
|
+
if (groupData.rawNames.length > 0 && lastGroup === group) {
|
|
660
|
+
groupData.spans[groupData.spans.length - 1]++;
|
|
577
661
|
} else {
|
|
578
|
-
groupData.rawNames.push(
|
|
662
|
+
groupData.rawNames.push(group);
|
|
579
663
|
groupData.spans.push(1);
|
|
580
664
|
}
|
|
665
|
+
groupData.headerCount++;
|
|
666
|
+
} else {
|
|
667
|
+
groupData.rawNames.push(null);
|
|
668
|
+
groupData.spans.push(1);
|
|
581
669
|
}
|
|
582
|
-
thIdx++;
|
|
583
670
|
}
|
|
584
671
|
|
|
585
|
-
|
|
586
|
-
const groupStripReg = /^\*\*[^*:]+:\*\*\s*(.*)$/;
|
|
672
|
+
if (groupData.headerCount < 2) return;
|
|
587
673
|
|
|
588
|
-
// Generate colgroup if needed
|
|
589
674
|
const hasSpan = groupData.spans.some(span => span > 1);
|
|
590
|
-
|
|
591
|
-
|
|
675
|
+
|
|
676
|
+
// Add colspan/rowspan to thead and strip group prefixes in the second row.
|
|
677
|
+
const firstRowRemove = [];
|
|
678
|
+
const secondRowRemove = [];
|
|
679
|
+
let firstPtr = 0;
|
|
680
|
+
let secondPtr = 0;
|
|
681
|
+
for (let groupIdx = 0; groupIdx < groupData.spans.length; groupIdx++) {
|
|
682
|
+
const span = groupData.spans[groupIdx];
|
|
683
|
+
const groupName = groupData.rawNames[groupIdx];
|
|
684
|
+
const firstOpen = firstRowCells[firstPtr];
|
|
685
|
+
if (typeof firstOpen !== 'number' || !tokens[firstOpen] || tokens[firstOpen].type !== 'th_open') {
|
|
686
|
+
break;
|
|
687
|
+
}
|
|
688
|
+
const firstInline = tokens[firstOpen + 1];
|
|
689
|
+
|
|
690
|
+
if (groupName === null) {
|
|
691
|
+
tokens[firstOpen].attrSet('rowspan', '2');
|
|
692
|
+
tokens[firstOpen].attrSet('scope', 'col');
|
|
693
|
+
removeStrongWrappers(firstInline, allowFallback);
|
|
694
|
+
const secondOpen = secondRowCells[secondPtr];
|
|
695
|
+
if (typeof secondOpen === 'number') {
|
|
696
|
+
secondRowRemove.push(secondOpen);
|
|
697
|
+
secondPtr += 1;
|
|
698
|
+
}
|
|
699
|
+
firstPtr += 1;
|
|
700
|
+
continue;
|
|
701
|
+
}
|
|
592
702
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
703
|
+
if (span > 1) {
|
|
704
|
+
tokens[firstOpen].attrSet('colspan', span.toString());
|
|
705
|
+
}
|
|
706
|
+
tokens[firstOpen].attrSet('scope', 'col');
|
|
707
|
+
if (firstInline) {
|
|
708
|
+
setInlineText(firstInline, Token, groupName);
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
for (let i = 1; i < span; i++) {
|
|
712
|
+
const extraFirst = firstRowCells[firstPtr + i];
|
|
713
|
+
if (typeof extraFirst === 'number') {
|
|
714
|
+
firstRowRemove.push(extraFirst);
|
|
597
715
|
}
|
|
598
|
-
insertTokens.push(colOpen, new Token('col_close', 'col', -1));
|
|
599
716
|
}
|
|
600
717
|
|
|
601
|
-
|
|
602
|
-
|
|
718
|
+
for (let i = 0; i < span; i++) {
|
|
719
|
+
const secondOpen = secondRowCells[secondPtr + i];
|
|
720
|
+
if (typeof secondOpen !== 'number' || !tokens[secondOpen] || tokens[secondOpen].type !== 'th_open') {
|
|
721
|
+
continue;
|
|
722
|
+
}
|
|
723
|
+
tokens[secondOpen].attrSet('scope', 'col');
|
|
724
|
+
const secondInline = tokens[secondOpen + 1];
|
|
725
|
+
if (!secondInline || typeof secondInline.content !== 'string') continue;
|
|
726
|
+
const secondContent = secondInline.content;
|
|
727
|
+
let secondMatch = null;
|
|
728
|
+
if (opt.colgroupWithNoAsterisk) {
|
|
729
|
+
if (secondContent.indexOf(':') !== -1 || secondContent.indexOf(':') !== -1) {
|
|
730
|
+
secondMatch = secondContent.match(groupStripReg);
|
|
731
|
+
}
|
|
732
|
+
} else if (hasLeadingStrongMarker(secondInline, allowFallback)) {
|
|
733
|
+
secondMatch = secondContent.match(groupStripReg);
|
|
734
|
+
}
|
|
735
|
+
if (secondMatch) {
|
|
736
|
+
setInlineText(secondInline, Token, secondMatch[1]);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
secondPtr += span;
|
|
741
|
+
firstPtr += span;
|
|
603
742
|
}
|
|
604
743
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
}
|
|
623
|
-
t2++;
|
|
624
|
-
}
|
|
625
|
-
groupIdx++;
|
|
626
|
-
} else {
|
|
627
|
-
// Group cell
|
|
628
|
-
if (groupData.spans[groupIdx] > 1) {
|
|
629
|
-
tokens[th1].attrSet('colspan', groupData.spans[groupIdx].toString());
|
|
630
|
-
}
|
|
631
|
-
tokens[th1].attrSet('scope', 'col');
|
|
632
|
-
tokens[th1 + 1].content = groupNames[groupIdx];
|
|
633
|
-
|
|
634
|
-
// Process corresponding ths in second row
|
|
635
|
-
let count = 0, t2 = th2;
|
|
636
|
-
while (t2 < tokens.length && tokens[t2].type !== 'tr_close' && count < groupData.spans[groupIdx]) {
|
|
637
|
-
if (tokens[t2].type === 'th_open') {
|
|
638
|
-
tokens[t2].attrSet('scope', 'col');
|
|
639
|
-
// Remove group name part from content
|
|
640
|
-
const t2Inline = tokens[t2 + 1];
|
|
641
|
-
const t2content = t2Inline.content;
|
|
642
|
-
let t2match = null;
|
|
643
|
-
if (hasLeadingStrongMarker(t2Inline, allowFallback)) {
|
|
644
|
-
t2match = t2content.match(groupStripReg);
|
|
645
|
-
}
|
|
646
|
-
if (t2match) {
|
|
647
|
-
tokens[t2 + 1].content = t2match[1];
|
|
648
|
-
}
|
|
649
|
-
count++;
|
|
650
|
-
}
|
|
651
|
-
t2++;
|
|
652
|
-
}
|
|
653
|
-
th2 = t2;
|
|
654
|
-
groupIdx++;
|
|
744
|
+
if (firstRowRemove.length || secondRowRemove.length) {
|
|
745
|
+
const removeTargets = firstRowRemove.concat(secondRowRemove).sort((a, b) => b - a);
|
|
746
|
+
for (let i = 0; i < removeTargets.length; i++) {
|
|
747
|
+
removeHeaderCellAt(tokens, removeTargets[i]);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// Insert colgroup after header edits so index calculations above remain stable.
|
|
752
|
+
if (hasSpan) {
|
|
753
|
+
const insertTokens = [
|
|
754
|
+
new Token('colgroup_open', 'colgroup', 1),
|
|
755
|
+
createNewlineToken(Token)
|
|
756
|
+
];
|
|
757
|
+
for (let i = 0; i < groupData.spans.length; i++) {
|
|
758
|
+
const colOpen = new Token('col_open', 'col', 1);
|
|
759
|
+
if (groupData.spans[i] > 1) {
|
|
760
|
+
colOpen.attrPush(['span', groupData.spans[i]]);
|
|
655
761
|
}
|
|
762
|
+
insertTokens.push(colOpen, createNewlineToken(Token));
|
|
656
763
|
}
|
|
657
|
-
|
|
764
|
+
insertTokens.push(
|
|
765
|
+
new Token('colgroup_close', 'colgroup', -1),
|
|
766
|
+
createNewlineToken(Token)
|
|
767
|
+
);
|
|
768
|
+
tokens.splice(tableOpenIdx + 1, 0, ...insertTokens);
|
|
658
769
|
}
|
|
659
770
|
};
|
|
660
771
|
|
|
661
|
-
const tableEx = (state, opt) => {
|
|
772
|
+
const tableEx = (state, opt, regexes) => {
|
|
662
773
|
const tokens = state.tokens;
|
|
663
774
|
let tokenLength = tokens.length;
|
|
664
775
|
const allowStrongFallback = !hasInlineRule(state.md, 'strong_ja');
|
|
@@ -670,16 +781,18 @@ const tableEx = (state, opt) => {
|
|
|
670
781
|
continue;
|
|
671
782
|
}
|
|
672
783
|
|
|
673
|
-
|
|
784
|
+
let tableOpenIdx = idx;
|
|
674
785
|
|
|
675
786
|
if (opt.wrapper) {
|
|
676
787
|
const wrapperStartToken = new state.Token('div_open', 'div', 1);
|
|
677
788
|
wrapperStartToken.attrPush(['class', 'table-wrapper']);
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
789
|
+
if (Array.isArray(tokens[idx].map)) {
|
|
790
|
+
wrapperStartToken.map = tokens[idx].map.slice();
|
|
791
|
+
}
|
|
792
|
+
tokens.splice(idx, 0, wrapperStartToken, createNewlineToken(state.Token));
|
|
681
793
|
tokenLength += 2;
|
|
682
794
|
idx += 2;
|
|
795
|
+
tableOpenIdx = idx;
|
|
683
796
|
}
|
|
684
797
|
|
|
685
798
|
let theadVar = {
|
|
@@ -691,27 +804,50 @@ const tableEx = (state, opt) => {
|
|
|
691
804
|
if (hasThead) {
|
|
692
805
|
theadVar = addTheadThScope(state, theadVar, allowStrongFallback);
|
|
693
806
|
idx = theadVar.i + 1;
|
|
807
|
+
const hadMatrixAnchor = Number.isInteger(theadVar.firstThPos) && theadVar.firstThPos >= 0;
|
|
694
808
|
if (opt.colgroup) {
|
|
695
809
|
const beforeLength = tokens.length;
|
|
696
|
-
setColgroup(state, tableOpenIdx, opt, allowStrongFallback);
|
|
810
|
+
setColgroup(state, tableOpenIdx, opt, allowStrongFallback, regexes);
|
|
697
811
|
tokenLength += tokens.length - beforeLength;
|
|
698
812
|
}
|
|
813
|
+
if (opt.matrix) {
|
|
814
|
+
let firstThPos = findFirstHeaderThPos(tokens, tableOpenIdx, allowStrongFallback);
|
|
815
|
+
if (firstThPos < 0 && hadMatrixAnchor) {
|
|
816
|
+
firstThPos = findFirstHeaderCellPos(tokens, tableOpenIdx);
|
|
817
|
+
}
|
|
818
|
+
theadVar.firstThPos = firstThPos;
|
|
819
|
+
}
|
|
699
820
|
}
|
|
700
821
|
|
|
701
822
|
if (opt.matrix) {
|
|
823
|
+
let tbodyOpenPos = -1;
|
|
824
|
+
for (let i = tableOpenIdx + 1; i < tokenLength; i++) {
|
|
825
|
+
const type = tokens[i].type;
|
|
826
|
+
if (type === 'tbody_open') {
|
|
827
|
+
tbodyOpenPos = i;
|
|
828
|
+
break;
|
|
829
|
+
}
|
|
830
|
+
if (type === 'table_close') {
|
|
831
|
+
break;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
|
|
702
835
|
let tbodyVar = {
|
|
703
|
-
i:
|
|
836
|
+
i: tbodyOpenPos,
|
|
704
837
|
isAllFirstTh: false,
|
|
705
838
|
tbodyFirstThPoses: [],
|
|
706
839
|
};
|
|
707
840
|
|
|
708
|
-
const hasTbody =
|
|
841
|
+
const hasTbody = tbodyVar.i >= 0;
|
|
709
842
|
if (hasTbody) {
|
|
710
843
|
tbodyVar = checkTbody(state, tbodyVar, allowStrongFallback);
|
|
711
844
|
idx = tbodyVar.i + 1;
|
|
712
845
|
}
|
|
713
846
|
|
|
714
|
-
|
|
847
|
+
const hasMatrixAnchor = hasThead
|
|
848
|
+
? Number.isInteger(theadVar.firstThPos) && theadVar.firstThPos >= 0
|
|
849
|
+
: true;
|
|
850
|
+
if (hasMatrixAnchor && tbodyVar.isAllFirstTh) {
|
|
715
851
|
const firstTdPoses = [...tbodyVar.tbodyFirstThPoses];
|
|
716
852
|
if (hasThead) {
|
|
717
853
|
firstTdPoses.unshift(theadVar.firstThPos);
|
|
@@ -725,9 +861,7 @@ const tableEx = (state, opt) => {
|
|
|
725
861
|
if (tokens[idx].type === 'table_close') {
|
|
726
862
|
if (opt.wrapper) {
|
|
727
863
|
const wrapperEndToken = new state.Token('div_close', 'div', -1);
|
|
728
|
-
|
|
729
|
-
linebreakToken.content = '\n';
|
|
730
|
-
tokens.splice(idx + 1, 0, wrapperEndToken, linebreakToken);
|
|
864
|
+
tokens.splice(idx + 1, 0, wrapperEndToken, createNewlineToken(state.Token));
|
|
731
865
|
tokenLength += 2;
|
|
732
866
|
idx += 2;
|
|
733
867
|
}
|
|
@@ -740,17 +874,17 @@ const tableEx = (state, opt) => {
|
|
|
740
874
|
};
|
|
741
875
|
|
|
742
876
|
const mditTableEx = (md, option) => {
|
|
743
|
-
|
|
877
|
+
const baseOpt = {
|
|
744
878
|
matrix: true,
|
|
745
879
|
wrapper: false,
|
|
746
880
|
colgroup: false,
|
|
747
881
|
colgroupWithNoAsterisk: false
|
|
748
882
|
};
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
883
|
+
const userOpt = (option && typeof option === 'object') ? option : {};
|
|
884
|
+
const opt = Object.assign({}, baseOpt, userOpt);
|
|
885
|
+
const regexes = createColgroupRegexes(opt.colgroupWithNoAsterisk);
|
|
752
886
|
md.core.ruler.after('replacements', 'table-ex', (state) => {
|
|
753
|
-
tableEx(state, opt);
|
|
887
|
+
tableEx(state, opt, regexes);
|
|
754
888
|
});
|
|
755
889
|
}
|
|
756
890
|
export default mditTableEx
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peaceroad/markdown-it-table-ex",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "A markdown-it plugin. Add matrix and wrapper notation for table processing.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"author": "peaceroad <peaceroad@gmail.com>",
|
|
17
17
|
"license": "MIT",
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@peaceroad/markdown-it-figure-with-p-caption": "^0.
|
|
20
|
-
"@peaceroad/markdown-it-strong-ja": "^0.
|
|
19
|
+
"@peaceroad/markdown-it-figure-with-p-caption": "^0.16.0",
|
|
20
|
+
"@peaceroad/markdown-it-strong-ja": "^0.7.2",
|
|
21
21
|
"markdown-it": "^14.1.0",
|
|
22
22
|
"markdown-it-multimd-table": "^4.2.3"
|
|
23
23
|
}
|