# 迭代日志


## 0.7.9 模板子目录重构

- 将 nb 模板从根目录移至 `templates/nb/` 子目录，并统一默认模板常量定义。

## 0.7.10 Theme Frontmatter 配置

- 新增 `theme` 配置组到 frontmatter，包含：
  - `theme.template` - 指定模板文件（替代顶级 `template`）
  - `theme.coverstyle` - 封面样式 ("default" / "report")
  - `theme.overview-fill` - overview 块背景色
- `nb.typ` 模板支持根据 coverstyle 切换封面库

## 0.7.11 模板导入机制简化

- 实现了模板智能解析：
  - 输入 `nb` 自动按顺序查找：`nb.typ`, `nb/nb.typ`, `nb/index.typ`
  - 简化了默认配置配置值为 `nb`
- 重构了 `helper_typst` 依赖处理：
  - 目录式模板（如 `nb/nb.typ`）直接复制整个目录，废弃了复杂的正则依赖解析
  - 移除了 `parse_template_deps` 等废弃函数
  - 仅支持 `theme.template` 格式配置，不再支持顶级 `template`

- **Frontmatter 结构变更**：
  - 将 `font` 和 `titlefont` 从 `pubinfo` 移至 `theme` 配置组。

## 0.7.13 封底样式系统 & Darkbg 封面优化

- **封底样式系统**：
  - 新增 `theme.backcoverstyle` 配置项，支持 `default` / `biglogo` 两种封底样式
  - `default` 封底：底部小 Logo + 出版信息
  - `biglogo` 封底：中央大 Logo + 底部出版信息
  - 新增 `nb-backcover-biglogo-lib.typ` 封底库文件

- **Darkbg 封面 Hero Image 优化**：
  - Hero Image 改用 `place` 固定定位（`dy: 4.1cm`），取代弹性布局
  - 解决了内容变化导致 Hero Image 位置不稳定的问题

## 0.7.14 PDF 压缩命令

- **新增 `compress` 命令**：使用 PyMuPDF 压缩 PDF 文件大小
  - `yakultpdf compress sample.pdf` - 压缩单个文件（覆盖原文件）
  - `yakultpdf compress --all` - 压缩 out 目录下所有 PDF
  - `yakultpdf compress --no-overwrite` - 输出为 `xxx_sm.pdf`
  - `--dpi` 参数预留，用于后续图片 DPI 重采样
- **压缩策略**：
  - `doc.scrub()` 清除元数据、缩略图等
  - `doc.ez_save()` 启用 garbage=3 + deflate 压缩
  - PNG → JPEG 转换（仅 >1MB 且无透明通道的 PNG）
- **依赖**：新增 `pymupdf`

## 0.7.15 NB 模板图片优化

- **Top/Bottom Image 支持**
  - 新增 `<topimage>` (页首出血图) 和 `<bottomimage>` (页尾出血图) 支持
  - 图片按原始比例显示，自动处理页边距和出血
- **Cover 兼容性修复**
  - 修复 `coverbg` 参数在不同封面样式下的兼容性问题
  - 仅 `darkbg`/`dark` 样式传递 `coverbg` 参数，避免其他样式报错

## 0.7.20-21 性能优化

- **Frontmatter 解析优化**
  - 新增 LRU 缓存机制（128 条），基于文件 mtime + size 判定命中
  - 转换流程中 frontmatter 仅解析一次，复用传递到各函数
- **字体路径缓存**
  - 目录级字体文件列表缓存，基于 mtime 失效
  - 避免重复遍历字体目录
- **工具检查优化**
  - `check_pandoc_typst()` 仅首次执行检查
  - 新增 `--skip-tool-check` 选项跳过检查
- **CLI 增强**
  - 新增 `--version` 选项显示版本号
- **批量并发处理**
  - 新增 `--jobs` 参数，支持 `ProcessPoolExecutor` 并发转换多文件
  - 默认 jobs=1 保持串行，可根据机器性能调整
- **OpenCC 实例缓存**
  - 使用 `lru_cache` 缓存 `OpenCC("s2t")` 实例，避免重复创建
  - 懒加载 import，未使用繁体转换时不加载 opencc
- **繁体转换去重**
  - CLI 构建后处理器链时不再加入 `to_traditional_chinese`
  - 繁体转换统一由 core 层 `options.tc` 处理，避免重复执行
- **Markdown 预处理优化**
  - 合并 `@` 和 `$` 字符转义为单次遍历 (`pre_escape_typst_chars`)
  - protected_regions 检查从 O(n*m) 优化为 O(n)
  - 预编译标题相关正则表达式


## 0.7.22 繁体转换修复与重构

- **繁体转换逻辑修复**
  - 修复自定义后处理器可能导致 `tc` 标志失效的问题
  - 确保 `tc=True` 时始终执行繁体转换，且执行顺序在自定义后处理器之后
  - `convert_file` / `convert_directory` / `convert_from_string` 统一增加 `postprocess` 参数支持
- **代码重构**
  - 重构 `process_builder.py`，使用 `load_postprocessor` 统一加载逻辑
  - 移除 `utils.py` 中被废弃的 `convert_to_traditional` 实现（已迁移至 `mark2pdf.helper_utils`）

## 0.7.23 Process Builder 彻底解耦

**处理流程（简化版）**
- CLI 先根据 flags 组装处理器名称：`--removelink` → `remove_links`，`--postprocess` → 指定名称，`--tc` → `to_traditional_chinese`；随后去重并保持顺序。
- `build_postprocessor_chain(names)` 只做加载与组装：返回 `PostprocessBuildResult`，包含 `chain`（可执行链）、`loaded`（成功加载）、`missing`（未找到）。
- CLI 负责输出：若有 `missing`，用 `click.echo(..., err=True)` 警告；`--verbose` 时显示已加载列表。
- 转换逻辑使用 `result.chain` 作为后处理链；非 CLI 场景不会产生任何输出副作用。

**结果对象**
- `chain`: 组合后的后处理函数（可能为 `None`）
- `loaded`: 实际加载成功的处理器名列表
- `missing`: 未找到的处理器名列表

## 0.7.24 代码审查与安全修复

- **安全修复**
  - 修复 `get_output_filename` 路径穿越漏洞：调整检查顺序，先检查原始输入再提取文件名
  - 增加绝对路径前缀检测（`/`, `\`）和空文件名验证

- **异常处理改进**
  - `interfile_manager.py`: `Exception` → `OSError`
  - `coverimg.py`: `Exception` → `OSError`
  - `compress.py`: `Exception` → `OSError`
  - `conversion.py`: 批处理添加 `traceback.print_exc()` 记录完整堆栈

- **代码清理**
  - 删除 `md_preprocess.py` 中 184 行已注释的遗留代码（旧字符串解析方法）

## 0.7.25 run_batch_conversion 重构

- **函数拆分**：将 204 行的 `run_batch_conversion` 拆分为多个子函数（每个 50 行以内）
  - `BatchConfig` dataclass：批量转换配置数据结构
  - `_prepare_postprocessors`：后处理器配置准备
  - `_prepare_batch_config`：配置加载和 frontmatter 合并
  - `_discover_batch_files`：文件发现和排序
  - `_run_sequential`：单线程执行
  - `_run_parallel`：多线程执行
- **默认并发数调整**：`--jobs` 默认值从 1 改为 4

## 0.7.26 CLI convert 命令重构

- **测试加固**：增加参数冲突检测、`--show-config`、Mock 模式调用等 6 个测试用例，覆盖率显著提升
- **函数拆分**：将 162 行的 `convert` 命令拆分为清晰的子函数
  - `_validate_convert_args`：参数合法性校验
  - `_prepare_convert_config`：配置上下文 (`ConvertContext`) 组装
  - `_dispatch_conversion`：根据模式分发执行 (`directory`/`batch`/`single`)
- **Move**: 将 `convert` 命令迁移至 `src/mark2pdf/commands/convert.py` [2026-01-06]
  - 减少 `cli.py` 复杂度，从 345 行减少到约 60 行

## 0.7.27 run_pandoc_typst 重构

- **测试加固**：新增 9 个测试用例覆盖边界情况
  - 目录式模板子目录复制、隐藏文件跳过
  - 命令构建验证（模板参数、kwargs转换、字体路径）
  - 执行失败处理（非零退出码、输出文件不存在）
  - 清理行为（成功清理、失败保留）
- **函数拆分**：将 196 行单体函数拆分为职责单一的子函数
  - `_copy_template_to_workdir`：模板复制（62行）
  - `_build_pandoc_command`：命令构建（39行）
  - `_execute_pandoc`：执行验证（49行）
  - `_cleanup_template_files`：清理（20行）
  - `run_pandoc_typst` 主函数：流程协调（56行）
- **接口保持不变**：对外 API 无任何改动

## 0.7.31 CLI 禁用封面/目录支持

- **新增 CLI 选项**：
  - `--no-cover`：禁用封面生成
  - `--no-toc`：禁用目录生成
- **核心改动**：
  - `_add_pandoc_arguments`：支持 list/tuple 值展开为多个 `-V` 参数
  - `ConversionOptions`：新增 `no_cover`、`no_toc` 字段
  - `execute_in_sandbox`：构建 `disables` 列表传递给 pandoc
- **数据流**：CLI → dispatch → run_*_conversion → ConversionOptions → core → pandoc (`-V disables=cover -V disables=toc`)
- **测试**：新增 3 个 TDD 测试用例验证列表参数展开功能


## 0.7.33 PDF 压缩集成

- **功能集成**：
  - 将 `compress` 逻辑从命令层下沉至 `core/compress.py`，实现复用
  - `convert` 命令新增 `--compress/--no-compress` 选项（默认开启）
  - 转换完成后自动对 PDF 进行压缩（大于 1MB 的 PNG 转 JPEG）
- **代码重构**：
  - 清理了 `conversion.py` 中因之前的修改导致的大量参数重复（BatchConfig, ConversionOptions 等）
  - 优化了 `test_output_format.py`，增加对 `compress_pdf` 的 Mock 防止文件不存在错误
- **兼容性**：
  - 保留独立的 `compress` 命令，底层调用共享的 core 逻辑

## 0.7.35 文档重构与工作区简化 (2026-01-24)

- **文档体系重构**
  - **文件重命名**：`docs/` 下文件添加数字前缀 (`00.` - `07.`)，确立明确阅读顺序。
  - **内容更新**：全面更新 `项目说明文档`、`快速开始`、`工作区指南`，由 `mark2pdf` 统一为 `yakultpdf` CLI。
  - **安装推荐**：更改为推荐 `uv tool install yakultpdf`。

- **工作区结构简化**
  - **默认路径变更**：`yakultpdf init` 不再创建 `in/` 子目录，默认 `input = "."`。
  - **配置更新**：`mark2pdf.config.toml` 生成逻辑适配新结构。
  - **体验优化**：降低了初学者上手门槛，支持单文件直接在根目录管理。

- **CLI 名称统一**
  - 确认并统一文档中所有命令引用为 `yakultpdf`，与 PyPI 包及 `entry_points` 保持一致。
