Align ASCII box-drawing diagrams in Markdown files, with CJK and nesting support.
Project description
ascii-box-aligner
在 Markdown 文档的 围栏代码块(```)内,自动对齐 ASCII / Unicode 框线字符绘制的示意图:统一右侧竖线与边框宽度,并在内容溢出时按需加宽方框。支持 中日韩全角字符(按终端可视宽度计算占列)、多层嵌套与并排小框。
功能概览
| 能力 | 说明 |
|---|---|
| 处理范围 | 仅处理 fenced code block 内的文本;围栏外的 Markdown 原样保留 |
| 竖线与宽度 | 按「可视列」对齐右侧 │、┤ 等;必要时拉长顶/底的 ─ _run |
| CJK | 全角字符按 2 列宽;对部分 Unicode「ambiguous」符号(箭头、制表几何图形等)按 1 列处理 |
| 嵌套 | 基于父子关系 后序(_innermost first) 对齐,避免外框先于内框改写 |
| 加宽策略 | 仅在确有「有意义内容」溢出时才加宽;空格与可伸缩横线(─/═/━)一般不迫使加宽 |
| 原位改写 | -w / --write 可将结果写回文件 |
环境要求
- Python ≥ 3.10
- 无第三方运行时依赖(标准库即可)。
安装
使用 uv(推荐)
cd ascii-box-aligner
uv sync
使用 pip(可编辑安装)
pip install -e .
安装后可通过入口 ascii-box-aligner 调用 CLI。
命令行用法
ascii-box-aligner [-w|--write] [FILE ...]
| 参数 | 含义 |
|---|---|
FILE |
一个或多个 Markdown 文件路径 |
(省略或使用 -) |
从 stdin 读取,结果写到 stdout |
-w / --write |
将对齐后的全文 写回对应输入文件(不能与 stdin - 同时使用) |
示例
# 预览:对齐后打印到终端
ascii-box-aligner notes.md
# 原地改写
ascii-box-aligner -w notes.md
# 管道
cat diagram.md | ascii-box-aligner > aligned.md
退出码:0 成功;读文件失败等为非零。
Python API
适合在脚本或其它工具里嵌入:
from ascii_box_aligner import align_text
md = Path("notes.md").read_text(encoding="utf-8")
fixed = align_text(md)
Path("notes-aligned.md").write_text(fixed, encoding="utf-8")
额外导出
from ascii_box_aligner import Box, visual_width, visual_to_str_index
visual_width(s):字符串整行的可视宽度(用于理解「列」与检测逻辑)。visual_to_str_index:可视列 ↔ 字符串下标换算(框线与 CJK 混排时使用)。
工作原理(简述)
整体流水线在源码注释中有更细的说明(见 src/ascii_box_aligner/aligner.py 开头)。
-
围栏扫描
找出 Markdown 中成对的 ``` 围栏;仅在围栏 内部 行上操作。 -
方框检测
在每个围栏内扫描「顶边」:┌(或╔/┏),必要时支持从├开头的分枝顶边(后跟横线)。
左侧竖线在向下追踪时允许 小幅抖动(适应手写示意图里轻微错位)。 -
嵌套树
根据包含关系建立父子结构;对齐顺序为 post-order(先子后父)。 -
单框对齐(对每个框)
- 遍历框内各行(不含顶/底边专用逻辑的简述):估算「有意义内容」所需的最右可视列;
new_right = max(原始右边列, 各行需求),并可应用少量启发式(例如抑制单行抖动导致的无谓加宽);- 重绘顶/底横边(含标签的边尽量只做横向闭合伸缩);
- 内容行在「内容与右边框」之间调节空格或可伸缩横线,使边框落在目标列。
可视列:与终端渲染一致——多数 CJK 为 2 列;框线字符等为 1 列(详见 models.char_visual_width)。
支持的框线字符
检测与对齐涵盖常用的 light / heavy 框线与接头,例如:
- 角:
┌ ┐ └ ┘及双线变体等 - 竖横:
│ ─、┃、═、━ - 接头:
├ ┤ ┬ ┴ ┼及双线变体等
只要示意图主要由上述字符构成,一般可被识别;极其随意的混合或非矩形拼贴可能失败。
限制与注意事项
- 只处理围栏代码块:普通段落里的框线图不会被改写。
- 识别假设:依赖清晰的顶左角 + 顶右角 + 大致落地的底左角闭合;严重残缺或非矩形布局可能检测不到或误判。
- 标签横边:顶/底边若夹带大量正文标签,加宽时可能跳过整块重绘以防破坏文案(CLI 仍会尽量伸缩末尾横线与角)。
- 审美目标:算法优先「对齐」与「不溢出」,与某一手工排版版本的空格分布可能略有差异。
目录结构
.
├── pyproject.toml # 项目元数据与脚本入口
├── main.py # 可选入口,转发到 CLI
├── README.md
└── src/ascii_box_aligner/
├── __init__.py # 导出 align_text 等
├── cli.py # 命令行
├── aligner.py # 对齐主算法
├── detector.py # 围栏与方框检测、建树
└── models.py # Box、可视宽度工具
许可证与版本
版本号见 pyproject.toml 中的 [project]。若仓库另附 LICENSE,以该文件为准。
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ascii_box_aligner-0.1.0.tar.gz.
File metadata
- Download URL: ascii_box_aligner-0.1.0.tar.gz
- Upload date:
- Size: 20.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
321ba471f7214be69bd34f171c544962032c09cdecdd5f1b9e561b2efe0f53af
|
|
| MD5 |
c090b6303d5a570325c7f2f6a158110f
|
|
| BLAKE2b-256 |
747a3b11582028e6a97dcdb81838e8f1494202d4b15d30e6dc42640eeb279ab9
|
File details
Details for the file ascii_box_aligner-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ascii_box_aligner-0.1.0-py3-none-any.whl
- Upload date:
- Size: 20.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
772b05f85c8957d4ce129b3f02daecd12fd539df06871ae314a55aaf47e2e904
|
|
| MD5 |
e8135b32817da05abfe9b5c91cb692b3
|
|
| BLAKE2b-256 |
8fc36a7cd0cbd55fb34d787908b21d791e47e1114db1d78309c20298ba9f2842
|