"""Render the owned offline Markdown runbook without external dependencies/assets."""
from pathlib import Path
import html,re
r=Path(__file__).resolve().parents[1];src=r/'private/dm-package/INSTALL.md';lines=src.read_text().splitlines();parts=[];toc=[];i=0;step=0
def inline(s):
 s=html.escape(s)
 s=re.sub(r'\[([^\]]+)\]\((https?://[^)]+)\)',r'<a href="\2" target="_blank" rel="noopener">\1</a>',s)
 s=re.sub(r'`([^`]+)`',r'<code>\1</code>',s);s=re.sub(r'\*\*([^*]+)\*\*',r'<strong>\1</strong>',s);return s
while i<len(lines):
 line=lines[i]
 if line.startswith('```'):
  code=[];i+=1
  while i<len(lines)and not lines[i].startswith('```'):code.append(lines[i]);i+=1
  parts.append('<div class="command"><button type="button" onclick="copyCode(this)">复制命令</button><pre><code>'+html.escape('\n'.join(code))+'</code></pre></div>');i+=1;continue
 if line.startswith('# '):parts.append('<h1>'+inline(line[2:])+'</h1>');i+=1;continue
 if line.startswith('## '):
  step+=1;title=line[3:];toc.append('<a href="#step'+str(step)+'">'+html.escape(title)+'</a>');parts.append('<h2 id="step'+str(step)+'">'+inline(title)+'</h2>');i+=1;continue
 if line.startswith('|')and i+1<len(lines)and re.match(r'^\|[ :|\-]+$',lines[i+1]):
  headers=[x.strip()for x in line.strip('|').split('|')];i+=2;rows=[]
  while i<len(lines)and lines[i].startswith('|'):rows.append([x.strip()for x in lines[i].strip('|').split('|')]);i+=1
  parts.append('<div class="table"><table><thead><tr>'+''.join('<th>'+inline(x)+'</th>'for x in headers)+'</tr></thead><tbody>'+''.join('<tr>'+''.join('<td>'+inline(c)+'</td>'for c in row)+'</tr>'for row in rows)+'</tbody></table></div>');continue
 if re.match(r'^(?:- |\d+\. )',line):
  ordered=bool(re.match(r'^\d+\. ',line));tag='ol'if ordered else'ul';items=[]
  while i<len(lines)and(re.match(r'^\d+\. ',lines[i])if ordered else lines[i].startswith('- ')):
   items.append(re.sub(r'^(?:- |\d+\. )','',lines[i]));i+=1
  parts.append('<'+tag+'>'+''.join('<li>'+inline(s)+'</li>'for s in items)+'</'+tag+'>');continue
 if not line.strip():i+=1;continue
 para=[line];i+=1
 while i<len(lines)and lines[i].strip()and not re.match(r'^(?:#|\||```|- |\d+\. )',lines[i]):para.append(lines[i]);i+=1
 parts.append('<p>'+inline(' '.join(para))+'</p>')
css='''*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:#f5f7fa;color:#192a3a;font:16px/1.8 -apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif}header{background:#17364c;color:white;padding:24px max(24px,calc((100vw - 1180px)/2));font-size:14px}header b{font-size:21px;display:block}main{max-width:1180px;margin:32px auto;display:grid;grid-template-columns:230px minmax(0,1fr);gap:28px;padding:0 20px}nav{position:sticky;top:24px;align-self:start;font-size:13px}nav a{display:block;padding:8px 10px;color:#3e5568;text-decoration:none;border-left:2px solid #d8e0e7}nav a:hover{background:#e8eef3;color:#102f47}article{background:white;border:1px solid #e0e6ed;border-radius:10px;padding:32px 38px;min-width:0}h1{font-size:28px;line-height:1.45;margin:0 0 24px}h2{font-size:21px;padding-top:28px;border-top:1px solid #e2e8ef;margin-top:36px;scroll-margin-top:20px}p{margin:16px 0}a{color:#1464a0}code{font:14px/1.65 ui-monospace,SFMono-Regular,Consolas,monospace;background:#edf2f6;padding:2px 5px;border-radius:3px;overflow-wrap:anywhere}pre{background:#142838;color:#eef4fa;margin:0;padding:44px 18px 18px;overflow:auto;border-radius:7px}pre code{background:transparent;padding:0;color:inherit;white-space:pre;overflow-wrap:normal} .command{position:relative;margin:18px 0}button{position:absolute;right:9px;top:8px;background:#28475f;border:1px solid #597187;color:white;border-radius:4px;padding:4px 10px;cursor:pointer;font:12px sans-serif}.table{overflow:auto}table{border-collapse:collapse;width:100%;font-size:14px;margin:18px 0}th,td{padding:10px 12px;text-align:left;border:1px solid #dae3eb;vertical-align:top}th{background:#edf3f7}li{margin:7px 0}footer{text-align:center;color:#728394;font-size:12px;padding:24px}@media(max-width:850px){main{display:block;margin-top:18px}nav{position:static;margin-bottom:20px;columns:2}article{padding:24px 18px}h1{font-size:24px}}@media print{header,nav,button,footer{display:none}main{display:block;padding:0;margin:0}article{border:0;padding:0}pre{white-space:pre-wrap;background:#f1f3f5;color:#111;padding:14px}pre code{white-space:pre-wrap}h2{break-after:avoid}table,pre{break-inside:avoid}}'''
js='''async function copyCode(b){const text=b.parentElement.querySelector('code').textContent;try{await navigator.clipboard.writeText(text)}catch(e){const t=document.createElement('textarea');t.value=text;document.body.appendChild(t);t.select();document.execCommand('copy');t.remove()}b.textContent='已复制';setTimeout(()=>b.textContent='复制命令',1500)}'''
doc='<!doctype html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>食安第二套达梦迁移实施手册</title><style>'+css+'</style></head><body><header><b>食安第二套 · 数据库迁移</b>按顺序执行，每步确认成功后继续 · standard_wxb / c4070071</header><main><nav>'+''.join(toc)+'</nav><article>'+''.join(parts)+'</article></main><footer>客户数据及私有配置保存在受控目录；本手册可离线阅读。</footer><script>'+js+'</script></body></html>'
(src.with_suffix('.html')).write_text(doc,encoding='utf8');print('Offline HTML rendered: '+str(src.with_suffix('.html')))
