mirror of
https://github.com/liberatedsystems/openCom-Companion.git
synced 2025-02-23 09:49:51 +01:00
83 lines
3.1 KiB
Python
83 lines
3.1 KiB
Python
|
from typing import Dict, Any, List
|
||
|
|
||
|
def merge_ordered_lists(md):
|
||
|
"""
|
||
|
A plugin to merge consecutive "top-level" ordered lists into one,
|
||
|
and also attach any intervening code blocks or blank lines to the
|
||
|
last list item so that the final BBCode appears as a single list
|
||
|
with multiple steps.
|
||
|
|
||
|
This relies on a few assumptions:
|
||
|
1) The only tokens between two ordered lists that should be merged
|
||
|
are code blocks or blank lines (not normal paragraphs).
|
||
|
2) We want any code block(s) right after a list item to appear in
|
||
|
that same bullet item.
|
||
|
"""
|
||
|
|
||
|
def rewrite_tokens(md, state):
|
||
|
tokens = state.tokens
|
||
|
merged = []
|
||
|
i = 0
|
||
|
|
||
|
while i < len(tokens):
|
||
|
token = tokens[i]
|
||
|
|
||
|
# Check if this token is a top-level ordered list
|
||
|
if (
|
||
|
token["type"] == "list"
|
||
|
and token.get("attrs", {}).get("ordered", False)
|
||
|
and token.get("attrs", {}).get("depth", 0) == 0
|
||
|
):
|
||
|
# Start new merged list
|
||
|
current_depth = token["attrs"]["depth"]
|
||
|
list_items = list(token["children"]) # bullet items in the first list
|
||
|
i += 1
|
||
|
|
||
|
# Continue until we run into something that's not:
|
||
|
# another top-level ordered list,
|
||
|
# or code blocks / blank lines (which we'll attach to the last bullet).
|
||
|
while i < len(tokens):
|
||
|
nxt = tokens[i]
|
||
|
|
||
|
# If there's another ordered list at the same depth, merge its bullet items
|
||
|
if (
|
||
|
nxt["type"] == "list"
|
||
|
and nxt.get("attrs", {}).get("ordered", False)
|
||
|
and nxt.get("attrs", {}).get("depth", 0) == current_depth
|
||
|
):
|
||
|
list_items.extend(nxt["children"])
|
||
|
i += 1
|
||
|
|
||
|
# If there's a code block or blank line, attach it to the *last* bullet item.
|
||
|
elif nxt["type"] in ["block_code", "blank_line"]:
|
||
|
if list_items: # attach to last bullet item, if any
|
||
|
list_items[-1]["children"].append(nxt)
|
||
|
i += 1
|
||
|
|
||
|
else:
|
||
|
# Not a same-depth list or code block—stop merging
|
||
|
break
|
||
|
|
||
|
# Create single merged list token
|
||
|
merged.append(
|
||
|
{
|
||
|
"type": "list",
|
||
|
"children": list_items,
|
||
|
"attrs": {
|
||
|
"ordered": True,
|
||
|
"depth": current_depth,
|
||
|
},
|
||
|
}
|
||
|
)
|
||
|
|
||
|
else:
|
||
|
# If not a top-level ordered list, just keep it as-is
|
||
|
merged.append(token)
|
||
|
i += 1
|
||
|
|
||
|
# Replace the old tokens with the merged version
|
||
|
state.tokens = merged
|
||
|
|
||
|
# Attach to before_render_hooks so we can manipulate tokens before rendering
|
||
|
md.before_render_hooks.append(rewrite_tokens)
|
||
|
return md
|