{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# RBPU16 Data Sheet",
    "\n\nRun All -> self-contained HTML."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys,os,re,base64,mimetypes,subprocess\n",
    "from datetime import datetime as dt; from pathlib import Path; from html import escape as eh\n",
    "try: import markdown\n",
    "except: subprocess.check_call([sys.executable,'-m','pip','install','markdown','-q']); import markdown\n",
    "B=Path(os.getcwd()).resolve(); os.chdir(str(B)); sys.path.insert(0,str(B))\n",
    "from doc_builder import import_handler, image_extension, codeblock_extension\n",
    "print(f'  {B.name}')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Build"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def pc(md_text):\n",
    "    md_text = import_handler.process_imports(md_text,B,pc)\n",
    "    md_text = codeblock_extension.render_code_blocks(md_text,B)\n",
    "    return markdown.markdown(md_text,extensions=[\n",
    "        'tables','fenced_code','codehilite','nl2br','sane_lists',\n",
    "        image_extension.ImageRowProcessor(),\n",
    "    ],extension_configs={'codehilite':{'css_class':'highlight','guess_lang':False}})\n",
    "\n",
    "cn=[]\n",
    "with open(B/'project.yaml',encoding='utf-8') as f:\n",
    "    ic=False\n",
    "    for line in f:\n",
    "        line=line.rstrip()\n",
    "        if line.startswith('chapters:'): ic=True; continue\n",
    "        if ic:\n",
    "            mx=re.match(r'^\\s*-\\s+(.+)$',line)\n",
    "            if mx: cn.append(mx.group(1).strip())\n",
    "            elif line and not line.startswith(' '): ic=False\n",
    "\n",
    "print('Processing...')\n",
    "chapters=[]\n",
    "for i,n in enumerate(cn):\n",
    "    fp=B/'chapters'/n\n",
    "    if not fp.exists(): continue\n",
    "    print(f'  [{i+1}] {n}')\n",
    "    c=pc(fp.read_text(encoding='utf-8'))\n",
    "    mx=re.search(r'<h1[^>]*>(.*?)</h1>',c)\n",
    "    chapters.append(dict(id=f'ch{i+1}',number=str(i+1),title=mx.group(1) if mx else fp.stem,content=c))\n",
    "apd=B/'chapters'/'appendix'\n",
    "if apd.exists():\n",
    "    for j,fp in enumerate(sorted(apd.glob('*.md'),key=lambda p:p.name)):\n",
    "        lb=chr(65+j)\n",
    "        c=pc(fp.read_text(encoding='utf-8'))\n",
    "        mx=re.search(r'<h1[^>]*>(.*?)</h1>',c)\n",
    "        chapters.append(dict(id=f'app{lb}',number=f'Appendix {lb}',title=mx.group(1) if mx else fp.stem,content=c))\n",
    "\n",
    "CSS=(B/'doc_builder'/'themes'/'datasheet.css').read_text(encoding='utf-8')\n",
    "\n",
    "def _parse_yaml(path):\n",
    "    meta={}; features=[]; in_features=False\n",
    "    with open(path,encoding='utf-8') as f:\n",
    "        for line in f:\n",
    "            s=line.strip(); k=None\n",
    "            if s.startswith('features:'):\n",
    "                in_features=True; continue\n",
    "            if in_features:\n",
    "                if s.startswith('- '):\n",
    "                    features.append(s[2:].strip()); continue\n",
    "                elif s and not line.startswith(' '):\n",
    "                    in_features=False\n",
    "            if not in_features and ':' in s:\n",
    "                k,v=s.split(':',1)\n",
    "                meta[k.strip()]=v.strip()\n",
    "    meta['features']=features\n",
    "    return meta\n",
    "\n",
    "meta=_parse_yaml(B/'project.yaml')\n",
    "TITLE=meta.get('title','RBPU16')\n",
    "SUBTITLE=meta.get('subtitle','数据手册')\n",
    "AUTHOR=meta.get('author','郭成')\n",
    "AU=AUTHOR\n",
    "DATE=dt.now().strftime('%Y-%m-%d')\n",
    "\n",
    "def _title_html(t):\n",
    "    parts=t.split(' ',1)\n",
    "    if len(parts)>1:\n",
    "        return f'<span class=\"model\">{eh(parts[0])}</span> <span class=\"zh-name\">{eh(parts[1])}</span>'\n",
    "    return eh(t)\n",
    "_title=_title_html(TITLE)\n",
    "\n",
    "COVER=''.join([\n",
    "    '<div class=\"cover-page\">',\n",
    "    '<div class=\"cover-top\"><div class=\"product-family\">READOUT BASEBAND PROCESSOR</div></div>',\n",
    "    '<div class=\"cover-body\">',\n",
    "    f'<h1>{_title}</h1>',\n",
    "    f'<div class=\"subtitle\">{eh(SUBTITLE)}</div>',\n",
    "    '</div>',\n",
    "    f'<div class=\"cover-bottom\"><span class=\"rev\">Rev 1.0 &middot; {DATE}</span><span class=\"author\">{eh(AUTHOR)}</span></div>',\n",
    "    '</div>',\n",
    "])\n",
    "ch_html=chr(10).join(f'<div class=\"chapter\" id=\"{c[\"id\"]}\">{c[\"content\"]}</div>' for c in chapters)\n",
    "FULL=chr(10).join([\n",
    "    '<!DOCTYPE html>','<html lang=\"zh-CN\">','<head>',\n",
    "    '<meta charset=\"utf-8\">','<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">',\n",
    "    f'<title>{TITLE} Data Sheet</title>',f'<meta name=\"author\" content=\"{AU}\">',\n",
    "    '<style>',CSS,'</style>','</head>','<body class=\"auto-numbering\">',\n",
    "    COVER,ch_html,\n",
    "    '<div class=\"page-break\"></div>','<h1>Revision History</h1>',\n",
    "    '<table class=\"revision compact\">',\n",
    "    '<thead><tr><th>Rev</th><th>Date</th><th>Changes</th><th>Author</th></tr></thead>',\n",
    "    f'<tbody><tr><td>1.0</td><td>{DATE}</td><td>Initial</td><td>{AU}</td></tr></tbody>','</table>',\n",
    "    '</body>','</html>',\n",
    "])\n",
    "SR=re.compile(r'src=\"(assets/[^\"]+)\"'); mimetypes.init()\n",
    "def em(m):\n",
    "    r=m.group(1); ip=(B/r).resolve()\n",
    "    if not ip.exists(): return m.group(0)\n",
    "    mt,_=mimetypes.guess_type(str(ip))\n",
    "    if not mt: mt='image/png'\n",
    "    with open(ip,'rb') as f: b64=base64.b64encode(f.read()).decode()\n",
    "    return f'src=\"data:{mt};base64,{b64}\"'\n",
    "FULL=SR.sub(em,FULL)\n",
    "out=B/'output'; out.mkdir(exist_ok=True)\n",
    "hp=out/f'{TITLE}_Data_Sheet.html'; hp.write_text(FULL,encoding='utf-8')\n",
    "print(f'\\n  {hp.name} ({hp.stat().st_size/1024:.0f} KB) OK')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Done",
    "\n\nSelf-contained HTML in `output/`."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.9.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}