81 lines
2.6 KiB
Python
81 lines
2.6 KiB
Python
|
|
"""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)
|