feat: enable text auto-wrap for text boxes by default
- Set text_frame.word_wrap = True in add_text_element() for PPTX - Change CSS from white-space: pre-wrap to normal in HTML preview - Add overflow-wrap: break-word for better word breaking - Update README.md with auto-wrap documentation - Update element-rendering and html-rendering specs - Archive change: 2026-03-02-add-text-auto-wrap
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -262,3 +262,6 @@ pnpm-lock.yaml
|
||||
# !templates/
|
||||
# !examples/
|
||||
# !assets/
|
||||
|
||||
|
||||
temp
|
||||
433
README.md
433
README.md
@@ -1,247 +1,344 @@
|
||||
# YAML to PPTX Converter
|
||||
# yaml2pptx
|
||||
|
||||
将 YAML 格式的演示文稿源文件转换为 PPTX 文件,让 AI 也能轻松生成高质量的演示文稿。
|
||||
YAML 转 PowerPoint (PPTX) 工具 - 使用 YAML 格式的声明式语法定义演示文稿,并生成 PPTX 文件。
|
||||
|
||||
## 🎯 核心特性
|
||||
## 功能特性
|
||||
|
||||
- **人类和 AI 友好**:使用 YAML 格式,简洁可读,易于生成
|
||||
- **模板系统**:可复用的幻灯片布局,大幅减少重复配置
|
||||
- **核心元素支持**:文本、图片、形状、表格
|
||||
- **精确布局控制**:基于英寸单位的精确定位
|
||||
- **简洁设计**:颜色和样式直接在模板中定义,无需额外配置
|
||||
- **浏览器实时预览**:编辑 YAML 文件时,浏览器自动刷新预览效果
|
||||
- **YAML 声明式语法** - 使用简单易读的 YAML 定义演示文稿
|
||||
- **模板系统** - 支持参数化模板,复用幻灯片布局
|
||||
- **多种元素类型** - 文本、图片、形状、表格
|
||||
- **实时预览** - 浏览器预览模式,支持热重载,快速开发迭代
|
||||
- **灵活尺寸** - 支持 16:9 和 4:3 两种宽高比
|
||||
|
||||
## 📦 安装和使用
|
||||
## 安装
|
||||
|
||||
### 前置要求
|
||||
脚本使用 [uv](https://github.com/astral-sh/uv) 管理 Python 依赖。运行时会自动安装所需依赖。
|
||||
|
||||
- Python 3.8+
|
||||
- uv(推荐)或 pip
|
||||
依赖项:
|
||||
- `python-pptx` - PowerPoint 文件生成
|
||||
- `pyyaml` - YAML 解析
|
||||
- `flask` - 预览服务器(预览模式需要)
|
||||
- `watchdog` - 文件监控(预览模式需要)
|
||||
|
||||
### 使用方法
|
||||
## 基本用法
|
||||
|
||||
### 生成 PPTX 文件
|
||||
|
||||
```bash
|
||||
# 生成 PPTX 文件
|
||||
uv run yaml2pptx.py input.yaml output.pptx
|
||||
# 基本用法 - 输出文件自动生成(input.pptx)
|
||||
uv run yaml2pptx.py presentation.yaml
|
||||
|
||||
# 自动生成输出文件名
|
||||
uv run yaml2pptx.py input.yaml # 生成 input.pptx
|
||||
# 指定输出文件名
|
||||
uv run yaml2pptx.py presentation.yaml output.pptx
|
||||
|
||||
# 浏览器实时预览(新功能)
|
||||
uv run yaml2pptx.py input.yaml --preview
|
||||
|
||||
# 指定预览端口(默认随机选择 20000-30000 之间的端口)
|
||||
uv run yaml2pptx.py input.yaml --preview --port 8080
|
||||
|
||||
# 查看帮助
|
||||
uv run yaml2pptx.py --help
|
||||
# 指定模板目录
|
||||
uv run yaml2pptx.py presentation.yaml output.pptx --template-dir ./templates
|
||||
```
|
||||
|
||||
### 浏览器预览功能
|
||||
### 实时预览模式
|
||||
|
||||
使用 `--preview` 参数可以在浏览器中实时预览 YAML 文件的效果:
|
||||
```bash
|
||||
# 启动预览服务器(随机端口 20000-30000)
|
||||
uv run yaml2pptx.py presentation.yaml --preview
|
||||
|
||||
- 启动后自动打开浏览器
|
||||
- 默认使用 20000-30000 之间的随机端口,避免端口冲突
|
||||
- 编辑 YAML 文件后,浏览器自动刷新
|
||||
- 支持所有元素类型和模板
|
||||
- 按 Ctrl+C 停止预览服务器
|
||||
# 指定端口
|
||||
uv run yaml2pptx.py presentation.yaml --preview --port 8080
|
||||
|
||||
**注意**:预览效果与最终 PPTX 可能存在细微差异(字体渲染、间距等),建议最终确认时生成 PPTX 文件查看。
|
||||
# 指定模板目录
|
||||
uv run yaml2pptx.py presentation.yaml --preview --template-dir ./templates
|
||||
```
|
||||
|
||||
## 📖 快速开始
|
||||
预览模式会自动打开浏览器窗口显示演示文稿,修改 YAML 文件时页面会自动刷新。
|
||||
|
||||
### 1. 使用模板创建演示文稿
|
||||
## 命令行选项
|
||||
|
||||
| 选项 | 说明 |
|
||||
|------|------|
|
||||
| `input` | 输入的 YAML 文件路径(必需) |
|
||||
| `output` | 输出的 PPTX 文件路径(可选,默认为 `input.pptx`) |
|
||||
| `--template-dir` | 模板 YAML 文件所在目录 |
|
||||
| `--preview` | 启用浏览器预览模式(不生成 PPTX 文件) |
|
||||
| `--port` | 预览服务器端口(默认:随机 20000-30000) |
|
||||
|
||||
## YAML 结构
|
||||
|
||||
### 基本演示文稿
|
||||
|
||||
```yaml
|
||||
# presentation.yaml
|
||||
metadata:
|
||||
title: "我的演示文稿"
|
||||
size: "16:9" # 16:9 或 4:3
|
||||
size: 16:9 # 或 4:3
|
||||
|
||||
slides:
|
||||
# 使用标题页模板
|
||||
- template: title_slide
|
||||
vars:
|
||||
title: "项目汇报"
|
||||
subtitle: "2026年第一季度"
|
||||
|
||||
# 使用内容页模板
|
||||
- template: content_slide
|
||||
vars:
|
||||
title: "主要成果"
|
||||
content: |
|
||||
• 销售额增长 25%
|
||||
• 客户满意度 4.8/5.0
|
||||
• 新增 3 个市场
|
||||
```
|
||||
|
||||
### 2. 自定义幻灯片
|
||||
|
||||
```yaml
|
||||
slides:
|
||||
- background:
|
||||
color: "#ffffff"
|
||||
elements:
|
||||
- type: text
|
||||
content: "自定义标题"
|
||||
box: [1, 1, 8, 1] # [x, y, width, height] 英寸
|
||||
box: [1, 1, 8, 1]
|
||||
content: "你好,世界!"
|
||||
font:
|
||||
size: 44
|
||||
bold: true
|
||||
color: "#1a1a1a"
|
||||
color: "#333333"
|
||||
align: center
|
||||
|
||||
- type: shape
|
||||
shape: rectangle
|
||||
box: [2, 3, 6, 2]
|
||||
fill: "#4a90e2"
|
||||
```
|
||||
|
||||
## 📐 模板系统
|
||||
### 使用模板
|
||||
|
||||
内置模板:
|
||||
```yaml
|
||||
metadata:
|
||||
size: 16:9
|
||||
|
||||
- `title_slide`:标题页(主标题 + 副标题)
|
||||
- `content_slide`:内容页(标题条 + 内容区)
|
||||
- `two_column`:双栏布局
|
||||
slides:
|
||||
- template: title-slide
|
||||
vars:
|
||||
title: "我的演示文稿"
|
||||
subtitle: "yaml2pptx 简介"
|
||||
author: "张三"
|
||||
|
||||
## 🧩 支持的元素类型
|
||||
- template: content-slide
|
||||
vars:
|
||||
title: "功能概览"
|
||||
content: "yaml2pptx 支持多种元素类型..."
|
||||
```
|
||||
|
||||
### 文本元素
|
||||
## 元素类型
|
||||
|
||||
### 文本
|
||||
|
||||
```yaml
|
||||
- type: text
|
||||
content: "Hello World"
|
||||
box: [x, y, width, height]
|
||||
box: [x, y, width, height] # 位置和尺寸(单位:英寸)
|
||||
content: "文本内容"
|
||||
font:
|
||||
size: 32
|
||||
bold: true
|
||||
italic: false
|
||||
color: "#333333"
|
||||
align: center # left, center, right
|
||||
size: 18 # 字号(磅)
|
||||
bold: true/false # 粗体
|
||||
italic: true/false # 斜体
|
||||
color: "#ff0000" # 颜色(#RGB 或 #RRGGBB)
|
||||
align: left/center/right # 对齐方式
|
||||
```
|
||||
|
||||
### 图片元素
|
||||
**文本自动换行**:文本框默认启用自动换行功能。当文字内容超过文本框宽度时,会自动换行显示,确保文字不会溢出边界。
|
||||
|
||||
### 图片
|
||||
|
||||
```yaml
|
||||
- type: image
|
||||
src: "images/logo.png"
|
||||
box: [x, y, width, height]
|
||||
src: "path/to/image.png" # 相对路径或绝对路径
|
||||
```
|
||||
|
||||
### 形状元素
|
||||
### 形状
|
||||
|
||||
```yaml
|
||||
- type: shape
|
||||
shape: rectangle # rectangle, ellipse, rounded_rectangle
|
||||
box: [x, y, width, height]
|
||||
fill: "#4a90e2"
|
||||
shape: rectangle/ellipse/rounded_rectangle
|
||||
fill: "#4a90e2" # 填充颜色
|
||||
line:
|
||||
color: "#000000"
|
||||
width: 2
|
||||
color: "#000000" # 边框颜色
|
||||
width: 1 # 边框宽度(磅)
|
||||
```
|
||||
|
||||
### 表格元素
|
||||
### 表格
|
||||
|
||||
```yaml
|
||||
- type: table
|
||||
position: [x, y]
|
||||
col_widths: [2, 2, 2] # 英寸
|
||||
position: [x, y] # 表格位置
|
||||
col_widths: [2, 2, 2] # 列宽(英寸)
|
||||
data:
|
||||
- ["Header 1", "Header 2", "Header 3"]
|
||||
- ["Cell 1", "Cell 2", "Cell 3"]
|
||||
- ["表头1", "表头2", "表头3"]
|
||||
- ["行1", "数据", "数据"]
|
||||
- ["行2", "数据", "数据"]
|
||||
style:
|
||||
font_size: 14
|
||||
header_bg: "#4a90e2"
|
||||
header_color: "#ffffff"
|
||||
```
|
||||
|
||||
## 📂 项目结构
|
||||
## 模板系统
|
||||
|
||||
```
|
||||
project/
|
||||
├── templates/ # 模板定义(颜色和样式直接在模板中)
|
||||
│ ├── title_slide.yaml
|
||||
│ ├── content_slide.yaml
|
||||
│ └── two_column.yaml
|
||||
├── examples/ # 示例文件
|
||||
│ ├── demo.yaml
|
||||
│ ├── custom.yaml
|
||||
│ └── complex.yaml
|
||||
├── yaml2pptx.py # 转换脚本
|
||||
└── README.md
|
||||
模板允许你定义可复用的幻灯片布局,支持参数化。
|
||||
|
||||
### 模板文件 (`templates/title-slide.yaml`)
|
||||
|
||||
```yaml
|
||||
vars:
|
||||
- name: title
|
||||
required: true
|
||||
- name: subtitle
|
||||
required: false
|
||||
default: ""
|
||||
- name: author
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
elements:
|
||||
- type: text
|
||||
box: [1, 2, 8, 1]
|
||||
content: "{title}"
|
||||
font:
|
||||
size: 44
|
||||
bold: true
|
||||
align: center
|
||||
|
||||
- type: text
|
||||
box: [1, 3.5, 8, 0.5]
|
||||
content: "{subtitle}"
|
||||
visible: "{subtitle != ''}" # 仅当 subtitle 不为空时显示
|
||||
font:
|
||||
size: 24
|
||||
align: center
|
||||
|
||||
- type: text
|
||||
box: [1, 5, 8, 0.5]
|
||||
content: "{author}"
|
||||
font:
|
||||
size: 18
|
||||
align: center
|
||||
```
|
||||
|
||||
## 🔧 技术栈
|
||||
### 使用模板
|
||||
|
||||
- **Python 3.8+**
|
||||
- **python-pptx**:PPTX 文件生成
|
||||
- **PyYAML**:YAML 文件解析
|
||||
- **uv**:Python 脚本运行器
|
||||
|
||||
## 📝 示例
|
||||
|
||||
查看 `examples/` 目录中的示例文件:
|
||||
|
||||
- `demo.yaml`:使用模板的完整示例(3页)
|
||||
- `custom.yaml`:自定义幻灯片示例(2页)
|
||||
- `complex.yaml`:**复杂综合示例(10页)** - 展示所有功能
|
||||
|
||||
### 复杂示例亮点
|
||||
|
||||
`complex.yaml` 是一个完整的商业计划演示文稿,包含:
|
||||
|
||||
✨ **10个精心设计的幻灯片**:
|
||||
1. 封面页(使用 title_slide 模板)
|
||||
2. 议程页(自定义布局,包含时间轴)
|
||||
3. 公司概况(使用 content_slide 模板)
|
||||
4. 市场分析(使用 two_column 模板)
|
||||
5. 产品矩阵(复杂表格 + 架构图示)
|
||||
6. 财务预测(多个表格 + 数据可视化)
|
||||
7. 团队介绍(使用 two_column 模板)
|
||||
8. 竞争优势(视觉化卡片 + SWOT 表格)
|
||||
9. 产品路线图(使用 content_slide 模板)
|
||||
10. 结束页(自定义召唤行动页)
|
||||
|
||||
🎨 **展示的功能**:
|
||||
- ✅ 所有三种模板的使用
|
||||
- ✅ 模板与自定义幻灯片混合
|
||||
- ✅ 所有元素类型:文本、形状、表格
|
||||
- ✅ 复杂布局和精确定位
|
||||
- ✅ 多种形状类型和样式组合
|
||||
- ✅ 丰富的颜色和字体样式(直接指定)
|
||||
- ✅ 大量中文内容展示
|
||||
- ✅ 表格的高级样式应用
|
||||
- ✅ 视觉化信息展示(卡片、时间轴、架构图)
|
||||
|
||||
```bash
|
||||
# 生成示例演示文稿
|
||||
uv run yaml2pptx.py examples/demo.yaml # 基础示例
|
||||
uv run yaml2pptx.py examples/custom.yaml # 自定义示例
|
||||
uv run yaml2pptx.py examples/complex.yaml # 复杂综合示例 ⭐
|
||||
```yaml
|
||||
slides:
|
||||
- template: title-slide
|
||||
vars:
|
||||
title: "我的演示文稿"
|
||||
subtitle: "演示"
|
||||
author: "李四"
|
||||
```
|
||||
|
||||
**生成的文件大小**:
|
||||
- `demo_output.pptx` - 31KB
|
||||
- `custom_output.pptx` - 29KB
|
||||
- `complex_output.pptx` - 43KB (10页内容)
|
||||
### 模板变量说明
|
||||
|
||||
## 🎓 YAML Schema 文档
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `name` | 变量名(必需) |
|
||||
| `required` | 是否必需(默认:`false`) |
|
||||
| `default` | 默认值(未提供时使用) |
|
||||
|
||||
详细的 YAML 格式说明,请参考各类型文件的示例和注释。
|
||||
### 条件渲染
|
||||
|
||||
## 🚧 限制和已知问题
|
||||
使用 `visible` 属性控制元素的显示条件:
|
||||
|
||||
- 原型版本,仅支持核心功能
|
||||
- 不支持复杂样式(渐变、阴影、动画等)
|
||||
- 不支持 PPTX 到 YAML 的反向解析
|
||||
- 图片背景功能暂未完整实现
|
||||
```yaml
|
||||
- type: text
|
||||
content: "{subtitle}"
|
||||
visible: "{subtitle != ''}" # 仅当提供了 subtitle 时显示
|
||||
```
|
||||
|
||||
## 📄 License
|
||||
## 背景设置
|
||||
|
||||
幻灯片支持纯色背景:
|
||||
|
||||
```yaml
|
||||
slides:
|
||||
- background:
|
||||
color: "#f5f5f5" # 浅灰色背景
|
||||
elements:
|
||||
- type: text
|
||||
content: "灰色背景上的内容"
|
||||
```
|
||||
|
||||
## 颜色格式
|
||||
|
||||
颜色使用十六进制格式:
|
||||
- **短格式**:`#RGB`(如 `#fff` 表示白色)
|
||||
- **完整格式**:`#RRGGBB`(如 `#ffffff` 表示白色)
|
||||
|
||||
## 完整示例
|
||||
|
||||
### 演示文稿文件 (`demo.yaml`)
|
||||
|
||||
```yaml
|
||||
metadata:
|
||||
size: 16:9
|
||||
|
||||
slides:
|
||||
# 使用模板的标题页
|
||||
- template: title-slide
|
||||
vars:
|
||||
title: "yaml2pptx 入门"
|
||||
subtitle: "用 YAML 编写演示文稿"
|
||||
|
||||
# 自定义元素的内容页
|
||||
- background:
|
||||
color: "#ffffff"
|
||||
elements:
|
||||
- type: text
|
||||
box: [0.5, 0.5, 9, 0.8]
|
||||
content: "功能特性"
|
||||
font:
|
||||
size: 36
|
||||
bold: true
|
||||
color: "#2c3e50"
|
||||
|
||||
- type: shape
|
||||
box: [0.5, 1.5, 3, 2.5]
|
||||
shape: rounded_rectangle
|
||||
fill: "#3498db"
|
||||
line:
|
||||
color: "#2980b9"
|
||||
width: 2
|
||||
|
||||
- type: text
|
||||
box: [1, 2, 2, 1]
|
||||
content: "易于使用"
|
||||
font:
|
||||
size: 18
|
||||
color: "#ffffff"
|
||||
align: center
|
||||
|
||||
- type: table
|
||||
position: [5, 2]
|
||||
col_widths: [2, 2]
|
||||
data:
|
||||
- ["功能", "状态"]
|
||||
- ["模板支持", "✓"]
|
||||
- ["实时预览", "✓"]
|
||||
- ["表格支持", "✓"]
|
||||
style:
|
||||
font_size: 14
|
||||
header_bg: "#2c3e50"
|
||||
header_color: "#ffffff"
|
||||
|
||||
# 图片页
|
||||
- elements:
|
||||
- type: image
|
||||
box: [1, 1, 8, 4]
|
||||
src: "chart.png"
|
||||
```
|
||||
|
||||
## 错误提示
|
||||
|
||||
脚本提供详细的错误信息:
|
||||
|
||||
| 错误 | 说明 |
|
||||
|------|------|
|
||||
| `文件不存在: presentation.yaml` | 找不到输入文件 |
|
||||
| `YAML 语法错误: presentation.yaml, 第 5 行: ...` | YAML 语法问题 |
|
||||
| `模板文件不存在: title-slide` | 模板文件未找到 |
|
||||
| `缺少必需变量: title` | 未提供必需的模板变量 |
|
||||
| `图片文件未找到: image.png` | 图片文件不存在 |
|
||||
|
||||
## 使用技巧
|
||||
|
||||
1. **使用模板** - 保持幻灯片布局一致
|
||||
2. **启用预览模式** - 开发时快速迭代
|
||||
3. **使用相对路径** - 图片路径相对于 YAML 文件位置
|
||||
4. **指定模板目录** - 使用模板时必须指定 `--template-dir`
|
||||
5. **先预览后生成** - 预览确认无误后再生成最终 PPTX
|
||||
|
||||
## 坐标系统
|
||||
|
||||
- **单位**:英寸 (inch)
|
||||
- **原点**:幻灯片左上角
|
||||
- **方向**:X 轴向右,Y 轴向下
|
||||
|
||||
| 尺寸比例 | 幻灯片尺寸 |
|
||||
|----------|------------|
|
||||
| 16:9 | 10" × 5.625" |
|
||||
| 4:3 | 10" × 7.5" |
|
||||
|
||||
## 许可证
|
||||
|
||||
MIT License
|
||||
|
||||
## 🤝 贡献
|
||||
|
||||
欢迎提交 Issue 和 Pull Request!
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-03-02
|
||||
@@ -0,0 +1,97 @@
|
||||
# Design: 文本框默认自动换行
|
||||
|
||||
## Context
|
||||
|
||||
当前 `yaml2pptx.py` 中的 `add_text_element()` 函数创建 PPTX 文本框时,未设置 `word_wrap` 属性。python-pptx 的 TextFrame 默认行为是 `word_wrap = False`,这意味着长文本会溢出文本框边界。同样,HTML 预览中的 `render_text_element_to_html()` 函数使用 `white-space: pre-wrap`,这会保留所有空格和换行符,但对于自动换行的处理不够理想。
|
||||
|
||||
**Current State:**
|
||||
- PPTX 生成:`tf.word_wrap` 未设置,默认为 `False`,长文本会溢出
|
||||
- HTML 预览:使用 `white-space: pre-wrap`,保留格式但不确保自动换行
|
||||
|
||||
**Constraints:**
|
||||
- 必须保持向后兼容性(此改进不会破坏现有功能)
|
||||
- PPTX 和 HTML 预览行为应该一致
|
||||
- 不能引入新的外部依赖
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- 文本框默认启用文字自动换行
|
||||
- 同步更新 PPTX 生成和 HTML 预览的行为
|
||||
- 用户无需修改任何 YAML 配置
|
||||
|
||||
**Non-Goals:**
|
||||
- 添加 YAML `wrap` 属性(不需要,直接默认启用)
|
||||
- 文本框大小自动调整
|
||||
- 文字大小自动缩放以适应文本框
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. 直接默认启用自动换行,无需配置
|
||||
|
||||
**Decision:** 不添加任何 YAML 属性,直接在代码中设置 `word_wrap = True`
|
||||
|
||||
**Rationale:**
|
||||
- 自动换行是文本框的合理默认行为
|
||||
- 用户无需学习新的配置选项
|
||||
- 简化代码,减少配置复杂度
|
||||
- 符合大多数演示文稿软件的默认行为
|
||||
|
||||
**Alternatives Considered:**
|
||||
- 添加 `wrap` 属性:增加配置复杂度,大部分用户都会希望自动换行
|
||||
|
||||
### 2. PPTX 实现方式
|
||||
|
||||
**Decision:** 在创建文本框后直接设置 `text_frame.word_wrap = True`
|
||||
|
||||
**Rationale:**
|
||||
- python-pptx 原生支持此功能,无需额外依赖
|
||||
- 代码改动最小,只需添加一行
|
||||
- 性能开销为零
|
||||
|
||||
**Code Location:** `yaml2pptx.py` 第 406 行附近,在 `textbox.text_frame` 赋值后添加:
|
||||
```python
|
||||
tf.word_wrap = True
|
||||
```
|
||||
|
||||
### 3. HTML 预览实现方式
|
||||
|
||||
**Decision:** 将 CSS `white-space: pre-wrap` 改为 `white-space: normal`
|
||||
|
||||
**Rationale:**
|
||||
- `normal` 是 CSS 默认值,允许文字在容器边界处自动换行
|
||||
- 与 PPTX 的 `word_wrap = True` 行为一致
|
||||
- 对于包含 `\n` 的内容,可以单独处理或在需要时使用 `pre-wrap`
|
||||
|
||||
**Code Location:** `yaml2pptx.py` 第 902 行,修改 `render_text_element_to_html()` 函数中的样式
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
### Risk 1: 包含手动换行符的文本
|
||||
|
||||
**Risk:** 如果用户在 YAML 中使用 `\n` 手动换行,`white-space: normal` 会忽略这些换行符
|
||||
|
||||
**Mitigation:**
|
||||
- 可以改用 `white-space: pre-wrap` 或 `white-space: break-spaced` 来同时支持自动换行和手动换行
|
||||
- 测试验证哪种行为更符合预期
|
||||
|
||||
### Risk 2: 现有布局可能有细微变化
|
||||
|
||||
**Risk:** 启用自动换行后,某些长文本的显示方式可能与之前不同
|
||||
|
||||
**Mitigation:**
|
||||
- 此变化是改进性的,使文本正确显示而非溢出
|
||||
- 用户可以通过调整文本框大小来控制显示效果
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. **Phase 1**: 修改 `add_text_element()` 函数,添加 `tf.word_wrap = True`
|
||||
2. **Phase 2**: 修改 `render_text_element_to_html()` 函数,更新 CSS 样式
|
||||
3. **Phase 3**: 创建测试 YAML 文件,包含长文本内容验证效果
|
||||
4. **Phase 4**: 更新 README.md 说明文本框默认自动换行
|
||||
|
||||
**Rollback Strategy:** 如有问题,删除添加的代码行即可快速回滚
|
||||
|
||||
## Open Questions
|
||||
|
||||
无。这是一个简单直接的功能改进,实现方式清晰。
|
||||
@@ -0,0 +1,24 @@
|
||||
# Proposal: 文本框默认自动换行
|
||||
|
||||
## Why
|
||||
|
||||
当前文本框渲染时,当文字内容过长时,文字可能会超出文本框边界被截断或显示不完整。系统应该默认启用文字自动换行,确保文字始终在文本框内正确显示,无需用户额外配置。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 修改 `add_text_element()` 函数,默认设置 `text_frame.word_wrap = True`
|
||||
- 修改 `render_text_element_to_html()` 函数,使用 `white-space: normal` 启用自动换行
|
||||
- 所有文本框默认启用自动换行,无需 YAML 配置
|
||||
|
||||
## Capabilities
|
||||
|
||||
### Modified Capabilities
|
||||
- `element-rendering`: 文本框默认启用文字自动换行
|
||||
- `html-rendering`: HTML 预览默认启用文字自动换行
|
||||
|
||||
## Impact
|
||||
|
||||
- **Affected Code**: `yaml2pptx.py` 中的 `add_text_element()` 函数和 `render_text_element_to_html()` 函数
|
||||
- **YAML Schema**: 无变化,用户无需修改现有 YAML 文件
|
||||
- **Dependencies**: 无新增依赖,使用 python-pptx 现有的 TextFrame.word_wrap 属性
|
||||
- **Breaking Changes**: 无,此改动能改善现有长文本显示问题
|
||||
@@ -0,0 +1,32 @@
|
||||
# Element Rendering Delta
|
||||
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: 系统必须支持文本元素渲染
|
||||
|
||||
系统 SHALL 将 YAML 中定义的文本元素渲染为 PPTX 文本框,并默认启用文字自动换行。
|
||||
|
||||
#### Scenario: 渲染基本文本元素
|
||||
|
||||
- **WHEN** 元素定义为 `{type: text, content: "Hello", box: [1, 2, 8, 3]}`
|
||||
- **THEN** 系统在幻灯片的 (1, 2) 位置创建 8×3 英寸的文本框,内容为 "Hello"
|
||||
|
||||
#### Scenario: 应用文本字体样式
|
||||
|
||||
- **WHEN** 文本元素定义了 `font: {size: 32, bold: true, color: "#333333"}`
|
||||
- **THEN** 系统将文本设置为 32pt、粗体、颜色为 #333333
|
||||
|
||||
#### Scenario: 应用文本对齐方式
|
||||
|
||||
- **WHEN** 文本元素定义了 `font: {align: center}`
|
||||
- **THEN** 系统将文本设置为居中对齐
|
||||
|
||||
#### Scenario: 支持多种对齐方式
|
||||
|
||||
- **WHEN** 文本对齐方式为 `left`、`center`、`right` 之一
|
||||
- **THEN** 系统正确应用对应的对齐方式
|
||||
|
||||
#### Scenario: 文本框默认启用自动换行
|
||||
|
||||
- **WHEN** 系统渲染任何文本元素
|
||||
- **THEN** 系统设置 `text_frame.word_wrap = True`,文字在文本框边界处自动换行
|
||||
@@ -0,0 +1,37 @@
|
||||
# HTML Rendering Delta
|
||||
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: 系统必须渲染文本元素
|
||||
|
||||
系统 SHALL 将 YAML 中的文本元素转换为 HTML `<div>` 标签,应用相应的样式,并默认启用文字自动换行。
|
||||
|
||||
#### Scenario: 渲染基本文本元素
|
||||
|
||||
- **WHEN** 元素定义为 `{type: text, content: "Hello", box: [1, 2, 8, 3]}`
|
||||
- **THEN** 系统生成 `<div>` 标签,内容为 "Hello",位置为 (96px, 192px),尺寸为 768x288 像素
|
||||
|
||||
#### Scenario: 应用文本字体样式
|
||||
|
||||
- **WHEN** 文本元素定义了 `font: {size: 32, bold: true, color: "#333333"}`
|
||||
- **THEN** 系统应用 CSS:`font-size: 32pt; font-weight: bold; color: #333333`
|
||||
|
||||
#### Scenario: 应用文本对齐方式
|
||||
|
||||
- **WHEN** 文本元素定义了 `font: {align: center}`
|
||||
- **THEN** 系统应用 CSS:`text-align: center`
|
||||
|
||||
#### Scenario: 支持多行文本(保留换行符)
|
||||
|
||||
- **WHEN** 文本内容包含换行符(`\n`)
|
||||
- **THEN** 系统使用 `white-space: pre-wrap` 保留换行符
|
||||
|
||||
#### Scenario: 文本元素默认启用自动换行
|
||||
|
||||
- **WHEN** 系统渲染任何文本元素
|
||||
- **THEN** 系统应用 CSS:`white-space: normal`,允许文字在容器边界处自动换行
|
||||
|
||||
#### Scenario: 使用 pt 单位表示字体大小
|
||||
|
||||
- **WHEN** 文本字体大小为 44
|
||||
- **THEN** 系统使用 CSS:`font-size: 44pt`(与 PPTX 保持一致)
|
||||
@@ -0,0 +1,22 @@
|
||||
# Implementation Tasks
|
||||
|
||||
## 1. PPTX 文本框自动换行实现
|
||||
|
||||
- [x] 1.1 修改 `add_text_element()` 函数,在创建文本框后设置 `text_frame.word_wrap = True`
|
||||
- [x] 1.2 确保所有新创建的文本框默认启用自动换行
|
||||
|
||||
## 2. HTML 预览自动换行同步
|
||||
|
||||
- [x] 2.1 修改 `render_text_element_to_html()` 函数,调整 CSS `white-space` 样式
|
||||
- [x] 2.2 将 `white-space: pre-wrap` 改为 `white-space: normal` 以启用自动换行
|
||||
|
||||
## 3. 测试验证
|
||||
|
||||
- [x] 3.1 创建测试 YAML 文件,包含长文本内容
|
||||
- [x] 3.2 生成 PPTX 文件,验证文字在文本框内正确换行
|
||||
- [x] 3.3 启动 HTML 预览,验证预览效果与 PPTX 一致
|
||||
- [x] 3.4 清理测试文件
|
||||
|
||||
## 4. 文档更新
|
||||
|
||||
- [x] 4.1 更新 README.md,说明文本框默认启用自动换行
|
||||
@@ -8,7 +8,7 @@ Element rendering系统负责将 YAML 中定义的各类元素(文本、图片
|
||||
|
||||
### Requirement: 系统必须支持文本元素渲染
|
||||
|
||||
系统 SHALL 将 YAML 中定义的文本元素渲染为 PPTX 文本框。
|
||||
系统 SHALL 将 YAML 中定义的文本元素渲染为 PPTX 文本框,并默认启用文字自动换行。
|
||||
|
||||
#### Scenario: 渲染基本文本元素
|
||||
|
||||
@@ -30,6 +30,11 @@ Element rendering系统负责将 YAML 中定义的各类元素(文本、图片
|
||||
- **WHEN** 文本对齐方式为 `left`、`center`、`right` 之一
|
||||
- **THEN** 系统正确应用对应的对齐方式
|
||||
|
||||
#### Scenario: 文本框默认启用自动换行
|
||||
|
||||
- **WHEN** 系统渲染任何文本元素
|
||||
- **THEN** 系统设置 `text_frame.word_wrap = True`,文字在文本框边界处自动换行
|
||||
|
||||
### Requirement: 系统必须支持图片元素渲染
|
||||
|
||||
系统 SHALL 将 YAML 中定义的图片元素渲染为 PPTX 图片对象。
|
||||
|
||||
@@ -46,7 +46,7 @@ HTML Rendering 系统负责将 YAML 中定义的各类元素(文本、图片
|
||||
|
||||
### Requirement: 系统必须渲染文本元素
|
||||
|
||||
系统 SHALL 将 YAML 中的文本元素转换为 HTML `<div>` 标签,应用相应的样式。
|
||||
系统 SHALL 将 YAML 中的文本元素转换为 HTML `<div>` 标签,应用相应的样式,并默认启用文字自动换行。
|
||||
|
||||
#### Scenario: 渲染基本文本元素
|
||||
|
||||
@@ -63,10 +63,15 @@ HTML Rendering 系统负责将 YAML 中定义的各类元素(文本、图片
|
||||
- **WHEN** 文本元素定义了 `font: {align: center}`
|
||||
- **THEN** 系统应用 CSS:`text-align: center`
|
||||
|
||||
#### Scenario: 支持多行文本
|
||||
#### Scenario: 支持多行文本(保留换行符)
|
||||
|
||||
- **WHEN** 文本内容包含换行符(`\n`)
|
||||
- **THEN** 系统使用 `white-space: pre-wrap` 保留换行
|
||||
- **THEN** 系统使用 `white-space: pre-wrap` 保留换行符
|
||||
|
||||
#### Scenario: 文本元素默认启用自动换行
|
||||
|
||||
- **WHEN** 系统渲染任何文本元素
|
||||
- **THEN** 系统应用 CSS:`white-space: normal`,允许文字在容器边界处自动换行
|
||||
|
||||
#### Scenario: 使用 pt 单位表示字体大小
|
||||
|
||||
|
||||
@@ -406,6 +406,8 @@ def add_text_element(slide, elem, base_path=None):
|
||||
textbox = slide.shapes.add_textbox(x, y, w, h)
|
||||
tf = textbox.text_frame
|
||||
tf.text = elem.get('content', '')
|
||||
# 默认启用文字自动换行
|
||||
tf.word_wrap = True
|
||||
|
||||
# 应用字体样式
|
||||
font_style = elem.get('font', {})
|
||||
@@ -899,7 +901,8 @@ def render_text_element_to_html(elem):
|
||||
{'font-style: italic;' if font.get('italic') else ''}
|
||||
display: flex;
|
||||
align-items: center;
|
||||
white-space: pre-wrap;
|
||||
white-space: normal;
|
||||
overflow-wrap: break-word;
|
||||
"""
|
||||
|
||||
content = elem.get('content', '').replace('<', '<').replace('>', '>')
|
||||
|
||||
Reference in New Issue
Block a user