from html import escape
from pathlib import Path
import re

source = Path(__file__).with_name('wms-sso-integration-maintenance.md').read_text()
lines = source.splitlines()
sections = []
blocks = []
index = 0
section_index = 0
highlight_open = False


def inline(text):
    text = escape(text)
    text = re.sub(r'`([^`]+)`', r'<code>\1</code>', text)
    return re.sub(r'\*\*([^*]+)\*\*', r'<strong>\1</strong>', text)


while index < len(lines):
    line = lines[index]
    if highlight_open and line.startswith(('## ', '### ')):
        blocks.append('</section>')
        highlight_open = False
    if not line.strip() or line.startswith('# '):
        index += 1
        continue
    if line.startswith('```'):
        language = line[3:].strip() or 'text'
        code = []
        index += 1
        while index < len(lines) and not lines[index].startswith('```'):
            code.append(lines[index])
            index += 1
        blocks.append('<div class="code-block"><div class="code-label">' + escape(language) + '</div><pre><code>' + escape('\n'.join(code)) + '</code></pre></div>')
        index += 1
        continue
    if line.startswith('## '):
        section_index += 1
        title = line[3:].strip()
        anchor = 'section-' + str(section_index)
        sections.append((anchor, title))
        blocks.append('<h2 id="' + anchor + '">' + inline(title) + '</h2>')
        index += 1
        continue
    if line.startswith('### '):
        if line[4:].strip() == '更换进销存项目：直接操作清单':
            blocks.append('<section class="project-switch-highlight" id="project-switch-guide" aria-label="重点：更换进销存项目操作清单">')
            highlight_open = True
        blocks.append('<h3>' + inline(line[4:]) + '</h3>')
        index += 1
        continue
    if line.startswith('|'):
        rows = []
        while index < len(lines) and lines[index].startswith('|'):
            cells = [cell.strip() for cell in lines[index].strip().strip('|').split('|')]
            if not all(re.fullmatch(r':?-{3,}:?', cell) for cell in cells):
                rows.append(cells)
            index += 1
        header = '<tr>' + ''.join('<th>' + inline(cell) + '</th>' for cell in rows[0]) + '</tr>'
        body = ''.join('<tr>' + ''.join('<td>' + inline(cell) + '</td>' for cell in row) + '</tr>' for row in rows[1:])
        blocks.append('<div class="table-wrap"><table><thead>' + header + '</thead><tbody>' + body + '</tbody></table></div>')
        continue
    if line.startswith('- ') or re.match(r'^\d+\. ', line):
        ordered = bool(re.match(r'^\d+\. ', line))
        items = []
        pattern = r'^\d+\. ' if ordered else r'^- '
        while index < len(lines) and re.match(pattern, lines[index]):
            items.append('<li>' + inline(re.sub(pattern, '', lines[index])) + '</li>')
            index += 1
        tag = 'ol' if ordered else 'ul'
        blocks.append('<' + tag + '>' + ''.join(items) + '</' + tag + '>')
        continue
    paragraph = [line]
    index += 1
    while index < len(lines) and lines[index].strip() and not re.match(r'^(#|\||```|- |\d+\. )', lines[index]):
        paragraph.append(lines[index])
        index += 1
    blocks.append('<p>' + inline(' '.join(paragraph)) + '</p>')

if highlight_open:
    blocks.append('</section>')
navigation = ''.join('<a href="#' + anchor + '">' + escape(title) + '</a>' for anchor, title in sections)
content = '\n'.join(blocks)
template = '''<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="light">
<title>大屏进销存对接与后期维护手册 · 12小时维护</title>
<style>
:root{--ink:#182b39;--muted:#60727c;--line:#dbe4e9;--accent:#08766d;--paper:#fff;--canvas:#f3f6f8}
*{box-sizing:border-box}html{scroll-behavior:smooth;scroll-padding-top:24px}body{margin:0;background:var(--canvas);color:var(--ink);font:15px/1.85 -apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif}
a{color:var(--accent)}.hero{background:#112c3a;color:white;padding:52px max(24px,calc((100vw - 1280px)/2)) 40px;border-bottom:5px solid #23a28e}.eyebrow{font-size:12px;letter-spacing:2px;color:#9fd8d0;margin:0 0 14px}.hero h1{font-size:clamp(27px,3.8vw,42px);line-height:1.3;letter-spacing:-.7px;margin:0 0 16px}.subtitle{margin:0;max-width:850px;color:#d2e1e8}.meta{display:flex;gap:12px;flex-wrap:wrap;margin-top:22px}.meta span{font-size:12px;padding:4px 11px;border:1px solid #42616e;border-radius:3px}
.layout{max-width:1328px;margin:28px auto;display:grid;grid-template-columns:252px minmax(0,1fr);gap:26px;padding:0 24px}.sidebar{position:sticky;top:22px;align-self:start;max-height:calc(100vh - 44px);overflow:auto;padding:18px 12px;background:white;border:1px solid var(--line);border-radius:6px}.sidebar strong{display:block;margin:0 10px 10px;color:var(--muted);font-size:12px;letter-spacing:2px}.sidebar a{display:block;color:#3b5360;text-decoration:none;padding:7px 10px;border-radius:3px;font-size:13px;line-height:1.55}.sidebar a:hover,.sidebar a:focus-visible{background:#e7f4f1;color:#075b53;outline:2px solid #c8e7df;outline-offset:-2px}
main{background:white;border:1px solid var(--line);border-radius:6px;padding:30px 38px 48px;min-width:0}.notice{border-left:4px solid #c38c23;background:#fff8e9;padding:14px 18px;margin:0 0 24px;color:#68511d}.notice strong{color:#473711}h2{margin:44px 0 16px;padding-top:24px;border-top:1px solid var(--line);font-size:23px;line-height:1.5;letter-spacing:-.3px}h3{margin:25px 0 10px;font-size:17px;color:#146c64}p{margin:12px 0}strong{font-weight:650}ul,ol{padding-left:24px;margin:14px 0}li{padding:4px 0}.table-wrap{overflow:auto;border:1px solid var(--line);border-radius:4px;margin:17px 0 22px}table{border-collapse:collapse;width:100%;font-size:13px;line-height:1.7}th,td{padding:11px 13px;text-align:left;vertical-align:top;border-bottom:1px solid var(--line);overflow-wrap:anywhere}th{background:#ecf3f5;color:#253f4d;font-weight:650}tr:last-child td{border-bottom:0}tbody tr:nth-child(even){background:#fafcfd}
code{font-family:"SFMono-Regular",Consolas,monospace;font-size:.86em;background:#edf3f5;border-radius:3px;padding:2px 5px;overflow-wrap:anywhere}.code-block{background:#142e3c;color:#e5f1f4;border-radius:5px;overflow:hidden;margin:16px 0 24px}.code-label{font:11px/1.5 Consolas,monospace;color:#a7c7d1;background:#203e4d;padding:7px 16px;text-transform:uppercase;letter-spacing:1px}pre{margin:0;padding:16px;overflow:auto;font:12px/1.85 "SFMono-Regular",Consolas,monospace;tab-size:2}pre code{padding:0;background:none;border-radius:0;color:inherit;font-size:inherit;overflow-wrap:normal}.footer{padding:0 24px 34px;text-align:center;color:var(--muted);font-size:12px}
@media(max-width:960px){.layout{grid-template-columns:1fr;gap:18px}.sidebar{position:static;max-height:270px;display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}.sidebar strong{grid-column:1/-1}main{padding:22px}.hero{padding:34px 24px}}@media(max-width:540px){.layout{padding:0 12px}.sidebar{display:block}main{padding:18px 15px}h2{font-size:20px}.hero{padding:30px 20px}th,td{min-width:120px}}@media print{body{background:white;font-size:10pt}.hero{padding:20px;background:white;color:#182b39;border-bottom:2px solid #08766d}.eyebrow,.subtitle{color:#415b69}.meta span{border-color:#aaa}.layout{display:block;padding:0;margin:0;max-width:none}.sidebar,.notice{display:none}main{border:0;padding:0}h2{break-after:avoid;page-break-after:avoid}pre{white-space:pre-wrap}.code-block{background:#f1f4f6;color:#172c39;break-inside:avoid}th{background:#eef2f4}.table-wrap{overflow:visible}a{color:inherit}.footer{padding:12px}}
.project-switch-highlight{padding:18px 20px;background:#fff5f5;border:1px solid #ebbbbb;border-left:4px solid #bd3030;border-radius:5px;color:#962b2b;margin:18px 0 26px}.project-switch-highlight h3{color:#b32323;margin-top:0}.project-switch-highlight code{color:#972b2b;background:#ffe8e8}.project-switch-highlight .table-wrap{border-color:#ebbbbb}.project-switch-highlight th{color:#972b2b;background:#ffe8e8}.project-switch-highlight td{color:#962b2b}.project-switch-highlight tbody tr:nth-child(even){background:#fffafa}.project-switch-highlight .code-block{background:#fffafa;color:#962b2b;border:1px solid #ebbbbb}.project-switch-highlight .code-label{background:#ffe8e8;color:#972b2b}.project-switch-highlight pre code{background:transparent}
.project-switch-jump{display:block;width:fit-content;max-width:100%;margin-top:24px;padding:12px 18px;background:#fff0ef;color:#a52222;border:2px solid #e56c64;border-radius:5px;text-decoration:none;font-weight:650;line-height:1.6}.project-switch-jump:hover,.project-switch-jump:focus-visible{background:#ffe2df;outline:2px solid #ffb3ad;outline-offset:3px}
</style>
</head>
<body>
<header class="hero"><p class="eyebrow">SMART CANTEEN · ENGINEERING HANDOVER</p><h1>大屏进销存对接<br>与后期维护手册</h1><p class="subtitle">从按钮点击到单点登录，明确接口、配置、令牌生命周期与项目切换边界，供研发、实施和运维共同交接。</p><div class="meta"><span>版本 1.1 · 12小时维护</span><span>2026-10-22 · Asia/Shanghai</span><span>代码核对版 · 不含真实凭据</span></div><a class="project-switch-jump" href="#project-switch-guide">重点：更换进销存项目 IP、账号、密码 → 点击查看红色操作清单</a></header>
<div class="layout"><nav class="sidebar" aria-label="章节目录"><strong>文档导航</strong>__NAVIGATION__</nav><main><aside class="notice"><strong>部署边界：</strong>本机任务已核实，不代表现场已发布。已实现 12 小时有条件维护和失败重试；尚无供应商 token 验真及第三方页面拒绝后的自动重登。维护命令会产生真实登录，须在授权窗口执行。</aside>__CONTENT__</main></div>
<footer class="footer">Markdown 为可维护主文档 · 本页无需外部资源 · 支持浏览器打印为 PDF</footer>
</body></html>'''
print(template.replace('__NAVIGATION__', navigation).replace('__CONTENT__', content))
