Fix indentation issues in Markdown content. This function corrects inconsistent indentation in nested Markdown structures, particularly for collapse blocks. It uses a bidirectional scanning approach to determine proper indentation levels. see also: - <https://oi-wiki.org/i
(md_content: str, **kwargs)
| 4 | |
| 5 | @step |
| 6 | def fix_details(md_content: str, **kwargs): |
| 7 | """ |
| 8 | Fix indentation issues in Markdown content. |
| 9 | |
| 10 | This function corrects inconsistent indentation in nested Markdown structures, |
| 11 | particularly for collapse blocks. It uses a bidirectional scanning approach to |
| 12 | determine proper indentation levels. |
| 13 | |
| 14 | see also: |
| 15 | - <https://oi-wiki.org/intro/format/#LINT-6> |
| 16 | - <https://oi-wiki.org/intro/format/#MDFM-6> |
| 17 | |
| 18 | Args: |
| 19 | md_content: The Markdown content to process |
| 20 | **kwargs: Additional arguments including 'line_origins' for tracking |
| 21 | |
| 22 | Returns: |
| 23 | str: The processed Markdown content with corrected indentation |
| 24 | """ |
| 25 | line_origins: list[int] = kwargs.get('line_origins') # type: ignore |
| 26 | lines: list[str] = md_content.splitlines() |
| 27 | |
| 28 | size = len(lines) |
| 29 | log(f"Processing {size} lines for indentation fixes") |
| 30 | |
| 31 | # Calculate maximum possible indent (used as sentinel value) |
| 32 | MAX_INDENT = max(len(line) for line in lines)+1 |
| 33 | log(f"Maximum indent calculated: {MAX_INDENT}") |
| 34 | |
| 35 | # Identify non-blank lines (lines with actual content) |
| 36 | non_blank = [i != -1 and len(line.strip()) > 0 |
| 37 | for i, line in zip(line_origins, lines)] |
| 38 | non_blank_count = sum(non_blank) |
| 39 | log(f"Found {non_blank_count} non-blank lines out of {size} total lines") |
| 40 | |
| 41 | # Calculate current indentation levels |
| 42 | pre_indents = [index_lfirst_neq(line, ' ') if line.strip() else 0 |
| 43 | for line in lines] |
| 44 | # Show first 5 |
| 45 | log(f"Calculated initial indentation levels: {pre_indents[:5]}...") |
| 46 | |
| 47 | # Initialize new indentation levels |
| 48 | now_indents = [i if flag else MAX_INDENT for i, |
| 49 | flag in zip(pre_indents, non_blank)] |
| 50 | |
| 51 | # Forward pass: propagate indentation from content lines to blank lines |
| 52 | log("Starting forward pass for indentation propagation") |
| 53 | past_indent = MAX_INDENT |
| 54 | changes_forward = 0 |
| 55 | |
| 56 | for index in filter(lambda i: line_origins[i] != -1, range(size)): |
| 57 | if non_blank[index]: |
| 58 | past_indent = now_indents[index] |
| 59 | else: |
| 60 | old_indent = now_indents[index] |
| 61 | now_indents[index] = min(now_indents[index], past_indent) |
| 62 | if old_indent != now_indents[index]: |
| 63 | changes_forward += 1 |