# 更新日志

K2F 参考引擎、`k2f` CLI、Python 与 JavaScript SDK、MCP 服务器、桌面阅读器以及导出工具的发布历史。

- **包版本**遵循[语义化版本](https://semver.org/)。带标签的构建与产物：[GitHub Releases](https://github.com/suzheng/k2f/releases)。
- **格式契约**为 [Spec 0.3](docs/spec/k2f-v0.3.md)。补丁版本通常保持该文件名；关于编译后 lock 上的 `engine_version` 与规范的关系，见[兼容性](COMPATIBILITY.md)。
- **安装：** `pip install k2f` · `cargo install k2f` · `npm i @openk2f/k2f`

条目遵循 [Keep a Changelog](https://keepachangelog.com/)。

## [未发布][Unreleased]

### 新增

- 规范 [EBNF 附录](docs/spec/k2f-v0.3.ebnf)，涵盖包路径、语义节点骨架和主题大纲（JSON Schema 仍是字段契约）。
- `schema/schemastore/` 下的 SchemaStore 导出，以及供 IDE 目录提交的[生态指南](docs/ecosystem/schemastore.md)。

## [0.3.3] - 2026-10-15

### 新增

- 当文本或子盒子绘制超出固定单元格或 `{fr}` 单元格、被钳制的 stack 或 `columns` 时，编译会给出 `CONTENT_OVERFLOW` 警告。仅为警告——打包仍然成功。当同族的 Bold/Italic 字体文件已嵌入但未被选中、粗体/斜体仍为合成时，`FONT_SYNTHETIC` 会给出警告。

### 修复

- `init_package.py --font` 会删除被替换字族的许可证文件，并在新字体带有同目录的 `OFL.txt` / `LICENSE` 时一并复制。`--font` / `--add-font` 会为 `-Regular` 旁边的同族 `-Bold` / `-Italic` / `-BoldItalic` 文件名填充 `font_faces`。
- SVG 图像按目标像素尺寸栅格化（查看器的绘制缩放比例；对 PDF、DOCX、PPTX 和 IDML 而言为图像盒每 pt 4 px），而不是按 SVG 文件自身的像素尺寸用最近邻放大。Lock 哈希不变；重新打开或重新导出即可获得更锐利的线条。

## [0.3.2] - 2026-09-28

### 新增

- **桌面阅读器：** 应用内编辑、文件重新加载/监视、弹出层外观、表单填写、丢弃/保存流程以及布局修复。打包的预览构建仍位于 [k2f.dev/download](https://k2f.dev/download)。
- **PDF 导出：** 对模糊、阴影、渐变和半透明填充采用效果切片栅格化（缩放 2–4；默认 4）。无效果的页面仍保持矢量轮廓，文本渲染模式为 3。

### 变更

- **项目状态**文档：桌面阅读器列在 Preview 下；签名/公证仍在路线图中。

## [0.3.1] - 2026-09-19

### 修复

- **`export-docx` / `export-pptx`：** 将已发布的 lock 绘制到 Word、LibreOffice Writer、PowerPoint 和 LibreOffice Impress 时的保真度修复——列表（项目符号、编号、换行缩进）、折叠卡片外壳与 z 顺序、表格单元格内边距与框线、字体嵌入（包括 CJK 和仅粗体字面）、渐变与透明度、文本换行与对齐、表单复选框以及行距。Office 文件仍然是对 lock 的单向绘制（`DOCX_IS_NOT_A_SOURCE`、`PPTX_IS_NOT_A_SOURCE`）。
- **`export-idml`：** 针对 InDesign 的保真度修复——原生表格与 DrawBox 回退、排版（伪粗体、图旁多行标题）、线性渐变与半透明填充（process RGB / `WebIntent`）以及相关布局边界情况。IDML 不是 K2F 源（`IDML_IS_NOT_A_SOURCE`）。

## [0.3.0] - 2026-09-18

### 新增

- 格式规范 **[0.3](docs/spec/k2f-v0.3.md)**——当前磁盘上的 ZIP 布局、schema 和 lock 契约（与 0.3.x SDK 系列对齐）。
- 打包/编译/栅格化会以 `SVG_TEXT`（而非 `IMAGE_SIZE`）拒绝 SVG 实时文本。仍然是失败关闭（fail-closed）；请将标签放入 K2F 文本节点或转换为 `<path>`。
- 列表标记和代码块使用与正文相同的包内字体覆盖回退。
- 技能目录：OFL 的 `NotoSerif-Regular.ttf` 用于衬线标题或正文（`--add-font catalog/assets/fonts/NotoSerif-Regular.ttf`，然后重定向角色的 `font_family`）。起始包仍仅含 Roboto；没有跨字族回退。
- `k2f export-idml <package> -o <out-dir>`——InDesign 包（`{stem}.idml` + `Document Fonts/`）。`-o file.zip` 写出同样的目录树并压缩；`--idml-only` 只写出一个 `.idml`。IDML ZIP 仍不包含 TTF 字节。IDML 不是 K2F 源（`IDML_IS_NOT_A_SOURCE`）。
- 角色/变体的 `image_fit`（默认 `contain`，或 `cover` 居中裁剪）。图像节点自身的 `corner_radius` 会裁剪该位图。PPTX/DOCX 输出 `a:srcRect` + `roundRect`；IDML 使用 FillProportionally + 框架圆角。

### 变更

- `grid` / `overlay` / `columns` / 水平 `stack` 的根 `layout` 是编译错误（此前对水平方向会静默回退为垂直流）。请嵌套在子节点下。目录中的 `ex_*.json` 都是子节点——不要替换 `content/root.json`。

### 修复

- `export-docx` / `export-pptx`：已应用主题 `emphasis`（包括 `emphasis` → 斜体）的 lock 绘制不会被重新映射为粗体。此前将每个非 `italic` 意图都叠加为粗体，导致真正的斜体文本段导出为粗斜体。空绘制的回退仍会将默认 emphasis 加粗。
- 带有部分 `list_style`（例如只有 `bullet_glyph`）的 `list_item` 会合并起始默认值后编译。显式的 `0` 仍然优先；schema 字段保持可选。

## [0.2.4] - 2026-09-11

### 新增

- 桌面阅读器：带显示 LOD 的连续捏合 / Ctrl+滚轮缩放、全部复制为文本，以及 macOS 菜单勾选标记。
- Web 查看器：与桌面阅读器对齐的显示缩放 LOD 辅助函数。

### 修复

- **`export-docx` / `export-pptx`：** 将已发布的 lock 绘制到 Word、LibreOffice Writer、PowerPoint 和 LibreOffice Impress 时的多项保真度修复——横幅上的主标题、卡片折叠与堆叠、列表项目符号与编号、表格行与部分边缘框线、深色模式纸张底色、字体嵌入与字距、换行与对齐、渐变与半透明、带 `{{page_*}}` 字段的页眉、表单复选框，以及相对于图像的 z 顺序。导出仍然是对 lock 的单向绘制。

## [0.2.3] - 2026-09-09

### 修复

- 使已发布的 Rust（`k2f`、`k2f_sdk`）、Python（`k2f`）和 npm（`@openk2f/k2f`）与 0.2.2 之后在 `main` 上发布的模板打包移除保持一致（crates.io 和 PyPI 上的 0.2.2 仍暴露具名模板 API）。

## [0.2.2] - 2026-09-09

### 新增

- `init_package.py` 页面预设 `square`（1:1，600pt）、`portrait-45`（4:5）和 `card`（美制 3.5×2"，252×144pt），默认边距 0。与幻灯片相同的分页 `ex_poster_shell`；将 `layout.height` 设为页面高度。双面卡片：两个外壳，背面 `break_before: page`，`--expect-pages 2`。
- 当页面内容盒底部空白 ≥25% 时（多页流的最后一页除外），编译会给出 `PAGE_UNDERFILL` 诊断。仅为警告——`pack_verify.py` 不会失败。目录示例 [`ex_filled_page.json`](skills/core/k2f/catalog/content/ex_filled_page.json)。`--render` 还会为额外页面写出 `preview-N.png`。

### 变更

- `k2f pack`、`k2f compile` 和 `Editor.save_bytes` 会将包内的大型 CJK 字面按覆盖范围取子集：GB2312 ∪ Big5 一级 ∪ JIS X 0208 汉字，外加所有非汉字字形。作者目录保留原始字面。不会丢弃任何汉字的字面保持字节完全一致。缺失汉字仍然失败关闭（`FONT_MISSING_GLYPH`）。
- 智能体技能：发票/简历/传单/海报是组合式填充页面（在这些场景中 `PAGE_UNDERFILL` = 必须修复）。合同/报告/论文是一棵流式树——没有 `p1`/`p2` 页面容器；允许在章节/附件/签名上使用 `break_before`。`LAYOUT_SLACK` 仍仅为警告。
- 除 `default` 之外的主题角色可以省略 `font_family` / `font_size` / `line_height_mult` / `color`；编译时会从 `default` 填充。`default` 仍要求全部四项。整页填充仍由根角色的 `box_decoration.background` 决定（整页，包括边距）——而不是 `page_config.background`。
- `LAYOUT_SLACK` / `PAGE_UNDERFILL` 会跳过微型页面（内容盒短于 180pt）和小于 36pt 的未使用间隙，因此卡片内缩不会被当作空心增长器。A4 / 16:9 的增长器保持不变。
- `FONT_MISSING_GLYPH` 会指出未覆盖的码点，并提示作者用 `--add-font` 添加覆盖这些码点的 TTF/OTF（仍然失败关闭；没有操作系统回退）。包内嵌入的字面之间已经可以相互回退。

### 修复

- 会溢出可用轴的网格 `{auto:true}` 轨道现在按比例收缩，而不是与相邻列/行重叠。较短的自动内容仍然贴合；剩余空间仍分配给 `fr`。两个轴上的规则相同。
- `grid` / `overlay` / `columns` 的根 `layout` 是编译错误（此前会静默回退为垂直流）。请嵌套在子节点下，例如 `root.grid`。
- 线性渐变绘制在色标颜色无法解析时失败关闭（不会静默变成单色标 / 空填充）。`angle_degrees` 中 0=向右，90=向下——已在图元 schema 和技能填充说明中记录（不是 CSS）。
- SVG `<text>` 的拒绝消息会提示智能体去掉这些标签并使用 K2F 文本节点（或 `<path>`），与技能错误表一致。
- 四边盒子边框在 PNG/查看器（以及虚线/点线 PDF）中遵循 `corner_radius`，与填充/阴影一致。部分边缘的边框保持直线。
- **`export-docx` / `export-pptx`：** Office 主题颜色固定为 lock 的 sRGB；Word 避免使用原生 `w:tbl`（深色模式会反转 `w:shd`）；表格单元格绘制为与页面其余部分相同的盒子 + 文本。**`export-docx`：** 渐变、玻璃效果和重叠图像使用原生 DrawingML / `behindDoc` 堆叠，以免 LibreOffice Writer 将标签隐藏在整页栅格图之后。

### 移除

- 从每个已发布的 SDK 中移除具名官方模板（`official_templates`、`copy_template`、`resolve_template`、`Editor.open_template` / `openTemplate`）。WASM 不再 `include_dir` `k2f/templates/`。请使用 `init_package.py` / 解包 / Gallery 创建，然后 `Editor.open_dir` 或 `Editor.open` / `open_bytes`。CLI 的 `k2f markdown --template` 需要一个作者目录。JS 的 `markdownToK2f` 接受 `templateBytes`。

## [0.2.1] - 2026-09-07

### 修复

- npm `@openk2f/k2f` 0.2.0 将仅查看器版 WASM 作为 SDK 二进制发布（`wasm/` 与 `wasm-viewer/` 文件完全相同），导致 `markdown_to_k2f` 和 `Editor` 缺失。SDK 与仅查看器构建现在使用各自独立的 cargo target 目录。

## [0.2.0] - 2026-09-07

### 新增

- 智能体技能**设计优先工作流**——在编写 K2F JSON 之前先写一份设计规范 Markdown；依据规范实现 `theme.json` + 内容，然后渲染并迭代，直到输出符合预期。
- `k2f export-pptx <package> -o <out.pptx>`——将已发布的 lock 绘制到 PowerPoint。它不是第二个布局引擎；预期会有轻微文本重排。PPTX 不是 K2F 源（`PPTX_IS_NOT_A_SOURCE`）。
- `k2f export-docx <package> -o <out.docx>`——将已发布的 lock 绘制到 Word。它不是第二个布局引擎；预期会有轻微文本重排。DOCX 不是 K2F 源（`DOCX_IS_NOT_A_SOURCE`）。
- 桌面阅读器：HUD 格式 **DOCX** 和 `k2f-reader --export-docx out.docx file.K2F`（与 GUI 导出相同的 lock 字节；与 `--export-pdf` / `--export-pptx` 冲突）。
- 当大型拉伸盒子底部为空时，`k2f compile` 会打印 `LAYOUT_SLACK`——通常是 `{fr:1}` 增长器与自动高度 stack 一起打包所致，而不是页面外壳（警告，退出码 0，lock 不变）。
- 网格轨道 `{ "auto": true }`——根据测量到的单元格内容确定尺寸；剩余空间分配给 `fr`。表格的 `column_widths` 仍只支持 `{pt}` / `{fr}`。
- 可选的网格 `rows`：省略时 → `{auto:true}` 轨道数为 `ceil(n_children / n_columns)`。声明的行不会增长。`fr` 行仍需要有限的外部高度。
- 目录示例 [`ex_glass.json`](skills/core/k2f/catalog/content/ex_glass.json)——`card` 变体 `glass`，通过具名 `box_decoration.blur` 和半透明表面实现（不是径向渐变）。
- 换行：连字符减号和 U+00AD 是可断行位置（连字符保留在行尾）。仍然宽于行的单词会按字符拆分。没有断词词典，也没有自动缩小。

### 变更

- 字体加载/渲染只解析 `.ttf`/`.otf`。`assets/fonts/` 下的许可证/附属文件仍保留在 ZIP 和 `Package.fonts` 中（外观哈希不变），但在 `Face::parse` 时会被跳过。无效字面会报告 `FONT_INVALID` 并附带路径，而不是 `UnknownMagic`。自动 `default` 和“至少一个字体”只统计字面。PDF/DOCX/PPTX 导出应用相同的字面路径过滤（不会将许可证 `.txt` 作为字体嵌入或解析）。
- SVG `<text>` / `<tspan>` / `<textPath>` / `<foreignObject>` 检测会先剥离 XML 注释和 CDATA，再匹配真实元素。打包和编译会拒绝它们（`IMAGE_SIZE`）；绘制仍然失败关闭。智能体技能写作规则 4 在写作循环关卡处也作了同样说明。
- 智能体技能：流式文章使用**一个**无内边距的 `columns` 容器，并设置 `column_span: all`（不要在图注上使用 `break_before: page`）。变体文本字段仍放在 `text_overrides` 下。紧凑表格：加宽列、降低角色的 `font_size`，或插入 U+00AD。
- 智能体技能：海报/幻灯片页面外壳是一个固定高度的 **grid**，带有 `{auto:true}` 的页眉/页脚和一个 `{fr:1}` 增长器（[`ex_poster_shell.json`](skills/core/k2f/catalog/content/ex_poster_shell.json)）；用嵌套的 `{fr:1}` 行填充该增长器（[`ex_poster_growers.json`](skills/core/k2f/catalog/content/ex_poster_growers.json)），而不是自动高度的 stack。当页面剩余空间太小时，零内边距的垂直 stack 会按子节点拆分。
- **`export-docx` / `export-pptx`：** 首轮重要的 Office 导出——锁定字体与字距、深色模式安全的主题颜色与文本框底衬、卡片折叠、换行/对齐启发式、超链接、表格行高与边框、为 LibreOffice 在正文中放置的页眉，以及相关的 DrawingML 修复。仍预期宿主会有轻微重排；导出不是源。

### 移除

- 智能体技能 **`looks/`**——移除了内置设计皮肤（`quiet-light`、`vivid-blocks`、`night-wash`）和 `verify_looks.py`；样式改为依据设计规范编写

## [0.1.2] - 2026-08-30

### 新增

- **`pip install k2f` 自带 CLI**——`k2f` 控制台脚本位于 PATH（pack、compile、verify、render、export-pdf、markdown）；智能体不再需要 `cargo install k2f`

### 变更

- 智能体技能安装指引：**优先使用 `pip install k2f`**；`cargo install k2f` 仅在纯 Rust 环境中可选

## [0.1.1] - 2026-08-30

### 新增

- 智能体技能 **`looks/`**——三个示例设计皮肤（`quiet-light`、`vivid-blocks`、`night-wash`）：完整的 `theme.json`、构图指南以及共享扩展角色（`display`、`kicker`、`caption`、`metric`、`shell`）。当用户未指定风格时，智能体会依据这些示例重写包主题。
- 用于 manifest 运行块的 `Editor.set_running_header` / `set_running_footer`

### 变更

- 将六个智能体技能统一为一个 `skills/core/k2f/` 技能，并附带工作流参考（writing、converting-markdown、exporting-pdf、publishing、embedding-viewer）
- 智能体技能：将 **generating** 和 **editing** 合并为单一的 **writing** 工作流（JSON + `k2f unpack` / `pack_verify.py`）；可选的 Python `Editor` 移至 `references/writing/sdk.md`
- 公开创建路径为 `Editor.open_template` / `open_dir` / `open_bytes` 加上 `insert_node` JSON（在 0.2.2 中已被取代——请使用 `init_package.py` / Gallery / 解包）

### 移除

- 公开的 `Composer` / `Document` 构建器（`add_heading`、`add_body`、`add_warning`、`add_table`）

## [0.1.0] - 2026-08-28

### 新增

- K2F 格式规范 v0.1（ZIP 包、语义树、主题、编译后的 lock）——已被 [Spec 0.3](docs/spec/k2f-v0.3.md) 取代
- 参考引擎：布局、绘制、PDF 导出、包校验、Ed25519 签名
- CLI（`k2f`）——pack、compile、verify、sign、render、export-pdf、markdown
- Python SDK（`pip install k2f`）——Document、Editor、Markdown 桥接
- JavaScript / WASM SDK（`npm i @openk2f/k2f`）——Document、Editor、`<k2f-viewer>` Web 组件
- MCP stdio 服务器（`k2f_mcp`），工具目录位于 `mcp_tools.json`
- `skills/` 下的六个智能体技能（后来统一；见 0.1.1）
- `docs/` 下的公开文档以及 [SECURITY.md](SECURITY.md) 中的完整性策略

[Unreleased]: https://github.com/suzheng/k2f/compare/v0.3.1...HEAD
[0.3.1]: https://github.com/suzheng/k2f/releases/tag/v0.3.1
[0.3.0]: https://github.com/suzheng/k2f/releases/tag/v0.3.0
[0.2.4]: https://github.com/suzheng/k2f/releases/tag/v0.2.4
[0.2.3]: https://github.com/suzheng/k2f/releases/tag/v0.2.3
[0.2.2]: https://github.com/suzheng/k2f/releases/tag/v0.2.2
[0.2.1]: https://github.com/suzheng/k2f/releases/tag/v0.2.1
[0.2.0]: https://github.com/suzheng/k2f/releases/tag/v0.2.0
[0.1.2]: https://github.com/suzheng/k2f/releases/tag/v0.1.2
[0.1.1]: https://github.com/suzheng/k2f/releases/tag/v0.1.1
[0.1.0]: https://github.com/suzheng/k2f/releases/tag/v0.1.0
