@web-ppt/editor 0.5.0-beta.1 → 0.5.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +188 -0
- package/README.md +97 -6
- package/dist/accessibility.js +60 -0
- package/dist/adjustments/index.d.ts +2 -0
- package/dist/adjustments/preset-adjustment-editor.d.ts +4 -0
- package/dist/adjustments/types.d.ts +22 -0
- package/dist/adjustments.js +300 -0
- package/dist/canvas-accessibility.d.ts +6 -0
- package/dist/chart/index.d.ts +2 -0
- package/dist/chart-shared/index.d.ts +2 -0
- package/dist/chart-shared.js +7 -0
- package/dist/chart.js +6 -0
- package/dist/common-object-slide-commands.d.ts +20 -0
- package/dist/design/index.d.ts +3 -0
- package/dist/design-editor-types.d.ts +15 -0
- package/dist/design-editor.d.ts +3 -0
- package/dist/design.js +108 -0
- package/dist/dom-identity.d.ts +4 -1
- package/dist/dom-patch.d.ts +1 -1
- package/dist/edit-context/geometry.d.ts +8 -0
- package/dist/edit-context/index.d.ts +8 -0
- package/dist/edit-context/native.d.ts +33 -0
- package/dist/edit-context.js +333 -0
- package/dist/editor-keyboard.d.ts +4 -1
- package/dist/editor.js +1 -6332
- package/dist/element-clipboard.d.ts +4 -2
- package/dist/framework-adapter-types.d.ts +17 -2
- package/dist/image-insertion.d.ts +4 -2
- package/dist/index.d.ts +6 -5
- package/dist/keyboard-context.d.ts +1 -0
- package/dist/keyboard-document.d.ts +8 -0
- package/dist/keyboard-group.d.ts +7 -0
- package/dist/media/index.d.ts +1 -0
- package/dist/media.js +1 -0
- package/dist/rotation-geometry.d.ts +4 -1
- package/dist/selection-all.d.ts +3 -0
- package/dist/selection-hit.d.ts +6 -0
- package/dist/selection-pane-types.d.ts +1 -0
- package/dist/session-state.d.ts +5 -1
- package/dist/session.d.ts +17 -1
- package/dist/slide-dom-renderer.d.ts +1 -0
- package/dist/slide-editor-commands.d.ts +14 -2
- package/dist/slide-editor-events.d.ts +1 -0
- package/dist/slide-editor-types.d.ts +37 -2
- package/dist/slide-pointer-controller.d.ts +3 -0
- package/dist/templates/index.d.ts +2 -0
- package/dist/templates.js +5 -0
- package/dist/text-edit-commit.d.ts +8 -0
- package/dist/text-editor-types.d.ts +2 -0
- package/dist/text-editor.d.ts +8 -3
- package/dist/text-font-step.d.ts +5 -0
- package/dist/text-keyboard.d.ts +28 -0
- package/dist/text-list-level.d.ts +4 -0
- package/dist/touch-gesture.d.ts +42 -0
- package/dist/transform-frame.d.ts +11 -6
- package/dist/vertex/index.d.ts +2 -0
- package/dist/vertex/types.d.ts +21 -0
- package/dist/vertex/vertex-editor.d.ts +4 -0
- package/dist/vertex.js +338 -0
- package/package.json +42 -6
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,194 @@
|
|
|
4
4
|
|
|
5
5
|
## 未发布
|
|
6
6
|
|
|
7
|
+
## 0.5.0-beta.7 - 2026-10-26
|
|
8
|
+
|
|
9
|
+
### 新增
|
|
10
|
+
|
|
11
|
+
- 新增按需 `@web-ppt/edit-core/lint` 七项布局检查与 `/lint/sampler` SVG 颜色采样协议:稳定元素定位、真实字体测量、显式资源错误、进度与取消,随包提供生成 Schema。
|
|
12
|
+
- 新增按需 `@web-ppt/edit-core/describe`:从当前 `EditDoc` 读出页面、设计来源、稳定元素 ID、页面外框和段落文字;支持完整 JSON 的字符 / token 预算及显式截断,随包发布由 TypeScript 类型生成的 JSON Schema。
|
|
13
|
+
- `presentationToVideo` 新增实验性 `videoOverlay`:导出时以 `<video>` 当前帧替代内嵌视频的海报帧,媒体起始时刻与音轨共用同一时间轴;默认关闭时产物不变。
|
|
14
|
+
- `savePpt` 原生写入首尾两色线性渐变(两端透明度分别保留)、十种预设虚线、五种默认尺寸箭头、图片四边矩形裁剪与形状名;图案填充、多色标或径向渐变、自定义虚线与非默认箭头尺寸仍以 `PptSaveError` 拒绝
|
|
15
|
+
- `@web-ppt/edit-core/ole` 新增 `setRun`(嵌入 DOCX 单个 run 改字,相邻格式保留)、`setCellStyle`(嵌入 XLSX 字体 / 填充 / 边框)与 `setCellRichText`(sharedStrings 富文本);`OleParagraph` 新增 `runs` 与表格行列 `table`,`OleCell` 新增 `styleIndex`、`style` 与 `richText`
|
|
16
|
+
- 实验性矢量 PDF 支持 dashed / dotted / double / wavy 文字装饰线,以及文字描边(描边轨在填色轨之下,等效 `paint-order:stroke`)。
|
|
17
|
+
|
|
18
|
+
### 修复
|
|
19
|
+
|
|
20
|
+
- 编辑性能基准统一使用完整源码别名和同一个运行时,不再依赖尚未构建的 dist 或重复的会话 WeakMap;增加干净构建状态的真实回归。
|
|
21
|
+
- 组合同时带旋转与非等比缩放时不再拒绝解组:解组改按 `placeGroupChild` / `placeGroupFrame` 的渲染外框回填孩子 frame,旋转子元素的宽高按转角象限承接组缩放;非等比缩放下预设形状的渲染路径会固化为自由形状覆盖,保存写回 `custGeom`,箭头、圆角等依赖宽高比例的几何不再变形。只有需要改变旋转的框架对象(图表 / OLE 等)仍显式拒绝。
|
|
22
|
+
- 读取 `.ppt` 时线性渐变不再一律按竖向、前景色在上渲染:方向取自 fillAngle,首尾色按 fillAngle 的符号与 fillFocus 还原(与 LibreOffice 的 PowerPoint 兼容规则一致,焦点 40–60 为两侧对称渐变),终点透明度取自 fillBackOpacity;图片的 cropFrom* 裁剪与 wzName 形状名不再丢失。
|
|
23
|
+
- `presentationToVideo` 的 `videoOverlay`:内嵌视频加载失败或超时不再静默退回海报帧,改为经 `onWarning` 以稳定原因 `video-overlay-unavailable` 暴露(附页号与元素名),seek 超时或帧不可用报 `video-overlay-frame-unavailable`,导出均不中断;就绪条件改为首帧可画,避免只取到元数据时首帧停在海报上。未开启 `videoOverlay` 时产物不变。
|
|
24
|
+
- 修复 `.pptx` 媒体源解析只认经典 `a:audioFile` / `a:videoFile` 引用:PowerPoint 2010+ 内嵌 mp3 / mp4 等时把经典关系写成 `Target="NULL"` 外链、字节只挂在 `p14:media` 的 `r:embed` 上,此前 `MediaInfo.src` 为 `null`,player 模式不生成播放器、编辑生成保存会丢失媒体字节。现按经典引用 → `p14:media`(`r:link` 优先于 `r:embed`)逐个取第一个可解析目标:包内关系要求部件存在,外链关系要求是带 scheme 的 URL;正常文件的解析结果不变。
|
|
25
|
+
- 修正视频导出过期说明:`presentationToVideo` 已支持可选音轨;含内嵌媒体时 `mediaPosters: true` 在开启 `audio` / `videoOverlay` 时仍必需,拒绝信息与文档同步说明原因。
|
|
26
|
+
- 英语缩写中的弯撇号(`I’m`、`that’s`)不再按全角标点挤压半个 em,避免撇号与后一个字母重叠(#8)。中文句读的挤压规则不变。
|
|
27
|
+
- 对象动画「伸展」按 PowerPoint 子类型播放:水平展开(across)从中线向两侧长,自底部 / 顶部 / 左侧 / 右侧钉住对应边长出,不再一律从中心缩放并淡入;退场缩回同一条边。「挥舞」按 PowerPoint 的 `sin(2.5π·t)` 宽度(横向为高度)轨迹翻转并叠加淡入,中途会转到背面镜像,不再是一次 `rotateY`。
|
|
28
|
+
- 组合缩放只映射子元素外框:渲染时把 `chOff` / `chExt` 折算进子元素的位置、尺寸、路径与表格行列,不再对子树整体 `scale()`,描边、字号、内边距与效果半径保持物理尺寸(与 PowerPoint、LibreOffice 一致)。WPS 产出的归一化组合(子坐标空间不足 1px)不再出现千像素描边或逐字换行;普通缩放组合内的字号与描边也不再随组放大,非等比组合里的旋转子元素保持矩形。编辑器按同一份刚体外框工作:选择框、命中、框选、对齐 / 分布、吸附、裁剪、顶点与调节柄不再把非等比组合里的旋转子元素当成斜切的平行四边形;缩放与旋转在父组渲染坐标里计算后换算回模型,旋转跨过 45° 等边界时画面宽高保持不变(模型宽高随组缩放承接的轴向互换),粘贴进非等比组合同样按画面落位。`@web-ppt/core` 公开 `placeGroupChild`、`placeGroupFrame` 与 `unplaceGroupFrame`;`@web-ppt/edit-core` / `@web-ppt/editor` 公开 `renderedElement`、`renderedFrameToSlideMatrix`、`renderedContentToSlideMatrix`、`elementParentToRenderedParentMatrix`、`elementEditFrame`、`elementEditParentToSlideMatrix`、`slideToElementEditParentPoint` 与 `editFrameToModelFrame`(edit-core 另有 `groupEditChildrenToSlideMatrix`、`groupEditFrameToModelFrame`);`elementFrameToSlideMatrix` 与 `elementParentToSlideMatrix` 改为沿渲染链求值,只在非等比组合内的非 90° 整数倍旋转、或此类组合嵌套时结果不同(#7)。
|
|
29
|
+
- `wedgeRectCallout` / `wedgeRoundRectCallout` 按 ECMA-376 guide 求值:尾巴从尾尖所在一侧的边伸出,圆角取 `adj3`;此前底座固定在下边,尾尖朝上时尾巴穿过整个框只剩一条细线(#7 附件)。
|
|
30
|
+
- 非占位符形状 `p:style` 的 `fontRef` 颜色压过 presentation `defaultTextStyle` 的方案色,形状自身 `lstStyle` 与 `rPr` 仍优先;PowerPoint 默认形状里的白字不再渲染成黑字。
|
|
31
|
+
- 背景 `bgRef` 按 ST_StyleMatrixColumnIndex 取主题样式:`1001` 起对应 `bgFillStyleLst` 第 1 项、`1`–`999` 对应 `fillStyleLst`;此前 `idx="1001"` 被夹到列表末项,最常见的白色背景被画成主题第三档渐变。
|
|
32
|
+
- run 的字体栈只在文字含复杂文种(阿拉伯文、希伯来文、泰文、天城文等)时才纳入 `a:cs` 字体;此前拉丁字体缺席时 `cs`(如 WPS 常写的 Arial Black)会接管拉丁字母,标题被撑宽断行。新增公开函数 `textRunFontStack` 供编辑投影共用。
|
|
33
|
+
- 只写 `asvg:svgBlip`、`a:blip` 上没有位图兼容副本的图片(WPS 插入的图标)按 SVG 部件渲染,不再显示为不支持的对象。
|
|
34
|
+
- 有封面且源可用的音频不再叠加灰色播放标识(封面本身就是喇叭图标);`media: 'player'` 下音频不显示原生控件条,`Viewer` 点击封面播放 / 暂停,播放被拒绝时同样派发 `web-ppt-playback-error`。官网查看器改用 player 模式,放映中点击媒体不翻页。
|
|
35
|
+
- 等线缺席时西文改用合成字族:`local()` 引用系统 Arial 度量族,粗体 `size-adjust: 95.4%`、下划线 `74.6%`,只在页面出现等线时声明;`@web-ppt/fonts` 的替换路径对 Arimo 套用同一组参数。取代窄体回退与连续空格半字宽的处理;依据是 #8 附带的 PowerPoint 导出图逐词拟合,断行与填空线长度与 PowerPoint 一致。
|
|
36
|
+
- `Viewer` 执行动画时间线里的 `mediacall` 媒体调用(`playFrom` / `pause` / `stop` 等),`afterPrev` 等定时触发的音视频按时播放,切页或取消时暂停;`play()` 被浏览器拒绝时容器派发 `web-ppt-playback-error`。媒体调用步骤不再给图标留下强调动画的半透明终态(#7)。
|
|
37
|
+
|
|
38
|
+
`@web-ppt/collab` 发布入口为 12.20KB gzip;排除 peer 的完整测试薄包为 14,333B gzip,两种口径分别核对。
|
|
39
|
+
|
|
40
|
+
## 0.5.0-beta.6 - 2026-10-10
|
|
41
|
+
|
|
42
|
+
### 新增
|
|
43
|
+
|
|
44
|
+
- `presentationToVideo` 新增可选音轨:`audio: true` 时解析 timing 树媒体节点(`p:audio` 的音量 / 静音 / 循环 / 触发批次),按页时间轴确定性混音后以 Opus 48kHz 编码进 WebM 双轨;视频文件的 AAC 音轨同样提取混入,无音轨或解码失败经 `onWarning` 以稳定原因跳过、不阻断导出。无音频媒体时仍为无声视频,默认关闭时产物与上一版逐字节一致。公开 `WebmWriter` 音频轨与 `mixAudioClips` 混音核;`MediaInfo` 扩展 `spid` 与 `playback` 播放语义。
|
|
45
|
+
- 实验性矢量 PDF 的文字渐变原生支持(Pattern colorspace):任意轴线性渐变、同段多 run 各自分框(按字形墨迹范围)、下划线 / 删除线继承渐变。坐标口径经 MuPDF / poppler / CoreGraphics 三实现实测裁决;透明渐变因渲染层无输入语义暂按稳定原因回退。
|
|
46
|
+
|
|
47
|
+
### 改进
|
|
48
|
+
|
|
49
|
+
- CJK 标点挤压补全 PowerPoint 完整规则:连续标点对、行首起始标点与行尾句读无条件收半格;断行判定仍按全角,与 PowerPoint 断行基线一致。
|
|
50
|
+
- 网络字体到货后的重排补齐数学布局缓存失效:`invalidateTextMeasureCaches` 公开导出,`Viewer.refresh()` 完整覆盖字体环境变化。
|
|
51
|
+
- 文档体系新增功能设计标准、分层依赖规范与 `.pptx` / `.ppt` 规范地图;依赖方向由 `check-architecture-boundary` 在 build 与 verify 机械审计。
|
|
52
|
+
|
|
53
|
+
### 修复
|
|
54
|
+
|
|
55
|
+
- 修复矢量 PDF 跨页复用渐变 Pattern 时未在当前页注册资源导致的整段取色错误(单页导出不触发)。
|
|
56
|
+
- 修正 README 已知限制与能力矩阵的三处失真(EMF+ / OMML / 3D)及打开密码文件的能力描述。
|
|
57
|
+
|
|
58
|
+
`@web-ppt/collab` 发布入口为 12.20KB gzip;排除 peer 的完整测试薄包为 14,333B gzip,两种口径分别核对。
|
|
59
|
+
|
|
60
|
+
## 0.5.0-beta.5 - 2026-09-10
|
|
61
|
+
|
|
62
|
+
### 新增
|
|
63
|
+
|
|
64
|
+
- 高级文本生成保存与跨文稿复制支持公式、艺术字及已声明的高级文字效果;经典图表支持多级类别与共享工作簿同步,保留历史、恢复、协同和原生保存闭环。
|
|
65
|
+
- 新增实验性 `@web-ppt/core/pdf/vector` 及独立 browser 适配入口:支持范围内的文字可搜索,图形保留矢量,特殊效果按对象回退为图片并返回位置说明。
|
|
66
|
+
编辑器导出窗口通过 Cordis 文件 / 字体服务提供入口,缺字体可定位并加载本机字体后重试;取消、换稿和退出等待实际资源消费结束。此版本不代表 005 整项验收完成;复杂文字效果、更多 SVG 组合、其他 PDF 阅读器及长文稿成本仍待收口。
|
|
67
|
+
- 新增 `@web-ppt/fonts/glyphs` 可选字体 Provider 及 HarfBuzz、Worker、FontFace 适配:验证原始容器与嵌入限制,返回定位字形、轮廓和 UTF-16 原文簇;整形器和字体字节由宿主提供。
|
|
68
|
+
产品编辑器由 Cordis 文稿服务检查、应用和释放字体,提供中英文缺字诊断与本机替换;原始字体模式避免主线程重复解压,替换和安装失败会归还旧字体预算。当前字体资源用于预览及图片 / SVG / 实验性矢量 PDF 导出,不写入 PPTX。
|
|
69
|
+
- 可选 `@web-ppt/collab/migration` 入口为扩展字段保留带原 stamp 的 `set/del` 操作证据;来源元素或页面删除后仍可恢复。
|
|
70
|
+
与默认入口共用协同会话和回滚,旧检查点缺少证据时保持未知;共享图表可按原操作裁决矛盾字段和删除,后续原操作可补齐缺失证据。
|
|
71
|
+
- 编辑核心可原子执行已裁决的扩展迁移凭据,保留来源操作、删除赢家和冷恢复语义;拒绝不完整来源及父子字段冲突。
|
|
72
|
+
可选协同入口在远端接收和延迟消息消费时重新裁决,保留更晚本地操作;默认入口拒绝凭据,原始版本不会替换为运输消息的时钟。
|
|
73
|
+
恢复日志在提交前准备声明,旧字段按原地址和顺序重放;解析器乱序释放不会复活旧实例。
|
|
74
|
+
- 包体积核对改为默认入口及全部相对静态分块逐文件 gzip 后求和,修正旧表漏算共享分块的问题;peer 与动态入口仍另计。
|
|
75
|
+
- 官网编辑产品层通过同一 Cordis 应用管理文稿、打开、新建、恢复、文件、业务工具与页面状态;页面插件持有模式、导航、历史和视口,入口仅保留启动及重试。
|
|
76
|
+
新打开取消旧模板和图片选择,退出先停止页面与 SDK 编辑输入,再等待已提交文件交付,最后释放文稿、监听、观察器和弹窗;重建后命令不重复。发布 SDK 保持无框架依赖。
|
|
77
|
+
- 图片插入、替换和背景接口支持 `options.signal`;取消会释放待选入口,并在读取、解码及提交边界阻止迟到修改,
|
|
78
|
+
避免应用退出等待文件交付期间旧工具继续写入文稿。
|
|
79
|
+
- 共享图表入口迁移独立数据区域的旧局部编辑,保留旧撤销历史、协同时钟及迟到消息;支持加载前复制页及
|
|
80
|
+
多旧所有者/新旧数据的相等或不同字段合并。删除整张原页及中间副本后,幸存副本仍可编辑、保存和冷恢复。
|
|
81
|
+
可选协同入口让复制快照继承可证明的原 set/del 版本,保留副本远端更新后的撤销重做,并裁决已加载共享入口的迟到复制。
|
|
82
|
+
缺失原版本或同版本矛盾的字段、无来源记录及日志的旧裸模型、身份冲突仍保留只读,完整范围见迁移记录。
|
|
83
|
+
|
|
84
|
+
### 验证与范围
|
|
85
|
+
|
|
86
|
+
- `@web-ppt/collab` 发布入口为 12.20KB gzip;包含相对静态分块。排除 peer 的完整测试薄包为 14,333B gzip,两种口径分别核对。
|
|
87
|
+
- 字体及 PDF 独立读取依赖固定版本并接入 CI / 发布环境;矢量 PDF 源码与产物契约纳入常规功能和一致性门禁。
|
|
88
|
+
- 保留 beta.4 的密码弹窗与 CI 稳定性修复。视频仍无音轨、内嵌视频合成和长尾格式扩展待后续;Windows PowerPoint 真机继续暂缓。
|
|
89
|
+
- 模块成果与下一步见[本轮交付说明](https://github.com/unStone/web-ppt/blob/master/docs/releases/0.5.0-beta.5.md)。
|
|
90
|
+
|
|
91
|
+
## 0.5.0-beta.4 - 2026-09-09
|
|
92
|
+
|
|
93
|
+
### 剩余功能收口
|
|
94
|
+
|
|
95
|
+
- 补齐四个产品入口的只读批注面板、PNG/SVG/ZIP 标记与打印正文;生成保存不再丢失批注,复制页独立分配批注部件和索引。
|
|
96
|
+
- 批注复制覆盖连续保存、撤销/重做、来源释放、外部补丁、恢复、最大索引及显式 Internal/未知 XML 扩展。
|
|
97
|
+
- 十页混合固件贯通七种原生现代布局、地图回退、经典数据、WAV/MP4、图片/立体和批注;新增包名产物契约及 0.8 功能完成度门禁。
|
|
98
|
+
- 新增按需图片效果和立体编辑,官网控件共用历史、恢复、协同与两条保存;双色调在 PNG/独立 SVG 中使用真实颜色。
|
|
99
|
+
- 官网与查看器遇到 ChartEx 自动按需启用原生解析,加载失败继续显示来源预览;SDK 默认行为不变。
|
|
100
|
+
- 新增可选画布读屏目录和 EditContext,真实 Chromium 覆盖预编辑、连续输入、撤销及加载失败回退。
|
|
101
|
+
- 修复经典图表系列标题与子节点顺序、零挤出重开及未加载扩展时双色调生成保存丢失。
|
|
102
|
+
- 补充混合内容保存旅程、公开 API 契约和迁移说明;Windows 真机按用户要求暂缓。
|
|
103
|
+
|
|
104
|
+
### 新增
|
|
105
|
+
|
|
106
|
+
- 新增 `@web-ppt/core/chart-ex` 与显式解析 hook:树状图、旭日、直方图/Pareto、箱线、瀑布和漏斗输出原生 Schema;
|
|
107
|
+
地图、歧义数据与不支持的来源保留 Office fallback。主题、母版与保存后继续沿用文稿打开时的解析配置。
|
|
108
|
+
SDK 默认入口不加载实现;官网按内容类型自动加载。其他类型真实 PPTX 和 Office 原生布局验收尚未完成。
|
|
109
|
+
- 官网增加中英文基础入口:三张页面输出静态英文镜像与双语 SEO,URL 优先于本机偏好和浏览器语言;
|
|
110
|
+
原地切换保留文稿、选区和撤销历史,中文默认不下载英文词库。编辑页打开/保存/图片 ZIP、转换确认、
|
|
111
|
+
模板选择、本机恢复、动态工具与无障碍文案均已接入;模板和恢复提示内可直接切换语言。
|
|
112
|
+
- 媒体按需入口支持 PCM WAV / MP4(含分片)、显式 HTTP(S) 外链、确定性音频图标和独立海报替换;
|
|
113
|
+
editor / React / Vue 和官网媒体工具转发同一 API,默认入口不加载媒体校验或图标。
|
|
114
|
+
官网支持选中媒体试听、失效外链提示与按需媒体日志恢复,外链仅在点击播放时访问;切换文稿和关闭工具释放播放器。
|
|
115
|
+
- 经典图表新增按需数据编辑入口,支持系列、类别和数值增删改;稀疏覆盖贯通历史、恢复与协同,保存同时同步
|
|
116
|
+
图表缓存和内嵌工作簿。官网数据检查器动态加载,默认入口不携带图表编辑实现。
|
|
117
|
+
- 主题、母版、版式与内置模板现已组成同一条公开编辑链:主题经 `exec`,母版与版式经 `execDesign`
|
|
118
|
+
精确传播到依赖页,页面直设继续优先;三套模板共用历史、恢复、字段级协同与保存协议。
|
|
119
|
+
- 新增独立按需模板入口:极光、刊页、夜幕三套确定性配方各自物化主题、母版、五种常用版式和可编辑标题页;
|
|
120
|
+
官网、无框架 editor 与 React/Vue 只转发同一目录,默认入口不加载配方或预览数据。
|
|
121
|
+
- 编辑模型补齐字符、自动编号和图片项目符号;结构化来源值、富文本剪贴板、格式刷、表格文字、恢复、协同
|
|
122
|
+
以及补丁/生成保存使用同一套项目符号语义。
|
|
123
|
+
- 新增预设形状切换、DrawingML 调节值和独立 `@web-ppt/editor/adjustments` 拖柄入口;187 个预设中
|
|
124
|
+
120 个含句柄的定义由固定规范源生成,未使用时不进入 editor 主包。
|
|
125
|
+
- 高级字符格式新增 17 种精确下划线、双删除线、高亮、字距、大小写与基线上下标;`ClearFormat` 删除
|
|
126
|
+
来源直设并保留文字、动态字段、公式和链接身份。
|
|
127
|
+
- 新增按需入口 `@web-ppt/core/image-zip`:以稳定原页码命名批量导出动画终态 PNG,支持隐藏页策略、
|
|
128
|
+
1–8 路有界并发、确定性 ZIP 元数据与逐页进度;任一页失败会携带页码原子拒绝,不返回半成品。
|
|
129
|
+
它复用单页 data URI + `foreignObject` 光栅化与 `SecurityError` 原生文本回退,不引入第二套渲染器。
|
|
130
|
+
- 编辑模型、无框架 editor 与 React/Vue 类型入口补齐对象等距分布、替代文字、节管理和页面尺寸;四组能力
|
|
131
|
+
贯通来源恢复、历史/恢复、字段级协同及保留型/生成式保存,页面尺寸采用不重排元素的“最大化”语义。
|
|
132
|
+
- 无框架 editor 新增仅触屏启用的细描边命中容差、双指缩放/平移和 500ms 长按上下文请求;导航结果经
|
|
133
|
+
adapter 与 React/Vue 公开 seam 交给宿主,不写模型、历史、恢复日志或保存内容,查看模式保留页面滚动。
|
|
134
|
+
- `EditorSession.toPresentation()` 公开当前编辑态只读投影,让官网可直接批量导出图片 ZIP,同时保持脏状态
|
|
135
|
+
与保存点不变;资源生命周期仍由会话统一拥有。
|
|
136
|
+
|
|
137
|
+
### 改进
|
|
138
|
+
|
|
139
|
+
- `@web-ppt/collab` 发布入口为 11.76KB gzip;契约测试使用的完整薄包在排除 peer 后为 14,288B gzip。
|
|
140
|
+
|
|
141
|
+
### 修复
|
|
142
|
+
|
|
143
|
+
- 官网打开加密 `.pptx` / `.ppt` 时弹出密码对话框:错误密码可原地重试,正确后继续查看;core 暴露可识别的 `PasswordRequiredError`,避免界面依赖错误文案判断。
|
|
144
|
+
- 官网内联 CSS 后仅删除无引用产物,并等 Vite 生成预加载清单后再检查,避免共享样式缺失导致动态编辑模块打不开。
|
|
145
|
+
- 无封面媒体新增海报后可保存;兼容分支媒体继续保留整壳限制。生成保存不再重放旧海报关系。
|
|
146
|
+
- 公开 Patch 事件补齐图片资源闭包,修复接收端撤销回收后无法重做;提交及历史双向闭包超限在提交前原子拒绝,
|
|
147
|
+
合并历史超限则保留独立撤销单元。
|
|
148
|
+
无 OOXML 所属页的新建对象可恢复,仍被无来源海报引用的资源不可被远端删除。
|
|
149
|
+
- MC 兼容内容按声明命名空间与实际能力选择;真实 ChartEx 漏斗回退图恢复显示,编辑以完整兼容外壳为身份。
|
|
150
|
+
移动、复制、层级、撤销与两条保存同步保留所有表示及原始数据;编辑会话保留兼容来源,原包释放后仍可生成保存,缺失或冲突的源依赖明确报错。
|
|
151
|
+
- 复制、外部补丁回放和恢复分配对象 ID 时计入未显示的兼容分支,避免新增形状撞 ID;OPC 写回不再因
|
|
152
|
+
Node Buffer 的切片共享内存而污染调用方输入。
|
|
153
|
+
- 0.7 集成验收打通“模板 → 主题 → 母版 → 版式 → 普通页面 → 保存重开”,并修复普通页面事务可绕过
|
|
154
|
+
设计画布权限的问题;普通页面权限隔离现由唯一提交入口统一执行。
|
|
155
|
+
- LibreOffice 与 Windows PowerPoint 改为消费同一份 11 件 Office 清单;清单、产物字节和 PowerPoint
|
|
156
|
+
报告均绑定当前提交,避免两套验收范围悄然分叉。
|
|
157
|
+
- 0.6 跨能力新建旅程打通表格、项目符号、预设形状、高级字符、等距分布、替代文字、节、页面尺寸、
|
|
158
|
+
触屏与批量导出;恢复后分别走补丁和生成保存,再由 Chrome 与 LibreOffice 重开验证。
|
|
159
|
+
- 生成保存现在保留动态页码字段与替代文字;此前这些能力单独测试可用,但从空白文稿混合编辑后会拒绝
|
|
160
|
+
动态字段或丢失 `cNvPr@title/@descr`。
|
|
161
|
+
|
|
162
|
+
## 0.5.0-beta.3 - 2026-08-31
|
|
163
|
+
|
|
164
|
+
### 新增
|
|
165
|
+
|
|
166
|
+
- `@web-ppt/edit-core` 新增稳定表格网格:任意位置插删行列、行高列宽、合并拆分与直接单元格格式都按
|
|
167
|
+
稳定行列身份寻址,并通过公开 `queryTableGrid` 与纯数据命令进入历史、恢复和保存链路。
|
|
168
|
+
- 表格 tombstone 与完整合并真值让删除只改变可见投影;被合并覆盖的文字和格式休眠而不销毁,拆分、撤销及
|
|
169
|
+
保存重开后仍恢复同一逻辑格。`@web-ppt/collab` 同步覆盖并发插删、合并和“至少保留一行一列”的确定性收敛;
|
|
170
|
+
发布入口为 11.76KB gzip;契约测试使用的完整薄包在排除 peer 后为 14,288B gzip,两种口径不混用。
|
|
171
|
+
|
|
172
|
+
### 改进
|
|
173
|
+
|
|
174
|
+
- 发布前一致性门禁统一核对版本、许可证、链接、断言数、快照数、包体积和发布包清单,并把 0.6 后续能力拆为
|
|
175
|
+
可独立验收的 Wayfinder 票据。
|
|
176
|
+
|
|
177
|
+
## 0.5.0-beta.2 - 2026-08-30
|
|
178
|
+
|
|
179
|
+
### 新增
|
|
180
|
+
|
|
181
|
+
- 无原包文档现在可确定性生成完整 PPTX;`.ppt` 编辑后可明确另存为 `.pptx`,官网同时贯通空白新建、
|
|
182
|
+
真实版式加页、保存下载与本机恢复。
|
|
183
|
+
- 编辑模型与无框架 DOM 层新增组合/解组、九级文本列表升降级、附录 B 快捷键、上下文工具栏、
|
|
184
|
+
顶点编辑扩展和表格样式应用/写回。
|
|
185
|
+
- 新增可选的 `@web-ppt/collab`:字段级 LWW、分数序与确定性页序重物化把 `Editor` 补丁流接到
|
|
186
|
+
可插拔 provider,支持离线幂等回放、remove-wins、远端历史 rebase 和 BroadcastChannel 双标签页。
|
|
187
|
+
OOXML 元素身份由 provider 分配的副本 slot 精确分区;协同包不进入单机 `editor` 入口。
|
|
188
|
+
发布入口为 10.70KB gzip;契约测试使用的完整薄包在排除 peer 后为 13,023B gzip,两种口径不混用。
|
|
189
|
+
|
|
190
|
+
### 改进
|
|
191
|
+
|
|
192
|
+
- 官网延后加载编辑引擎,样本在构建期预渲染并内联关键 CSS,同时补齐 WCAG 对比度与稳定 chunk 命名。
|
|
193
|
+
- 浏览器性能契约将功能失败与预算超标分离,并在检测到并行负载时只允许一次全新 Chrome 重测。
|
|
194
|
+
|
|
7
195
|
## 0.5.0-beta.1 - 2026-08-27
|
|
8
196
|
|
|
9
197
|
### 新增
|
package/README.md
CHANGED
|
@@ -7,12 +7,39 @@ source file once, owns its parsed resources and headless editing model, and moun
|
|
|
7
7
|
slide views without uploading the file.
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm i @web-ppt/core @web-ppt/edit-core @web-ppt/viewer-core @web-ppt/editor
|
|
10
|
+
npm i @web-ppt/core@next @web-ppt/edit-core@next @web-ppt/viewer-core@next @web-ppt/editor@next
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
Load the optional template entry only when a user opens a new-deck picker. It forwards the one shared catalog
|
|
14
|
+
and returns ordinary PPTX bytes accepted by `openEditor()`:
|
|
15
|
+
|
|
13
16
|
```ts
|
|
17
|
+
import { createPptxFromTemplate, listBuiltinTemplates } from '@web-ppt/editor/templates';
|
|
14
18
|
import { openEditor } from '@web-ppt/editor';
|
|
15
19
|
|
|
20
|
+
const catalog = listBuiltinTemplates();
|
|
21
|
+
const session = await openEditor(createPptxFromTemplate(catalog[0].id));
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Load classic chart data tools only after the user selects a chart. The editor, React, and Vue chart entries all
|
|
25
|
+
forward this same dataset and command API:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
const charts = await import('@web-ppt/editor/chart');
|
|
29
|
+
const chart = charts.listEditableCharts(session.editor.doc)[0];
|
|
30
|
+
const dataset = charts.queryChartData(session.editor.doc, chart.id);
|
|
31
|
+
charts.createChartDataEditor(session.editor).setSeriesName(chart.id, dataset.series[0].id, 'Forecast');
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Check `chart.binding.mode` before showing controls: `workbook` is fully synchronized, `cache` is cache-only, and
|
|
35
|
+
`readonly` includes the reason editing is unsafe.
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { listThemes, openEditor, queryTheme } from '@web-ppt/editor';
|
|
39
|
+
import {
|
|
40
|
+
createDesignEditor, listLayouts, listMasters, queryMaster,
|
|
41
|
+
} from '@web-ppt/editor/design';
|
|
42
|
+
|
|
16
43
|
const session = await openEditor(file);
|
|
17
44
|
const view = session.mount(container, {
|
|
18
45
|
mode: 'edit', zoom: 1, textMode: 'auto', snapping: true,
|
|
@@ -21,6 +48,7 @@ const view = session.mount(container, {
|
|
|
21
48
|
const selectionPane = session.mountSelectionPane(paneContainer, {
|
|
22
49
|
mode: 'edit', slideId: view.slideId,
|
|
23
50
|
});
|
|
51
|
+
const current = session.toPresentation(); // read-only current projection; valid until session.dispose()
|
|
24
52
|
|
|
25
53
|
const slideId = session.editor.doc.slideOrder[0];
|
|
26
54
|
const elementId = session.editor.doc.slides[slideId].children[0];
|
|
@@ -37,6 +65,26 @@ session.editor.exec({ type: 'MoveSlide', id: view.slideId, at: { after: null } }
|
|
|
37
65
|
const duplicated = session.editor.exec({ type: 'DuplicateSlide', id: view.slideId });
|
|
38
66
|
view.setSlide([...duplicated.createdSlides][0]);
|
|
39
67
|
|
|
68
|
+
const theme = listThemes(session.editor.doc)[0];
|
|
69
|
+
session.editor.exec({ type: 'SetTheme', id: theme.id, clrScheme: { accent1: '#112233' } });
|
|
70
|
+
const effectiveTheme = queryTheme(session.editor.doc, theme.id);
|
|
71
|
+
|
|
72
|
+
const layout = listLayouts(session.editor.doc)[0];
|
|
73
|
+
const design = createDesignEditor(layoutContainer, session, {
|
|
74
|
+
target: layout.target, textMode: 'auto',
|
|
75
|
+
});
|
|
76
|
+
design.exec({
|
|
77
|
+
type: 'SetBackground', target: layout.target,
|
|
78
|
+
fill: { type: 'solid', color: '#112233' },
|
|
79
|
+
}); // updates every slide using this layout in the same committed frame
|
|
80
|
+
const master = listMasters(session.editor.doc)[0];
|
|
81
|
+
design.setTarget(master.target);
|
|
82
|
+
const masterState = queryMaster(session.editor.doc, master.target);
|
|
83
|
+
design.exec({
|
|
84
|
+
type: 'SetMasterTextStyle', target: master.target, category: 'body', level: 1,
|
|
85
|
+
paragraph: { align: 'right' }, run: { font: 'Aptos', size: 30 },
|
|
86
|
+
}); // updates only layouts/slides owned by this master; direct child formatting still wins
|
|
87
|
+
|
|
40
88
|
await view.insertImage(imageFile, { rect: { x: 420, y: 180, w: 320, h: 220 } });
|
|
41
89
|
// Or from a toolbar click: const imageId = await view.chooseImage();
|
|
42
90
|
const tableId = view.insertTable(3, 4); // rows, columns; replaces a selected empty content placeholder
|
|
@@ -70,6 +118,7 @@ view.setAnimations(null); // restore the untouched parsed source
|
|
|
70
118
|
|
|
71
119
|
const bytes = await session.editor.save();
|
|
72
120
|
view.destroy(); // destroys only this mounted view
|
|
121
|
+
design.destroy();
|
|
73
122
|
selectionPane.destroy();
|
|
74
123
|
session.dispose(); // destroys remaining views and releases ZIP bytes / blob URLs
|
|
75
124
|
```
|
|
@@ -148,6 +197,12 @@ recovery candidate, session, view, mode, stable slide id, and zoom without intro
|
|
|
148
197
|
When persistence is enabled, `onRecovery(candidate)` returns `restore`, `discard`, or `cancel`; React and Vue pass
|
|
149
198
|
through this same callback.
|
|
150
199
|
|
|
200
|
+
Common PowerPoint toolbar actions are also adapter-native: `distributeElements()`, `queryAltText()` /
|
|
201
|
+
`setAltText()`, the section directory and four section mutations, and `querySlideSize()` / `setSlideSize()`.
|
|
202
|
+
The same methods exist on a mounted `SlideEditor`; queries remain available in view mode while mutations return
|
|
203
|
+
`false`. A canvas-size change synchronizes the stage, static SVG, and interaction viewBox in the same committed
|
|
204
|
+
frame. `ElementAltTextState`, `SectionRecord`, and `SlideSizeState` are exported for framework controls.
|
|
205
|
+
|
|
151
206
|
### Session format painter
|
|
152
207
|
|
|
153
208
|
The format painter is one session controller shared by every mounted view and framework adapter. Select exactly one
|
|
@@ -297,12 +352,16 @@ listeners symmetrically, so multiple React/Vue/Svelte/Web Component/vanilla view
|
|
|
297
352
|
|
|
298
353
|
Double-clicking an editable shape opens the HTML text layer with native selection and IME composition. Selected
|
|
299
354
|
text responds to `Ctrl/Cmd+B`, `I`, and `U` as one undo unit; the equivalent `beforeinput` format events are also
|
|
300
|
-
handled.
|
|
355
|
+
handled. `Ctrl/Cmd+Shift+7` applies decimal numbering and `Ctrl/Cmd+Shift+8` applies a character bullet to every
|
|
356
|
+
paragraph touched by the native Range. At a collapsed caret, the run-format shortcuts update view-local pending typing style, and the next insertion plus
|
|
301
357
|
its format commit as one history unit without creating a zero-width model run. The live DOM range is published as
|
|
302
358
|
`session.editor.selection`; non-collapsed ranges can use headless `SetRunProps` / `queryRunProps` directly. A mounted
|
|
303
359
|
toolbar uses the view seam below so collapsed-caret typing style stays with the owning input view. Every mounted
|
|
304
360
|
view refreshes while the active browser range is preserved. Switching to view mode closes the input layer and keeps
|
|
305
361
|
the high-fidelity static preview.
|
|
362
|
+
The same seam accepts exact underline/strike styles, highlight, spacing, caps, and baseline shift. Calling
|
|
363
|
+
`view.clearFormat()` clears a selected range immediately; at a collapsed caret it clears pending typing style and
|
|
364
|
+
applies source formatting to the next trusted input or IME commit.
|
|
306
365
|
|
|
307
366
|
```ts
|
|
308
367
|
const unregister = view.registerTextUi(toolbarElement);
|
|
@@ -322,13 +381,18 @@ centerButton.addEventListener('pointerdown', (event) => {
|
|
|
322
381
|
Paragraph controls use the same live DOM Range and remain framework-neutral. `setParaProps` formats every touched
|
|
323
382
|
paragraph—including the current paragraph at a collapsed caret—in one undo unit, then restores the browser Range.
|
|
324
383
|
`queryParaProps` returns per-property mixed state for alignment, effective line height, spacing, margin, and indent.
|
|
384
|
+
It also returns structured character/auto-number/image bullet state. `setParaProps` accepts uploaded image bytes,
|
|
385
|
+
independent bullet font/color/size, and distinguishes `bullet: null` (restore inheritance) from explicit none.
|
|
325
386
|
The command refreshes all views sharing the session; an external toolbar registered with `registerTextUi` does not
|
|
326
387
|
steal focus or accidentally close text editing.
|
|
327
388
|
|
|
328
389
|
Text-mode `Ctrl/Cmd+C`, `X`, and `V` use the same synchronous browser clipboard events as native editors. Copy and
|
|
329
|
-
cut publish sanitized `text/plain` plus `text/html`; default paste keeps only font, size, bold, italic,
|
|
330
|
-
|
|
331
|
-
|
|
390
|
+
cut publish sanitized `text/plain` plus `text/html`; default paste keeps only font, size, color, bold, italic,
|
|
391
|
+
exact underline/strike styles, highlight, spacing, caps, and baseline shift, while `Ctrl/Cmd+Shift+V` ignores HTML.
|
|
392
|
+
Blocks become PPT paragraphs and `<br>` remains a hard
|
|
393
|
+
line break. The editor's sanitized HTML carries a private paragraph attribute for structured bullets; external
|
|
394
|
+
HTML cannot forge an invalid command because the edit-core boundary validates it before commit. External HTML is
|
|
395
|
+
parsed in a detached tree and never injected into the live editor; scripts, style
|
|
332
396
|
sheets, link targets, image sources, hidden metadata, and unsupported CSS are discarded. If sanitized HTML text
|
|
333
397
|
does not equal `text/plain`, formatting is dropped instead of guessing offsets. A paste or cut is one undo unit.
|
|
334
398
|
Image-only paste on the canvas routes through the same `AddImage` command and creates one undo unit. Text/table
|
|
@@ -377,6 +441,10 @@ keeps the insertion inside the standard 8MB undo budget and can be changed expli
|
|
|
377
441
|
view exposes `aria-busy="true"`; failures reject the promise and dispatch `webpptimageerror`. Double-clicking an
|
|
378
442
|
empty picture placeholder uses the same path and replaces that placeholder plus the image in one undo unit.
|
|
379
443
|
|
|
444
|
+
Image insertion, replacement, and background methods accept `options.signal`. Aborting closes a pending file
|
|
445
|
+
chooser (resolving `null`) and prevents unfinished reads or decodes from committing. Direct image operations
|
|
446
|
+
reject on cancellation without dispatching `webpptimageerror`; already committed commands remain undoable.
|
|
447
|
+
|
|
380
448
|
Table pickers call synchronous `view.insertTable(rows, cols, options?)`. An explicit `rect` is used as-is; without
|
|
381
449
|
one, the view replaces the selected empty content placeholder or computes a centered size from the grid. The result
|
|
382
450
|
is a native DrawingML table whose cells open in the existing text editor and whose final-cell `Tab` uses the existing
|
|
@@ -456,6 +524,29 @@ selected roots around the shared AABB center. Angles accumulate continuously acr
|
|
|
456
524
|
ghost wrappers; pointer-up writes OOXML's 1/60000-degree value in one transaction, while every cancellation path
|
|
457
525
|
commits nothing.
|
|
458
526
|
|
|
527
|
+
Edit mode gives touch input its own semantics. Finger selection gets a 12-screen-pixel tolerance around thin SVG
|
|
528
|
+
geometry, while mouse and pen input keep the browser's exact hit testing. One finger still enters the existing
|
|
529
|
+
move, resize, rotate, text-selection, and image-crop paths; only a second finger upgrades the view to canvas
|
|
530
|
+
navigation. The public callbacks keep product layout and menus outside the package:
|
|
531
|
+
|
|
532
|
+
```ts
|
|
533
|
+
const view = session.mount(container, {
|
|
534
|
+
mode: 'edit',
|
|
535
|
+
onTouchNavigate: ({ phase, viewport }) => {
|
|
536
|
+
canvasLayout.applyTouchViewport(phase, viewport);
|
|
537
|
+
},
|
|
538
|
+
onContextRequest: ({ screen, slide, targetId }) => {
|
|
539
|
+
contextMenu.open({ screen, slide, targetId });
|
|
540
|
+
},
|
|
541
|
+
});
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
Pinch zoom is applied to this view; `left` / `top` describe the desired stage position for the host's outer
|
|
545
|
+
scroller. Navigation never writes the model, history, recovery journal, or saved bytes. A 500ms long press emits
|
|
546
|
+
only a context request, and moving more than 8px cancels it. Pointer cancellation/capture loss, page or mode
|
|
547
|
+
changes, host zoom, and view destruction release the gesture. View mode binds none of these edit handlers and
|
|
548
|
+
clears `touch-action`, so page scrolling and browser gestures retain ownership.
|
|
549
|
+
|
|
459
550
|
`textMode: 'auto'` is the default. It reuses `viewer-core`'s runtime probe and switches affected Safari/iOS
|
|
460
551
|
engines to native SVG text when they fail to scale `foreignObject`. The out-of-SVG `contenteditable` then consumes
|
|
461
552
|
the same absolute engine line boxes from core. Explicit `html` and `svg` modes are also available. Soft wraps stay
|
|
@@ -467,7 +558,7 @@ releases shared resources; disposing the session destroys every remaining view a
|
|
|
467
558
|
Svelte, Web Components, and plain DOM adapters all use the same `openEditor` / `mount` seam—none of their
|
|
468
559
|
runtimes are dependencies of this package.
|
|
469
560
|
|
|
470
|
-
The published entry measures
|
|
561
|
+
The published entry measures 68.11 KB gzip. `@web-ppt/core`, `@web-ppt/edit-core`, and
|
|
471
562
|
`@web-ppt/viewer-core` are peer dependencies.
|
|
472
563
|
|
|
473
564
|
MIT
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { slideText as f } from "@web-ppt/core";
|
|
2
|
+
import { querySelectionPane as A, queryElementAltText as y } from "@web-ppt/edit-core";
|
|
3
|
+
class g {
|
|
4
|
+
constructor(i, s, n, r) {
|
|
5
|
+
this.root = i, this.staticLayer = s, this.editor = n, this.prefix = r, this.nodes = /* @__PURE__ */ new Map(), this.serial = 0, this.list = i.ownerDocument.createElement("div"), this.list.dataset.pptAccessibility = "", this.list.role = "listbox", this.list.setAttribute("aria-multiselectable", "true"), Object.assign(this.list.style, {
|
|
6
|
+
position: "absolute",
|
|
7
|
+
width: "1px",
|
|
8
|
+
height: "1px",
|
|
9
|
+
overflow: "hidden",
|
|
10
|
+
clipPath: "inset(50%)",
|
|
11
|
+
whiteSpace: "nowrap"
|
|
12
|
+
}), i.append(this.list);
|
|
13
|
+
}
|
|
14
|
+
sync(i, s) {
|
|
15
|
+
if (this.root.role = s ? "application" : "document", this.staticLayer.setAttribute("aria-hidden", String(s)), this.list.hidden = !s, this.root.removeAttribute("aria-activedescendant"), !s) return;
|
|
16
|
+
this.list.setAttribute("aria-label", this.root.getAttribute("aria-label") ?? "Slide objects");
|
|
17
|
+
const n = /* @__PURE__ */ new Map();
|
|
18
|
+
for (const e of A(this.editor.doc, i)) {
|
|
19
|
+
const t = n.get(e.parentId) ?? [];
|
|
20
|
+
t.unshift(e), n.set(e.parentId, t);
|
|
21
|
+
}
|
|
22
|
+
const r = [], l = (e) => {
|
|
23
|
+
for (const t of n.get(e) ?? [])
|
|
24
|
+
t.hidden || t.editable === "none" || (r.push(t), l(t.id));
|
|
25
|
+
};
|
|
26
|
+
l(null);
|
|
27
|
+
const d = new Set(r.map((e) => e.id));
|
|
28
|
+
for (const [e, t] of this.nodes) d.has(e) || (t.remove(), this.nodes.delete(e));
|
|
29
|
+
const a = this.editor.selection, o = new Set(a.kind === "elements" ? a.ids : []);
|
|
30
|
+
let c = null;
|
|
31
|
+
for (const e of r) {
|
|
32
|
+
let t = this.nodes.get(e.id);
|
|
33
|
+
t || (t = this.root.ownerDocument.createElement("div"), t.role = "option", t.id = `${this.prefix}at-${++this.serial}`, t.dataset.pptAccessibleId = e.id, this.nodes.set(e.id, t)), (t.previousElementSibling !== c || t.parentElement !== this.list) && this.list.insertBefore(t, c ? c.nextElementSibling : this.list.firstElementChild), t.onclick = () => {
|
|
34
|
+
this.editor.select({ kind: "elements", ids: [e.id], enteredGroup: e.parentId }), this.root.focus({ preventScroll: !0 });
|
|
35
|
+
};
|
|
36
|
+
const u = y(this.editor.doc, e.id), b = this.editor.effectiveElement(e.id), p = b.kind === "group" ? "" : f({ background: null, elements: [b] }), m = [...new Set([e.name, u.title, u.descr, p].filter(Boolean))].join(" · ");
|
|
37
|
+
t.textContent !== m && (t.textContent = m), t.setAttribute("aria-selected", String(o.has(e.id))), t.setAttribute("aria-disabled", String(e.locked)), o.has(e.id) && !this.root.hasAttribute("aria-activedescendant") && this.root.setAttribute("aria-activedescendant", t.id), c = t;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
destroy() {
|
|
41
|
+
this.list.remove();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function E(h, i) {
|
|
45
|
+
const s = i.element.querySelector("[data-ppt-layer=static]"), n = i.element.getAttribute("role"), r = s.getAttribute("aria-hidden"), l = new g(
|
|
46
|
+
i.element,
|
|
47
|
+
s,
|
|
48
|
+
h.editor,
|
|
49
|
+
`webppt-${++v}-`
|
|
50
|
+
), d = () => {
|
|
51
|
+
i.destroyed || l.sync(i.slideId, i.mode === "edit");
|
|
52
|
+
}, a = h.editor.subscribe(d), o = new i.element.ownerDocument.defaultView.MutationObserver(d);
|
|
53
|
+
return o.observe(s, { childList: !0 }), o.observe(i.element, { attributes: !0, attributeFilter: ["data-mode", "aria-label"] }), d(), { dispose() {
|
|
54
|
+
a(), o.disconnect(), l.destroy(), i.element.removeAttribute("aria-activedescendant"), n === null ? i.element.removeAttribute("role") : i.element.setAttribute("role", n), r === null ? s.removeAttribute("aria-hidden") : s.setAttribute("aria-hidden", r);
|
|
55
|
+
} };
|
|
56
|
+
}
|
|
57
|
+
let v = 0;
|
|
58
|
+
export {
|
|
59
|
+
E as createCanvasAccessibility
|
|
60
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { EditorSession } from '../session';
|
|
2
|
+
import type { SlideEditor } from '../slide-editor-types';
|
|
3
|
+
import type { PresetAdjustmentEditor, PresetAdjustmentEditorOptions } from './types';
|
|
4
|
+
export declare function createPresetAdjustmentEditor(session: EditorSession, view: SlideEditor, options?: PresetAdjustmentEditorOptions): PresetAdjustmentEditor;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { GeomSpec } from '@web-ppt/core';
|
|
2
|
+
import type { PresetAdjustmentHandle } from '@web-ppt/core/geometry/handles';
|
|
3
|
+
import type { ElementId } from '@web-ppt/edit-core';
|
|
4
|
+
import type { EditorSession } from '../session';
|
|
5
|
+
import type { SlideEditor } from '../slide-editor-types';
|
|
6
|
+
export interface PresetAdjustmentEditorOptions {
|
|
7
|
+
onError?: (error: unknown) => void;
|
|
8
|
+
}
|
|
9
|
+
export interface PresetAdjustmentEditor {
|
|
10
|
+
readonly elementId: ElementId | null;
|
|
11
|
+
readonly geometry: GeomSpec | null;
|
|
12
|
+
readonly handles: readonly PresetAdjustmentHandle[];
|
|
13
|
+
readonly destroyed: boolean;
|
|
14
|
+
/** 省略 id 时只接受当前单元素选区;无手柄预设也能进入并显示为空。 */
|
|
15
|
+
start(id?: ElementId): boolean;
|
|
16
|
+
end(): void;
|
|
17
|
+
/** 切换后保留当前目标;没有活动目标时使用当前单元素选区。 */
|
|
18
|
+
setPreset(preset: string): boolean;
|
|
19
|
+
refresh(): void;
|
|
20
|
+
destroy(): void;
|
|
21
|
+
}
|
|
22
|
+
export type PresetAdjustmentEditorFactory = (session: EditorSession, view: SlideEditor, options?: PresetAdjustmentEditorOptions) => PresetAdjustmentEditor;
|