diff --git a/build.ipynb b/build.ipynb index f63d15f..e940b0f 100644 --- a/build.ipynb +++ b/build.ipynb @@ -73,13 +73,47 @@ " 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", - "TITLE='RBPU16'; AU='Guo Cheng'; DATE=dt.now().strftime('%Y-%m-%d')\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'{eh(parts[0])} {eh(parts[1])}'\n", + " return eh(t)\n", + "_title=_title_html(TITLE)\n", + "\n", "COVER=''.join([\n", " '
',\n", - " '
READOUT BASEBAND PROCESSOR
',\n", - " '

RBPU16
',chr(35835),chr(20986),chr(22522),chr(24102),chr(22788),chr(29702),chr(33455),chr(29255),'

',\n", - " '
Data Sheet · User Manual
',\n", - " f'

Rev 1.0 · {DATE}

{AU}

',\n", + " '
READOUT BASEBAND PROCESSOR
',\n", + " '
',\n", + " f'

{_title}

',\n", + " f'
{eh(SUBTITLE)}
',\n", + " '
',\n", + " f'
Rev 1.0 · {DATE}{eh(AUTHOR)}
',\n", " '
',\n", "])\n", "ch_html=chr(10).join(f'
{c[\"content\"]}
' for c in chapters)\n", diff --git a/chapters/00_cover.md b/chapters/00_cover.md index e7b56ad..90dabb3 100644 --- a/chapters/00_cover.md +++ b/chapters/00_cover.md @@ -16,4 +16,4 @@ RBPU16 是一款面向超导量子比特态信息读出的 SoC 芯片,最大 ## 功能框图 -![系统框图](../assets/chip_schematic.png){s=100%} +![系统框图](../assets/chip_schematic.png){w=100%} diff --git a/doc_builder/image_extension.py b/doc_builder/image_extension.py index 6276f81..e20044b 100644 --- a/doc_builder/image_extension.py +++ b/doc_builder/image_extension.py @@ -1,10 +1,10 @@ """Python-Markdown extension: image sizing. -Syntax (standard Markdown paths, relative to chapter file): - ![alt](../assets/x.png){s=50%} → scale to 50% (width, auto height) - ![alt](../assets/x.png){w=50%} → width 50%, auto height - ![alt](../assets/x.png){w=50%, h=300} → width 50%, max-height 300px - ![alt](../assets/x.png) → default: s=75% +Syntax: + ![alt](../assets/x.png){w=50%} → width 50%, height auto (proportional) + ![alt](../assets/x.png){h=50%} → height 50%, width auto (proportional) + ![alt](../assets/x.png){w=50%, h=300} → width 50%, max-height 300px (pixel h) + ![alt](../assets/x.png) → default: width 80%, height auto """ import re from markdown.extensions import Extension @@ -13,11 +13,10 @@ from markdown.inlinepatterns import ImageInlineProcessor IMG_RE = ( r'\!\[(?P.*?)\]\((?P[^)]+)\)' r'(?:\{' - r'(?:s=(?P\d+%))?' - r'(?:,\s*)?' r'(?:w=(?P\d+%))?' - r'(?:,\s*h=(?P\d+)(?:px)?)?' - r'\}?)?' + r'(?:,\s*)?' + r'(?:h=(?P\d+)(?:%|px)?)?' + r'\})?' ) @@ -26,22 +25,24 @@ class SizedImageProcessor(ImageInlineProcessor): def handleMatch(self, m, data): alt = m.group('alt') src = m.group('src') - scale = m.group('s') - width = m.group('w') - height = m.group('h') + w = m.group('w') + h = m.group('h') - # Normalize paths for HTML output src = src.replace('../assets/', 'assets/') src = src.replace('../circuits/output/', 'assets/') - if scale: - style = f'width:{scale}; height:auto; max-width:none; max-height:none' - elif width: - style = f'width:{width}; max-width:none' - if height: - style += f'; max-height:{height}px' + if w and h: + # Both specified: h could be % or px + style = f'width:{w}; height:{h}; max-width:none; max-height:none' + elif w: + # w only: auto height (proportional) + style = f'width:{w}; height:auto; max-width:none; max-height:none' + elif h: + # h only: auto width (proportional) + style = f'height:{h}; width:auto; max-width:none; max-height:none' else: - style = 'width:75%; height:auto' + # Default: 80% + style = 'width:80%; height:auto; max-width:none; max-height:none' img_tag = f'{alt}' el = self.md.htmlStash.store(img_tag) diff --git a/doc_builder/themes/datasheet.css b/doc_builder/themes/datasheet.css index f265bcc..e6fe84a 100644 --- a/doc_builder/themes/datasheet.css +++ b/doc_builder/themes/datasheet.css @@ -1,28 +1,25 @@ /* ============================================================ - Datasheet Theme — 芯片数据手册风格 + Datasheet Theme ============================================================ */ :root { --bg: #fff; - --text: #1a1a1a; - --text-muted: #555; + --text: #000; + --text-muted: #333; --heading: #000; --accent: #003d7c; - --accent-light: #e8f0f8; - --th-bg: #e9ecf0; - --th-border: #c0c4c8; - --stripe: #f7f8f9; - --cover-bg: #003d7c; - --cover-text: #fff; - --link: #005da0; - --note-bg: #f5f7fa; - --note-border: #003d7c; + --th-bg: #f2f2f2; + --th-border: #ccc; + --stripe: #fafafa; + --link: #000; + --note-bg: #f7f7f7; + --note-border: #999; --font-body: "Noto Serif CJK SC", "Source Han Serif SC", "SimSun", Georgia, serif; --font-heading: "Noto Sans CJK SC", "Source Han Sans SC", "Microsoft YaHei", "PingFang SC", sans-serif; --font-mono: "Cascadia Code", "Fira Code", Consolas, monospace; - --size: 14px; - --line: 1.7; + --size: 16px; + --line: 1.75; } *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } @@ -42,70 +39,73 @@ body { /* ---------- Cover ---------- */ .cover-page { - width: 100%; - box-sizing: border-box; - padding: 0 2.5em; - margin: 0 0 3em 0; min-height: 100vh; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 4em 2.5em; + margin: 0 0 3em 0; position: relative; -} -.cover-page-inner { - position: absolute; - top: 50%; left: 50%; - transform: translate(-50%, -50%); - text-align: center; - width: 100%; - padding: 0 2.5em; - box-sizing: border-box; -} -.cover-page .cover-meta { - position: absolute; - bottom: 40px; - left: 0; right: 0; - font-size: 0.8rem; - color: var(--text-muted); text-align: center; } -.cover-page::after { - content: ''; - position: absolute; - bottom: 0; left: 50%; transform: translateX(-50%); - width: 60px; height: 1px; - background: var(--th-border); -} -.cover-page .product-family { + +.cover-top { margin-bottom: 4em; } + +.cover-top .product-family { font-family: var(--font-heading); - font-size: 0.75rem; + font-size: 0.8rem; letter-spacing: 0.5em; text-transform: uppercase; color: var(--text-muted); - margin-bottom: 64px; -} -.cover-page h1 { - font-family: var(--font-heading); - font-size: 2.4rem; font-weight: 700; - line-height: 1.4; - margin-bottom: 20px; +} + +.cover-body { max-width: 100%; } + +.cover-body h1 { + font-family: var(--font-heading); + font-size: 2.6rem; + font-weight: 700; + line-height: 1.3; + margin-bottom: 0.5em; color: var(--heading); border: none; padding: 0; } -.cover-page .subtitle { + +.cover-body h1 .model { font-weight: 800; display: inline; } + +.cover-body h1 .zh-name { + font-weight: 600; + color: var(--text-muted); + display: inline; +} + +.cover-body .subtitle { font-family: var(--font-heading); - font-size: 1rem; + font-size: 1.05rem; font-weight: 400; color: var(--text-muted); - margin-bottom: 64px; + letter-spacing: 0.1em; } -.cover-page .feature-list { display: none; } -.cover-page .cover-meta { + +.cover-bottom { position: absolute; - bottom: 40px; - font-size: 0.8rem; + bottom: 3.5em; + left: 0; right: 0; + font-size: 0.85rem; color: var(--text-muted); + font-family: var(--font-heading); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 0.2em; } -.cover-page .cover-meta p { margin: 4px 0; } + +.cover-bottom .rev { font-weight: 700; color: var(--heading); } +.cover-bottom .author { white-space: nowrap; } /* ---------- Chapters ---------- */ .chapter { padding: 2em 2.5em; } @@ -113,43 +113,44 @@ body { /* ---------- Headings ---------- */ h1 { font-family: var(--font-heading); - font-size: 1.5rem; - font-weight: 700; + font-size: 1.6rem; + font-weight: 800; color: var(--heading); margin: 2em 0 0.8em; - padding-bottom: 6px; - border-bottom: 2px solid var(--accent); + padding-bottom: 8px; + border-bottom: 2px solid var(--heading); } h2 { font-family: var(--font-heading); - font-size: 1.25rem; + font-size: 1.3rem; font-weight: 700; - color: var(--accent); + color: var(--heading); margin: 1.5em 0 0.6em; padding-bottom: 4px; border-bottom: 1px solid var(--th-border); } h3 { font-family: var(--font-heading); - font-size: 1.1rem; - font-weight: 600; + font-size: 1.15rem; + font-weight: 700; color: var(--heading); margin: 1.2em 0 0.5em; } h4 { font-family: var(--font-heading); - font-size: 1rem; - font-weight: 600; + font-size: 1.05rem; + font-weight: 700; color: var(--text); margin: 1em 0 0.4em; } /* ---------- Body ---------- */ -p { margin: 0.6em 0; text-align: justify; } -ul, ol { margin: 0.6em 0; padding-left: 2em; } +p { margin: 0.6em 0; text-align: justify; color: var(--text); } +ul, ol { margin: 0.6em 0; padding-left: 2em; color: var(--text); } li { margin: 2px 0; } a { color: var(--link); text-decoration: none; } a:hover { text-decoration: underline; } +strong { font-weight: 700; color: var(--heading); } /* ---------- Tables ---------- */ table { @@ -161,13 +162,14 @@ table { thead th { background-color: var(--th-bg); font-family: var(--font-heading); - font-weight: 600; + font-weight: 700; font-size: 0.88rem; text-align: left; padding: 6px 10px; border: 1px solid var(--th-border); - border-bottom: 2px solid var(--accent); + border-bottom: 2px solid var(--heading); white-space: nowrap; + color: var(--heading); } tbody td { padding: 5px 10px; @@ -175,16 +177,15 @@ tbody td { vertical-align: top; } tbody tr:nth-child(even) { background-color: var(--stripe); } -table.compact { font-size: 0.82rem; } -table.compact thead th { font-size: 0.8rem; padding: 3px 7px; } +table.compact { font-size: 0.85rem; } +table.compact thead th { font-size: 0.82rem; padding: 3px 7px; } table.compact tbody td { padding: 3px 7px; } td.addr, td.bits, td.reset-val { font-family: var(--font-mono); font-size: 0.85em; white-space: nowrap; } td.bits { text-align: center; } -/* Permissions */ -.perm-rw { color: #1a7a1a; font-weight: 600; } -.perm-ro { color: #b8860b; font-weight: 600; } -.perm-wc { color: #8b0000; font-weight: 600; } +.perm-rw { color: var(--text); font-weight: 700; } +.perm-ro { color: var(--text); font-weight: 700; } +.perm-wc { color: var(--text); font-weight: 700; } /* ---------- Code ---------- */ code { @@ -194,172 +195,77 @@ code { padding: 1px 5px; border-radius: 2px; border: 1px solid var(--th-border); + color: var(--text); } pre { font-family: var(--font-mono); - font-size: 0.82rem; + font-size: 0.85rem; background: var(--note-bg); border: 1px solid var(--th-border); - border-left: 3px solid var(--accent); + border-left: 3px solid var(--heading); padding: 12px; margin: 1em 0; overflow-x: auto; line-height: 1.5; + color: var(--text); } pre code { background: none; padding: 0; border: none; font-size: inherit; } -/* Code block with line numbers (default @import display) */ .code-block { margin: 1em 0; border: 1px solid var(--th-border); - border-radius: 3px; overflow: hidden; } .code-header { background: var(--th-bg); font-family: var(--font-heading); - font-size: 0.78rem; + font-size: 0.8rem; padding: 4px 10px; color: var(--text-muted); border-bottom: 1px solid var(--th-border); + font-weight: 700; } .code-lines { - margin: 0; - border: none; - border-left: none; - font-size: 0.78rem; - line-height: 1.55; - padding: 8px 0; - background: #fafbfc; + margin: 0; border: none; border-left: none; + font-size: 0.82rem; line-height: 1.55; + padding: 8px 0; background: var(--stripe); + color: var(--text); } .code-lines .ln { - display: inline-block; - width: 40px; - text-align: right; - color: var(--text-muted); - user-select: none; - padding-right: 12px; - margin-right: 8px; - border-right: 1px solid var(--th-border); + display: inline-block; width: 40px; + text-align: right; color: var(--text-muted); + user-select: none; padding-right: 12px; + margin-right: 8px; border-right: 1px solid var(--th-border); } -.code-lines .lc { +.code-lines .lc { color: var(--text); } + +/* ---------- Figures ---------- */ +figure { margin: 1.2em auto; text-align: center; max-width: 75%; } +figure img { max-width: 100%; max-height: 420px; height: auto; border-radius: 2px; } +figure figcaption { + font-family: var(--font-heading); font-size: 0.85rem; + color: var(--text-muted); margin-top: 4px; font-weight: 700; +} +p img { max-width: 75%; max-height: 400px; height: auto; display: block; margin: 0.8em auto; border-radius: 2px; } +td img { max-width: 100%; max-height: 180px; margin: 0; } +.img-row { display: flex; gap: 1em; justify-content: center; align-items: flex-start; margin: 1em 0; } +.img-row img { flex: 0 0 auto; margin: 0; border-radius: 2px; } + +/* ---------- Notes ---------- */ +blockquote { + margin: 1em 0; padding: 10px 16px; + border-left: 3px solid var(--heading); + background: var(--note-bg); font-size: 0.92rem; color: var(--text); } -/* ---------- Figures ---------- */ -figure { - margin: 1.2em auto; - text-align: center; - max-width: 75%; -} -figure img { - max-width: 100%; - max-height: 420px; - height: auto; - border-radius: 3px; -} -figure figcaption { - font-family: var(--font-heading); - font-size: 0.85rem; - color: var(--text-muted); - margin-top: 4px; -} -/* Standalone images (not in figure) */ -p img { - max-width: 75%; - max-height: 400px; - height: auto; - display: block; - margin: 0.8em auto; - border-radius: 3px; -} -/* Small images: inline icons, small diagrams */ -img.img-sm, figure.img-sm { max-width: 40%; } -figure.img-sm img { max-height: 240px; } -/* Full-width: detailed block diagrams that need detail */ -img.img-lg, figure.img-lg { max-width: 95%; } -figure.img-lg img { max-height: 600px; } -/* Images inside table cells — tighter constraints */ -td img { - max-width: 100%; - max-height: 180px; - margin: 0; -} -/* Side-by-side image row */ -.img-row { - display: flex; - gap: 1em; - justify-content: center; - align-items: flex-start; - margin: 1em 0; -} -.img-row img { - flex: 0 0 auto; - margin: 0; - border-radius: 3px; -} - -/* ---------- Blockquote / Notes ---------- */ -blockquote { - margin: 1em 0; - padding: 10px 16px; - border-left: 4px solid var(--note-border); - background: var(--note-bg); - font-size: 0.92rem; -} - -/* ---------- TOC ---------- */ -.toc { margin-bottom: 2em; } -.toc h2 { font-size: 1.4rem; border-bottom: 2px solid var(--accent); } -.toc-list { list-style: none; padding: 0; } -.toc-list li { - padding: 4px 0; - border-bottom: 1px dotted var(--th-border); - display: flex; - justify-content: space-between; -} -.toc-list li a { flex: 1; } - -/* ---------- Sidebar (screen only) ---------- */ -@media screen and (min-width: 1200px) { - body { padding-left: 260px; max-width: 1100px; } - .screen-toc { - position: fixed; - left: max(0px, calc((100vw - 1100px) / 2 - 240px)); - top: 0; - width: 220px; - height: 100vh; - overflow-y: auto; - background: var(--note-bg); - border-right: 1px solid var(--th-border); - padding: 16px 12px; - font-size: 0.78rem; - z-index: 100; - } - .cover-page { margin-left: calc(-2em - 260px + 2.5em); } -} - -@media screen and (max-width: 1199px) { - .screen-toc { display: none; } -} - -.screen-toc ul { list-style: none; padding: 0; } -.screen-toc li { margin: 3px 0; line-height: 1.4; } -.screen-toc a { color: var(--text); display: block; padding: 2px 5px; border-radius: 2px; } -.screen-toc a:hover { background: var(--accent-light); text-decoration: none; } - -/* ---------- Register summary ---------- */ .reg-summary { font-size: 0.9rem; } .reg-summary strong { margin-right: 4px; } .reg-summary code { margin-right: 12px; } -/* ---------- Warning ---------- */ .warning { - background: #fff3cd; - border: 1px solid #ffc107; - padding: 10px; - margin: 10px 0; - border-radius: 3px; + background: #f5f5f5; border: 1px solid #999; + padding: 10px; margin: 10px 0; color: var(--text); } /* ---------- Utility ---------- */ @@ -370,8 +276,8 @@ blockquote { /* ---------- Auto-numbering ---------- */ body.auto-numbering { counter-reset: section; } body.auto-numbering .chapter h1 { counter-increment: section; counter-reset: subsection; } -body.auto-numbering .chapter h1::before { content: counter(section) ". "; } +body.auto-numbering .chapter h1::before { content: counter(section) ". "; font-weight: 800; } body.auto-numbering .chapter h2 { counter-increment: subsection; counter-reset: subsubsection; } -body.auto-numbering .chapter h2::before { content: counter(section) "." counter(subsection) " "; } +body.auto-numbering .chapter h2::before { content: counter(section) "." counter(subsection) " "; font-weight: 700; } body.auto-numbering .chapter h3 { counter-increment: subsubsection; } -body.auto-numbering .chapter h3::before { content: counter(section) "." counter(subsection) "." counter(subsubsection) " "; } +body.auto-numbering .chapter h3::before { content: counter(section) "." counter(subsection) "." counter(subsubsection) " "; font-weight: 700; } diff --git a/readme.md b/readme.md index aa388a2..4b8164f 100644 --- a/readme.md +++ b/readme.md @@ -1,28 +1,28 @@ # RBPU16 读出基带处理芯片 · 数据手册 -纯文本管理,Python 脚本构建,生成自包含 HTML 报告。 +纯文本管理,Python 构建,生成自包含 HTML 报告。 ## 项目结构 ``` -├── build.ipynb # 构建入口:VS Code 打开 → Run All -├── project.yaml # 项目配置(标题、作者、章节列表) -├── chapters/ # 章节源文件(Markdown) -├── data/ # 结构化数据(CSV / JSON) -├── assets/ # 图片(PNG / JPG) -├── doc_builder/ # 构建工具(可跨项目复用) +├── build.ipynb # 构建入口:VS Code 打开 → Run All +├── project.yaml # 项目配置(标题、作者、章节列表) +├── chapters/ # 章节源文件(Markdown) +├── data/ # 结构化数据(CSV / JSON) +├── assets/ # 图片(PNG / JPG) +├── doc_builder/ # 构建工具(可跨项目复用) │ ├── themes/datasheet.css -│ ├── renderers/ # 代码块渲染器 +│ ├── renderers/ # 代码块渲染器 │ │ └── schemdraw.py -│ ├── render_table.py # @import 渲染器 -│ ├── render_bga.py -│ ├── render_address.py -│ ├── render_registers.py -│ ├── render_requirements.py -│ ├── import_handler.py # @import 调度器 -│ ├── image_extension.py # 图片尺寸扩展 -│ └── codeblock_extension.py# 代码块渲染(pre-markdown) -└── output/ # 构建产物 +│ ├── render_table.py # @import 渲染器:通用表格 +│ ├── render_bga.py # @import 渲染器:BGA 网格 +│ ├── render_address.py # @import 渲染器:地址映射表 +│ ├── render_registers.py # @import 渲染器:寄存器定义 +│ ├── render_requirements.py # @import 渲染器:YAML 需求表 +│ ├── import_handler.py # @import 调度器 +│ ├── image_extension.py # 图片尺寸扩展 +│ └── codeblock_extension.py # 代码块渲染(pre-markdown) +└── output/ # 构建产物 └── RBPU16_Data_Sheet.html ``` @@ -46,15 +46,16 @@ chapters: ### 1. 图片 ```markdown -![alt](../assets/x.png){s=75%} # 等比例缩放,默认 75% -![alt](../assets/x.png){s=100%} # 原始尺寸 -![alt](../assets/x.png){w=50%} # 宽度 50%,高度自适应 -![alt](../assets/x.png){w=48%, h=200} # 宽度 48% + 最大高度 200px +![alt](../assets/x.png) # 默认 80% 宽,高自动等比 +![alt](../assets/x.png){w=50%} # 宽 50%,高自动等比 +![alt](../assets/x.png){h=50%} # 高 50%,宽自动等比 +![alt](../assets/x.png){w=50%, h=300} # 宽 50% + 最大高度 300px ``` -- `{s=N%}` — 等比例缩放,同时控制宽高 -- `{w=N%}` — 仅控制宽度 -- `{w=N%, h=M}` — 宽度 + 最大高度(像素) +- `{w=N%}` — 宽 N%,高自动等比 +- `{h=N%}` — 高 N%,宽自动等比 +- `{w=N%, h=M}` — 同时指定宽高(h 为像素时限制最大高度) +- 不写 → 默认 `w=80%` - 两张图 `{w=N%}` 相加 ≤ 100% 时自动并排 ### 2. `@import` — 导入数据文件 @@ -68,20 +69,18 @@ chapters: `using ` 加载项目根目录下的 Python 脚本,调用 `render(filepath)` → HTML。脚本不存在时降级为行号视图,不报错。 -### 3. 代码块渲染 — ` ```lang ` +### 3. 代码块渲染 -```markdown ```schemdraw import schemdraw from schemdraw import elements as e with schemdraw.Drawing(show=False) as d: d += e.Resistor().right().label('R1') ``` -``` -构建时在 markdown 之前执行:` ```lang ` 代码块 → `doc_builder/renderers/lang.py` → SVG/HTML。`mermaid` 等标签为 passthrough(浏览器渲染)。 +构建时在 markdown 之前执行:代码块 → `doc_builder/renderers/.py` → SVG/HTML。`mermaid` 等标签为 passthrough(浏览器端渲染)。 -### 4. 表格占位符 +### 4. 占位符 表格中 `—` 表示待补充数据。 @@ -91,10 +90,10 @@ with schemdraw.Drawing(show=False) as d: 章节 .md 文件 │ ├─→ @import 处理器(替换为渲染 HTML) - ├─→ 代码块渲染器(```schemdraw → SVG) + ├─→ 代码块渲染器(```lang → 渲染输出) └─→ Python-Markdown(→ HTML) │ - ├─→ 图片尺寸扩展({s=N%} / {w=N%}) + ├─→ 图片尺寸扩展({w=N%} / {h=N%}) └─→ codehilite(代码高亮) │ ▼