Files
wehub-resource-sync c48612c494
CI / E2E Tests (push) Has been cancelled
CI / Lint, Typecheck & Unit Tests (push) Has been cancelled
Docs Build / Build docs site (push) Has been cancelled
Publish @openmaic packages / Build, validate & publish (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:03:23 +08:00

137 lines
6.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# DESIGN
`maic-importer`:将 `.pptx` 文件解析为结构化 JSON,供 PPTist 等下游渲染器消费。
## 解析管线
```
.pptx (ArrayBuffer)
↓ parser/ZipParser ── 解压 zip,按用途分类
PptxFiles
↓ model/* ── XML → 结构化模型(位置、大小、层级)
PresentationData
↓ serializer/* ── 模型 + 主题/模板上下文 → JSON 元素
Element[]
↓ adapter/toPptxtojson ── 组装最终输出
Output { slides, themeColors, size }
```
入口:`src/index.ts``parse(buffer, options?)`
## 分层职责
| 层 | 目录 | 做什么 | 不做什么 |
|---|---|---|---|
| **parser** | `src/parser/` | zip 解压、XML 解析(SafeXmlNode)、rels 映射、单位换算 | 不解析 OOXML 业务语义 |
| **model** | `src/model/` | 解析几何与结构:位置、大小、旋转、占位符、节点类型 | 不解析视觉样式(颜色、字体、填充) |
| **serializer** | `src/serializer/` | 结合 theme/master/layout 上下文,把模型转成 JSON 元素 | 不直接读 zip |
| **adapter** | `src/adapter/` | 定义对外 JSON 类型,组装最终 Output | 不写业务逻辑 |
| **shapes** | `src/shapes/` | 生成 SVG path 字符串(200+ preset + 自定义几何) | 不决定填充/边框 |
| **utils** | `src/utils/` | 通用工具(颜色变换、媒体格式、EMF 解析、EQ 公式等) | 不引用业务类型 |
依赖方向:`adapter → serializer → model → parser`,单向。`shapes``utils` 是底层工具。
## 目录结构
```
src/
├── index.ts # 入口:parse() + 类型导出
├── adapter/
│ ├── types.ts # ★ 对外 JSON 类型定义(改它 = 改协议)
│ └── toPptxtojson.ts # 组装 Output
├── parser/
│ ├── ZipParser.ts # .pptx → PptxFiles
│ ├── XmlParser.ts # SafeXmlNodenull-safe DOM 包装)
│ ├── RelParser.ts # .rels 关系映射
│ └── units.ts # EMU / pt / px / 角度换算
├── model/
│ ├── Presentation.ts # 组装 theme → master → layout → slide 链
│ ├── Theme.ts / Master.ts / Layout.ts / Slide.ts
│ └── nodes/ # 各节点类型解析器
│ ├── BaseNode.ts # 共用属性(位置、大小、旋转、xmlOrder)
│ ├── ShapeNode.ts # sp / cxnSp
│ ├── PicNode.ts # pic
│ ├── TableNode.ts / ChartNode.ts / GroupNode.ts / MathNode.ts
├── serializer/
│ ├── RenderContext.ts # 每页渲染上下文(slide → layout → master → theme
│ ├── slideSerializer.ts # 编排:背景 → master 装饰 → layout 装饰 → slide 元素
│ ├── shapeSerializer.ts # ★ Shape/Text 判定、preset 路径、自适应
│ ├── textSerializer.ts # TextBody → HTML 富文本
│ ├── tableSerializer.ts # 表格样式级联
│ ├── chartSerializer.ts # 图表数据提取
│ ├── imageSerializer.ts # 图片/视频/音频
│ ├── mathSerializer.ts # OMML → LaTeX
│ ├── groupSerializer.ts # ★ 坐标空间缩放 + flip/rotation 烘焙
│ ├── StyleResolver.ts # 颜色/填充 → CSS
│ ├── backgroundSerializer.ts # 背景填充
│ └── borderMapper.ts # 线型 → dasharray
├── shapes/
│ ├── presets.ts # 200+ OOXML preset 几何
│ ├── customGeometry.ts # 自定义几何 → SVG path
│ └── shapeArc.ts # 弧形计算
├── utils/
│ ├── color.ts # OOXML 颜色变换全套
│ ├── media.ts # MIME / 路径
│ ├── mediaWebConvert.ts # TIFF/EMF/JXR → PNG
│ ├── emfParser.ts # EMF 内嵌提取
│ ├── eqFieldParser.ts # Word EQ 域公式 → LaTeX
│ ├── rgbaToPng.ts # RGBA → PNG 编码
│ └── urlSafety.ts # 外链白名单
├── export/
│ └── serializePresentation.ts # 调试用:扁平化输出
└── types/
└── vendor-shims.d.ts
```
★ 标记的是定位问题时最常修改的文件。
## 核心设计点
### 模型层不感知样式
`model/*` 只解析"是什么、在哪里、多大"。视觉样式(颜色、字体、填充)留给 serializer 层,因为需要 theme/master/layout 的级联解析。
### Serializer 是纯映射
`*ToElement(node, ctx, order)` 输入模型 + 上下文,输出 JSON 元素,无副作用。定位 bug 时只需怀疑对应的 serializer 文件。
### Group 坐标烘焙
`groupSerializer.ts` 处理两件事:
1. **chOff/chExt 缩放**:子元素坐标从 group 内部坐标系映射到外层坐标
2. **flip/rotation 烘焙**:group 的变换折算进子元素,输出的 group 始终中性(`rotate:0`, `isFlipH/V:false`
### 元素层级(order
`layoutElements`master + layout 装饰)和 `elements`slide 内容)分开输出。`layoutElements` 内部,layout 元素的 order 会加偏移量,保证始终在 master 元素之上。每个元素的 `order` 来自 `xmlOrder`(文档深度优先遍历索引)。
### 单位约定
- 对外 JSON 一律 **pt**`left/top/width/height`
- 颜色一律 `#RRGGBB`,角度一律 deg
- 内部 EMU 在 model 层转 pxadapter 层 px → pt
## 输出结构概览
完整类型定义见 `src/adapter/types.ts`
| `type` | 关键字段 |
|---|---|
| `text` | `content`(HTML), `vAlign`, `isVertical`, `autoFit` |
| `shape` | `shapType`, `path`, `keypoints`, `content`, `vAlign` |
| `image` | `src`, `geom`, `rect`(裁切), `filters` |
| `table` | `data[][]`, `borders`, `rowHeights`, `colWidths` |
| `chart` | `chartType`, `data`, `colors` |
| `group` | `elements[]`(坐标已转换,变换已烘焙) |
| `math` | `latex`, `picBase64`, `text` |
| `video`/`audio` | `src`, `blob` |
## 参考实现
- `src1/`:原版 JS 实现,**只读不改**,作为参考
## 脚本
| 命令 | 用途 |
|---|---|
| `npx tsx scripts/transvert.ts <file.pptx> [out.json]` | 用本库解析(开发主力,直接跑源码无需构建) |
| `npx tsx scripts/transvert.js <file.pptx> [out.json]` | 用 pptxtojson 原版解析 |
| `node scripts/extract-pptx-structure.js <file.pptx> [outDir]` | 解压 .pptx 查看源 XML |
| `pnpm build` | Rollup 打包 + 生成 .d.ts → dist/ |
| `pnpm lint` | ESLint 检查 |