#!/usr/bin/env python3
"""为 SOP 模板正文表非主操作区行添加 sop-row-hidden,并重新生成 seed SQL。"""
from __future__ import annotations
import re
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
TEMPLATES_DIR = ROOT / "docs" / "sop-templates"
SQL_DIR = ROOT / "docs" / "sql"
SOP_CODES = [
"SOP-CC-001-E01-01",
"SOP-CC-002-E01-01",
"SOP-CC-003-E01-01",
"SOP-CC-006-E01-01",
"SOP-SC-003-E01-01",
"SOP-SC-004-E01-01",
"SOP-SC-005-E01-01",
"SOP-SC-006-E01-01",
"SOP-SC-007-E01-01",
"SOP-SC-008-E01-01",
"SOP-SC-009-E01-01",
"SOP-SC-010-E01-01",
"SOP-SC-011-E01-01",
"SOP-SC-012-E01-01",
"SOP-SC-013-E01-01",
"SOP-SC-014-E01-01",
]
SC014_NK_ROW_OLD = (
'
\n'
' '
"NK细胞 培养 | \n"
' '
)
SC014_NK_ROW_NEW = (
' |
\n'
' '
"NK细胞 培养 | \n"
' '
)
def _is_tr_open(html: str, pos: int) -> bool:
if not html.startswith(" |
", "/", "\n", "\t", "\r")
def _split_top_level_trs(html: str) -> list[str]:
rows: list[str] = []
i = 0
n = len(html)
while i < n:
start = html.find("
", pos):
depth -= 1
pos += 5
if depth == 0:
rows.append(html[start:pos])
i = pos
break
continue
pos += 1
else:
raise ValueError("unclosed
in sop-body-table tbody")
return rows
def _add_hidden_class(tr_html: str) -> str:
open_tag = tr_html.split(">", 1)[0] + ">"
if "sop-fill-row" in open_tag:
return tr_html
def _patch_tr_tag(match: re.Match[str]) -> str:
tag = match.group(0)
if 'class="' in tag:
return re.sub(
r'class="([^"]*)"',
lambda m: f'class="{m.group(1)} sop-row-hidden"',
tag,
count=1,
)
return tag.replace("
]*>", _patch_tr_tag, tr_html, count=1)
def _find_body_tbody_span(html: str) -> tuple[int, int] | None:
body_start = html.find('", body_start)
if tbody_open < 0:
return None
inner_start = tbody_open + len("")
table_depth = 1
tbody_depth = 1
pos = inner_start
n = len(html)
while pos < n:
if html.startswith("", pos):
table_depth -= 1
pos += 8
continue
if html.startswith("", pos):
tbody_depth += 1
pos += 7
continue
if html.startswith("", pos):
tbody_depth -= 1
pos += 8
if tbody_depth == 0:
return inner_start, pos - 8
continue
pos += 1
raise ValueError("无法定位 sop-body-table 的 tbody 结束位置")
def process_body_table(html: str) -> str:
span = _find_body_tbody_span(html)
if span is None:
return html
inner_start, inner_end = span
tbody_inner = html[inner_start:inner_end]
rows = _split_top_level_trs(tbody_inner)
processed = [_add_hidden_class(row) for row in rows]
return html[:inner_start] + "".join(processed) + html[inner_end:]
def process_template(html: str, code: str) -> str:
html = html.replace(
'