@peaceroad/markdown-it-numbering-ul-regarded-as-ol 0.2.0 → 0.2.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 +336 -335
- package/debug/dump_listinfos.mjs +65 -0
- package/debug/dump_tokens.mjs +72 -0
- package/index.js +5 -0
- package/package.json +5 -2
- package/src/phase0-description-list.js +654 -654
- package/src/phase1-analyze.js +90 -7
- package/src/phase2-convert.js +1037 -738
- package/src/phase3-attributes.js +260 -244
- package/src/phase5-spans.js +1 -1
- package/src/phase6-attrs-migration.js +1 -1
- package/src/preprocess-literal-lists.js +776 -0
- package/src/types-utility.js +995 -991
package/src/phase1-analyze.js
CHANGED
|
@@ -154,7 +154,10 @@ function analyzeList(tokens, startIndex, opt) {
|
|
|
154
154
|
const level = listToken.level || 0
|
|
155
155
|
const originalType = listToken.type
|
|
156
156
|
const items = analyzeListItems(tokens, startIndex, endIndex, opt)
|
|
157
|
-
const isLoose = detectLooseList(tokens, startIndex, endIndex)
|
|
157
|
+
const isLoose = detectLooseList(tokens, startIndex, endIndex, items)
|
|
158
|
+
if (!isLoose) {
|
|
159
|
+
hideFirstParagraphsForTightList(tokens, items, level)
|
|
160
|
+
}
|
|
158
161
|
|
|
159
162
|
// Extract marker info (for both bullet_list and ordered_list)
|
|
160
163
|
const markerInfo = extractMarkerInfo(tokens, startIndex, endIndex, opt)
|
|
@@ -229,9 +232,11 @@ function analyzeListItem(tokens, startIndex, endIndex, opt) {
|
|
|
229
232
|
// When child list starts, check if blank line exists right after first paragraph
|
|
230
233
|
if (foundParagraph && firstParagraphIndex !== -1) {
|
|
231
234
|
const paragraphToken = tokens[firstParagraphIndex]
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
+
const paragraphEndLine = paragraphToken.map ? paragraphToken.map[1] : undefined
|
|
236
|
+
const nestedListStartLine = token.map
|
|
237
|
+
? token.map[0]
|
|
238
|
+
: (typeof token._literalStartLine === 'number' ? token._literalStartLine : undefined)
|
|
239
|
+
if (typeof paragraphEndLine === 'number' && typeof nestedListStartLine === 'number') {
|
|
235
240
|
// Check if blank line exists between paragraph end and child list start
|
|
236
241
|
if (nestedListStartLine > paragraphEndLine) {
|
|
237
242
|
firstParagraphIsLoose = true
|
|
@@ -297,6 +302,7 @@ function extractMarkerInfo(tokens, startIndex, endIndex, opt) {
|
|
|
297
302
|
|
|
298
303
|
markers.push({
|
|
299
304
|
number: itemNumber,
|
|
305
|
+
originalNumber: itemNumber,
|
|
300
306
|
prefix: '',
|
|
301
307
|
suffix: markup,
|
|
302
308
|
type: 'decimal' // Default (can be extended to detect from markup)
|
|
@@ -329,6 +335,7 @@ function extractMarkerInfo(tokens, startIndex, endIndex, opt) {
|
|
|
329
335
|
// Use sequential numbers when same marker continues
|
|
330
336
|
// (e.g., "イ. イ. イ." → interpreted as "イ、ロ、ハ")
|
|
331
337
|
const adjustedMarkerInfo = { ...markerInfo }
|
|
338
|
+
adjustedMarkerInfo.originalNumber = markerInfo.number
|
|
332
339
|
|
|
333
340
|
// Assign sequential numbers based on first marker's number
|
|
334
341
|
if (markers.length === 0) {
|
|
@@ -361,12 +368,22 @@ function extractMarkerInfo(tokens, startIndex, endIndex, opt) {
|
|
|
361
368
|
|
|
362
369
|
const firstType = markers[0].type
|
|
363
370
|
const allSameType = markers.every(m => m.type === firstType)
|
|
371
|
+
const literalNumbers = markers.map(m => (typeof m.originalNumber === 'number' ? m.originalNumber : undefined))
|
|
372
|
+
const hasLiteralNumbers = literalNumbers.length === markers.length && literalNumbers.every(n => typeof n === 'number')
|
|
373
|
+
let allNumbersIdentical = false
|
|
374
|
+
if (hasLiteralNumbers) {
|
|
375
|
+
const firstLiteral = literalNumbers[0]
|
|
376
|
+
if (literalNumbers.every(n => n === firstLiteral) && firstLiteral === 1) {
|
|
377
|
+
allNumbersIdentical = true
|
|
378
|
+
}
|
|
379
|
+
}
|
|
364
380
|
|
|
365
381
|
return {
|
|
366
382
|
markers,
|
|
367
383
|
type: firstType,
|
|
368
384
|
isConsistent: allSameType,
|
|
369
|
-
count: markers.length
|
|
385
|
+
count: markers.length,
|
|
386
|
+
allNumbersIdentical
|
|
370
387
|
}
|
|
371
388
|
}
|
|
372
389
|
|
|
@@ -397,17 +414,83 @@ function shouldConvertToOrdered(originalType, markerInfo, opt) {
|
|
|
397
414
|
* In markdown-it, lists separated by blank lines have paragraphs in each list_item
|
|
398
415
|
* For tight lists, paragraph_open.hidden === true
|
|
399
416
|
*/
|
|
400
|
-
function detectLooseList(tokens, startIndex, endIndex) {
|
|
417
|
+
function detectLooseList(tokens, startIndex, endIndex, items = null) {
|
|
418
|
+
const listLevel = tokens[startIndex]?.level || 0
|
|
419
|
+
const paragraphLevel = listLevel + 2
|
|
401
420
|
for (let i = startIndex + 1; i < endIndex; i++) {
|
|
402
421
|
const token = tokens[i]
|
|
403
422
|
// Loose list if paragraph_open exists and is not hidden
|
|
404
|
-
if (token.type === 'paragraph_open' && !token.hidden) {
|
|
423
|
+
if (token.type === 'paragraph_open' && token.level === paragraphLevel && !token.hidden) {
|
|
424
|
+
if (items && items.length === 1 && isTightSingleItem(tokens, items[0])) {
|
|
425
|
+
continue
|
|
426
|
+
}
|
|
405
427
|
return true
|
|
406
428
|
}
|
|
407
429
|
}
|
|
408
430
|
return false
|
|
409
431
|
}
|
|
410
432
|
|
|
433
|
+
function isTightSingleItem(tokens, item) {
|
|
434
|
+
if (!item || item.firstParagraphIsLoose) {
|
|
435
|
+
return false
|
|
436
|
+
}
|
|
437
|
+
const itemOpenToken = tokens[item.startIndex]
|
|
438
|
+
const childLevel = (itemOpenToken.level || 0) + 1
|
|
439
|
+
let paragraphCount = 0
|
|
440
|
+
for (let i = item.startIndex + 1; i < item.endIndex; i++) {
|
|
441
|
+
const token = tokens[i]
|
|
442
|
+
if (token.level !== childLevel) {
|
|
443
|
+
continue
|
|
444
|
+
}
|
|
445
|
+
if (token.type === 'paragraph_open') {
|
|
446
|
+
paragraphCount++
|
|
447
|
+
if (paragraphCount > 1) {
|
|
448
|
+
return false
|
|
449
|
+
}
|
|
450
|
+
} else if (token.type === 'ordered_list_open' || token.type === 'bullet_list_open') {
|
|
451
|
+
continue
|
|
452
|
+
} else if (token.type.endsWith('_open') || token.type === 'html_block' || token.type === 'code_block' || token.type === 'fence') {
|
|
453
|
+
return false
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
return true
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function hideFirstParagraphsForTightList(tokens, items, level) {
|
|
460
|
+
if (!Array.isArray(items) || level !== 0) {
|
|
461
|
+
return
|
|
462
|
+
}
|
|
463
|
+
for (const item of items) {
|
|
464
|
+
if (!item || item.firstParagraphIsLoose) {
|
|
465
|
+
continue
|
|
466
|
+
}
|
|
467
|
+
const itemToken = tokens[item.startIndex]
|
|
468
|
+
if (!itemToken) {
|
|
469
|
+
continue
|
|
470
|
+
}
|
|
471
|
+
const paragraphLevel = (itemToken.level || 0) + 1
|
|
472
|
+
for (let i = item.startIndex + 1; i < item.endIndex; i++) {
|
|
473
|
+
const token = tokens[i]
|
|
474
|
+
if (!token) {
|
|
475
|
+
continue
|
|
476
|
+
}
|
|
477
|
+
if (token.type === 'paragraph_open' && token.level === paragraphLevel) {
|
|
478
|
+
if (!token._literalTight) {
|
|
479
|
+
break
|
|
480
|
+
}
|
|
481
|
+
token.hidden = true
|
|
482
|
+
const closeIdx = findMatchingClose(tokens, i, 'paragraph_open', 'paragraph_close')
|
|
483
|
+
if (closeIdx !== -1) {
|
|
484
|
+
tokens[closeIdx].hidden = true
|
|
485
|
+
}
|
|
486
|
+
break
|
|
487
|
+
} else if (token.type === 'bullet_list_open' || token.type === 'ordered_list_open') {
|
|
488
|
+
break
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
411
494
|
/**
|
|
412
495
|
* Find list end position
|
|
413
496
|
*/
|