1+ from typing import Dict , Any , List
2+
3+ def merge_ordered_lists (md ):
4+ """
5+ A plugin to merge consecutive "top-level" ordered lists into one,
6+ and also attach any intervening code blocks or blank lines to the
7+ last list item so that the final BBCode appears as a single list
8+ with multiple steps.
9+
10+ This relies on a few assumptions:
11+ 1) The only tokens between two ordered lists that should be merged
12+ are code blocks or blank lines (not normal paragraphs).
13+ 2) We want any code block(s) right after a list item to appear in
14+ that same bullet item.
15+ """
16+
17+ def rewrite_tokens (md , state ):
18+ tokens = state .tokens
19+ merged = []
20+ i = 0
21+
22+ while i < len (tokens ):
23+ token = tokens [i ]
24+
25+ # Check if this token is a top-level ordered list
26+ if (
27+ token ["type" ] == "list"
28+ and token .get ("attrs" , {}).get ("ordered" , False )
29+ and token .get ("attrs" , {}).get ("depth" , 0 ) == 0
30+ ):
31+ # Start new merged list
32+ current_depth = token ["attrs" ]["depth" ]
33+ list_items = list (token ["children" ]) # bullet items in the first list
34+ i += 1
35+
36+ # Continue until we run into something that's not:
37+ # another top-level ordered list,
38+ # or code blocks / blank lines (which we'll attach to the last bullet).
39+ while i < len (tokens ):
40+ nxt = tokens [i ]
41+
42+ # If there's another ordered list at the same depth, merge its bullet items
43+ if (
44+ nxt ["type" ] == "list"
45+ and nxt .get ("attrs" , {}).get ("ordered" , False )
46+ and nxt .get ("attrs" , {}).get ("depth" , 0 ) == current_depth
47+ ):
48+ list_items .extend (nxt ["children" ])
49+ i += 1
50+
51+ # If there's a code block or blank line, attach it to the *last* bullet item.
52+ elif nxt ["type" ] in ["block_code" , "blank_line" ]:
53+ if list_items : # attach to last bullet item, if any
54+ list_items [- 1 ]["children" ].append (nxt )
55+ i += 1
56+
57+ else :
58+ # Not a same-depth list or code block—stop merging
59+ break
60+
61+ # Create single merged list token
62+ merged .append (
63+ {
64+ "type" : "list" ,
65+ "children" : list_items ,
66+ "attrs" : {
67+ "ordered" : True ,
68+ "depth" : current_depth ,
69+ },
70+ }
71+ )
72+
73+ else :
74+ # If not a top-level ordered list, just keep it as-is
75+ merged .append (token )
76+ i += 1
77+
78+ # Replace the old tokens with the merged version
79+ state .tokens = merged
80+
81+ # Attach to before_render_hooks so we can manipulate tokens before rendering
82+ md .before_render_hooks .append (rewrite_tokens )
83+ return md
0 commit comments