#!/usr/bin/env python3 """为 web-admin 中缺少序号的 el-table 批量插入序号列。""" from __future__ import annotations import re import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] / "src" SKIP_FILES = { ROOT / "components/bx/base/BaseTable.vue", } def find_table_spans(text: str) -> list[tuple[int, int]]: spans: list[tuple[int, int]] = [] for m in re.finditer(r")", text): start = m.start() end_m = re.search(r"", text[start:]) if not end_m: continue spans.append((start, start + end_m.end())) return spans def extract_first_column(block: str) -> tuple[int, int, str] | None: table_open = re.search(r"]*>", block) if not table_open: return None pos = table_open.end() m = re.search(r"(\s*)]*?/>)", rest, re.DOTALL) if self_close: col_end = col_start + len(self_close.group(1)) return col_start, col_end, block[col_start:col_end] open_end = rest.find(">") if open_end == -1: return None close = rest.find("", open_end) if close == -1: return None col_end = col_start + close + len("") return col_start, col_end, block[col_start:col_end] def leading_indent(block: str, col_start: int) -> str: line_start = block.rfind("\n", 0, col_start) + 1 return re.match(r"[ \t]*", block[line_start:col_start]).group(0) def build_index_column(indent: str, paginated: bool) -> str: if paginated: return ( f"{indent} (pagination.page - 1) * pagination.pageSize + index + 1\"\n" f"{indent}/>" ) return ( f'{indent}' ) def should_use_pagination(block: str, file_text: str) -> bool: if "pagination.page" not in file_text: return False table_open = re.search(r"]*>", block) if not table_open: return False opening = table_open.group(0) if 'size="small"' in opening or "size='small'" in opening: return False if "sub-table" in opening: return False return True def insert_index_into_block(block: str, file_text: str) -> str | None: if 'type="index"' in block or "type='index'" in block: return None first = extract_first_column(block) if not first: return None col_start, col_end, first_col = first indent = leading_indent(block, col_start) paginated = should_use_pagination(block, file_text) index_col = build_index_column(indent, paginated) is_select = re.search(r'type="(selection|radio)"', first_col) is not None if is_select: insert_at = col_end new_block = block[:insert_at] + "\n" + index_col + block[insert_at:] else: line_start = block.rfind("\n", 0, col_start) + 1 new_block = block[:line_start] + index_col + "\n" + block[line_start:] return new_block def process_file(path: Path) -> bool: if path in SKIP_FILES: return False text = path.read_text(encoding="utf-8") if not re.search(r")", text): return False spans = find_table_spans(text) if not spans: return False changed = False offset = 0 for start, end in spans: start += offset end += offset block = text[start:end] new_block = insert_index_into_block(block, text) if not new_block: continue text = text[:start] + new_block + text[end:] offset += len(new_block) - len(block) changed = True if changed: path.write_text(text, encoding="utf-8") return changed def main() -> int: changed_files: list[str] = [] for path in sorted(ROOT.rglob("*.vue")): if process_file(path): changed_files.append(str(path.relative_to(ROOT.parents[0]))) print(f"Updated {len(changed_files)} files") for f in changed_files: print(f" {f}") return 0 if __name__ == "__main__": sys.exit(main())