rbpu_datasheet/doc_builder/render_requirements.py

81 lines
2.6 KiB
Python
Raw Normal View History

2026-07-19 20:56:15 +08:00
"""YAML requirements renderer — for request_*.yaml style files."""
from html import escape
def render(filepath):
"""Render YAML requirements as grouped tables (F_/P_/S_ sections)."""
try:
import yaml
except ImportError:
return '<div class="warning">pyyaml not installed. Run: pip install pyyaml</div>'
with open(str(filepath), encoding='utf-8') as f:
data = yaml.safe_load(f)
if not isinstance(data, dict):
return f'<pre><code>{escape(str(data))}</code></pre>'
sections = {
'F_': ('功能需求', []),
'P_': ('性能需求', []),
'S_': ('规格需求', []),
}
other = []
for key, val in data.items():
if not isinstance(val, dict):
continue
name = val.get('name', key)
desc = val.get('description', '')
limit = val.get('limit', None)
limit_str = ''
if limit and isinstance(limit, dict):
parts = []
if 'min' in limit and limit['min'] is not None:
parts.append(f'>= {limit["min"]}')
if 'max' in limit and limit['max'] is not None:
parts.append(f'<= {limit["max"]}')
if 'value' in limit:
parts.append(str(limit['value']))
if 'unit' in limit:
parts.append(limit['unit'])
if 'count' in limit:
parts.append(f'x{limit["count"]}')
limit_str = ' '.join(parts)
entry = {'id': key, 'name': name, 'desc': desc, 'limit': limit_str}
placed = False
for prefix in sections:
if key.startswith(prefix):
sections[prefix][1].append(entry)
placed = True
break
if not placed:
other.append(entry)
html = []
for prefix, (label, items) in sections.items():
if not items:
continue
html.append(f'<h3>{label}{len(items)} 项)</h3>')
html.append(
'<table><thead><tr>'
'<th style="width:16%">ID</th>'
'<th style="width:16%">名称</th>'
'<th>描述</th>'
'<th style="width:20%">指标</th>'
'</tr></thead><tbody>'
)
for e in items:
html.append(
f'<tr>'
f'<td class="text-mono">{escape(e["id"])}</td>'
f'<td>{escape(e["name"])}</td>'
f'<td>{escape(e["desc"])}</td>'
f'<td>{escape(e["limit"])}</td>'
f'</tr>'
)
html.append('</tbody></table>')
return '\n'.join(html)