Fix PowerPoint math paragraph fonts (0.7.4)

This commit is contained in:
2026-10-15 18:17:40 +08:00
parent d671e412ae
commit 8943e7e5ae
5 changed files with 20 additions and 6 deletions
+3 -1
View File
@@ -1,6 +1,6 @@
# Templated-PPT-Master
可独立安装的 `ppt-template-workflow` Skill,当前版本 **0.7.3**。仓库根目录就是唯一安装单元:[SKILL.md](SKILL.md)。它提供模板选择、逐页设计、素材上色、原生 PPTX、图表与表格、页面协作和可重建工程;无需另装其他 Skill。template、theme、组织素材和字体独立提供。
可独立安装的 `ppt-template-workflow` Skill,当前版本 **0.7.4**。仓库根目录就是唯一安装单元:[SKILL.md](SKILL.md)。它提供模板选择、逐页设计、素材上色、原生 PPTX、图表与表格、页面协作和可重建工程;无需另装其他 Skill。template、theme、组织素材和字体独立提供。
在支持本地文件和命令执行的 Agent 中输入:
@@ -16,6 +16,8 @@ Agent 应读取本页和 [INSTALL.md](INSTALL.md),通过 Git 克隆这个地
0.7.2新增[文字与容器硬约束](references/text-and-containers.md):段落优先使用一个原生文本框,必要拆分保持逻辑统一;实质说明不放小号灰字;同容器不同文字角色不能只靠字体区分;同类容器共用内部排版实现,调用者不得逐例摆放内部文字和图标。
0.7.4补齐原生公式所在段落的默认/段尾字体、字号和颜色,修复PowerPoint for Mac中根号和高括号的尺寸异常;保留专用数学字体与原生编辑能力。后处理不能移除这些段落属性,保存重开后的实际字体与渲染仍须检查。
0.7.3统一组件的文字角色解析,落实所选template的字体、字号、字重与行高;图表标题、标注和来源使用不同层级。新增C20通用段落硬约束:遵守标点避头尾,每一行均不得只有一个字或一个字加周围标点;以完整段落重排并检查实际渲染。图表轴暂只支持常规字重,无法兑现的字重明确拒绝。
0.7.3将[间距固定到template和共享recipe](references/spacing.md):调用者不传间距数字、阈值或临时变体。共享多段文本组件读取固定内边距与段间距,自动生成精确关系检查,过窄与过宽均拒绝;正文仍保留内容驱动的换行与占用高度。[数学](references/mathematics.md)以专用字体和结构化表达式生成Office Math;不依赖通用TeX服务或另一个Skill,不把线性兼容文字当成公式效果或编辑证据。
+1 -1
View File
@@ -2,7 +2,7 @@
name: ppt-template-workflow
description: Create and revise template-based editable PPTX decks, design page mockups and materials, reconstruct visual pages into native objects, and maintain portable source projects. Select one external template and theme at a time; includes its own native compiler and workflows without requiring another installed Skill.
metadata:
version: "0.7.3"
version: "0.7.4"
---
# PPT Template Workflow
+4
View File
@@ -1,5 +1,9 @@
# 版本变化
## 0.7.4
为公式所在DrawingML段落的defRPr和endParaRPr补齐外部声明的数学字体、字号与颜色,并保持普通文字fallback的正确子元素次序。修复PowerPoint for Mac可能出现的根号过短、矩阵与嵌套分式括号在本地PDF中过小的问题。接口、公式语义、默认字体来源、原生类型与上游快照保持;数学验证文档增加段落默认属性及保存重开检查。
## 0.7.3
将C21/C22进一步固定:spacing属于外部template与共享recipe,内容调用者不提供数字、阈值、偏移或临时变体。`resolve_spacing`按role路径读取唯一数值;`check_spacing(...,style=...)`只接受role,精确核对间隔与四侧padding,过小/过大均拒绝。多段文字自动记录固定padding和paragraph关系;空白可用区不要求文字填满。旧template可按既有固定字段读取,不猜新数字。
+3
View File
@@ -43,11 +43,14 @@ The SVG contains complete JSON math metadata and a derived **linear text compati
The resulting `mc:AlternateContent` has an Office Math choice and an ordinary linear-text fallback for applications without math support. The fallback preserves expression meaning but is not an editable equation or a faithful complex-equation preview. Inspect the supported choice in the target application. No online equation service, additional installed Skill, font download or global installation is invoked.
The equation frame declares the same math family, point size and color on the enclosing DrawingML paragraph's `a:pPr/a:defRPr` and `a:endParaRPr`, as well as math runs and operator controls. These paragraph defaults are required: PowerPoint for Mac can otherwise render a radical too short or export tall delimiters at ordinary character size despite explicit run/control fonts. Keep these defaults when rebuilding or postprocessing a frame. Do not substitute Word-only `mathFont` settings or matrix-spacing properties. PowerPoint may rewrite some operator control fonts on save; verify the saved file's actual rendering and PDF font identities separately from those properties.
## Verification
- Check complete input expressions against OMML: correct fraction operands, script attachment, radical degree, delimiter grouping, limits and matrix dimensions. Ordinary Unicode text alone is not proof of an equation.
- Check the declared family, actual destination font identity and OpenType MATH table. Verify glyph coverage and actual use in the application/export; do not silently replace a missing math font. Fonts are referenced, not distributed or embedded by this wrapper.
- Inspect mathematical runs and control properties for the selected family, size and color. Confirm Office Math choice nodes are present, no WordprocessingML-only properties or temporary tokens remain, and Master/Layout/notes are preserved.
- Confirm the enclosing paragraph's default and end properties carry the same math family, point size and color. Include tall delimiters around matrix fractions and radicals containing fractions in application checks, then save and export again to check that the result survives a PowerPoint round trip.
- Render the current native file in a math-capable application. Check symbols, fraction bars, radicals, scripts, operators/limits, equation bounds and clearance from neighboring content. An SVG compatibility view or prior unrelated render cannot substitute.
- Actual equation editing is a separate test: select and change a representative expression in a disposable copy, save, then confirm the resulting equation structure/content. Native XML establishes structure only.
+9 -4
View File
@@ -242,8 +242,8 @@ def _property(parent, name, value):
return _sub(parent, M, name, **{"{" + M + "}val": str(value)})
def _run_properties(parent, spec):
properties = _sub(parent, A, "rPr", sz=str(round(spec["font_size_pt"] * 100)), b="0", dirty="0")
def _run_properties(parent, spec, *, tag="rPr"):
properties = _sub(parent, A, tag, sz=str(round(spec["font_size_pt"] * 100)), b="0", dirty="0")
_sub(_sub(properties, A, "solidFill"), A, "srgbClr", val=spec["color"][1:])
for script in ("latin", "ea", "cs"):
_sub(properties, A, script, typeface=spec["font_family"])
@@ -343,7 +343,10 @@ def _equation_shape(original, spec, px_to_emu):
_sub(body_props, A, "noAutofit")
_sub(body, A, "lstStyle")
paragraph = _sub(body, A, "p")
_sub(paragraph, A, "pPr", algn={"left": "l", "center": "ctr", "right": "r"}[spec["align"]])
paragraph_props = _sub(paragraph, A, "pPr", algn={"left": "l", "center": "ctr", "right": "r"}[spec["align"]])
# PowerPoint's math layout/export also reads the enclosing paragraph defaults.
# Run/control fonts alone leave radicals and tall delimiters incorrectly sized.
_run_properties(paragraph_props, spec, tag="defRPr")
math_node = _sub(paragraph, A14, "m")
if spec["display"] == "block":
container = _sub(math_node, M, "oMathPara")
@@ -351,6 +354,7 @@ def _equation_shape(original, spec, px_to_emu):
else:
container = math_node
_expression(_sub(container, M, "oMath"), spec["expression"], spec)
_run_properties(paragraph, spec, tag="endParaRPr")
return shape
@@ -386,7 +390,8 @@ def apply_math(path: Path, pages, canvas):
body = fallback.find("p:txBody", NS)
paragraph = body.find("a:p", NS)
paragraph.remove(paragraph.find("a14:m", NS))
run = _sub(paragraph, A, "r")
run = ET.Element("{" + A + "}r")
paragraph.insert(paragraph.index(paragraph.find("a:endParaRPr", NS)), run)
_run_properties(run, spec)
_sub(run, A, "t").text = linear_text(spec["expression"])
alternative = ET.Element("{" + MC + "}AlternateContent", nsmap={"mc": MC})