| name | junhao-pptx-style |
| description | Use when creating PPTX slide decks for Junhao Zhang that should follow his preferred warm research dossier visual language adapted for slides: paper-warm background, Noto Serif SC headings, IBM Plex Sans body, numbered section plates with hard offset shadow, red/teal/ochre/green/cobalt semantic accents, carbon-header matrix tables, formula boxes, callout strips, and editorial typography. This is the slide counterpart of junhao-frontend-style. |
| metadata | {"description_zh":"俊豪 PPT 风格","description_en":"Junhao PPTX style","disable":false,"agent_created":true} |
junhao-pptx-style
When to use
Use this skill when producing PPTX slide decks for Junhao, especially:
- Research presentations, paper walkthroughs, project proposals, or technical reviews.
- Requests that say "做 PPT", "做幻灯片", "参考我的风格", "和 HTML 保持一致" or reference
junhao-frontend-style.
- Work that needs the warm research dossier aesthetic applied to slides instead of HTML.
This skill focuses on PPTX-specific design tokens and layout patterns. For HTML pages, use junhao-frontend-style instead.
Visual direction
Adapt the research dossier / paper workbench style to slides:
- Overall feeling: warm, editorial, rigorous, slightly academic — like high-quality internal research slides, not generic corporate templates.
- Light paper backgrounds for most slides; controlled dark backgrounds only for special emphasis.
- Strong typographic hierarchy: serif headings, sans-serif body, monospace formulas.
- Semantic accent colors, not rainbow decoration.
Design tokens
Color palette
const C = {
paper: "F4EFE2",
paperDeep: "E7DCC5",
ink: "25231F",
ink2: "4D463C",
muted: "746B5D",
carbon: "191814",
panelSolid: "FFFAF0",
white: "FFFFFF",
line: "D5D0C5",
red: "B43D2F",
teal: "147070",
green: "52743D",
ochre: "B9781E",
cobalt: "2D5F88",
softRed: "FAE4DB",
softTeal: "DCEFED",
softGreen: "E5EDD8",
softOchre: "F4E5C7",
softCobalt: "DCE8EF",
};
Typography
const F = {
serif: "Noto Serif SC",
sans: "IBM Plex Sans",
mono: "Consolas",
};
Font sizing guidelines:
| Element | Font size | Weight | Font |
|---|
| Cover title | 36–44pt | bold | serif |
| Section title (h2) | 24–30pt | bold | serif |
| Subsection / card title | 14–18pt | bold | serif |
| Body text | 10.5–12pt | normal | sans |
| Table header | 9–10pt | bold, uppercase feel | sans |
| Table cell | 9.5–11pt | normal | sans |
| Caption / muted text | 10–11pt | normal/italic | sans |
| Formula text | 11–12pt | normal | mono |
| Formula tag label | 10pt | bold | sans |
| Eyebrow / overline | 11pt | bold, letter-spacing 3 | sans |
Shadow factories
pptxgenjs mutates shadow objects, so always use factory functions:
const cardShadow = () => ({
type: "outer", blur: 12, offset: 3, angle: 135,
color: "000000", opacity: 0.10
});
const plateShadow = () => ({
type: "outer", blur: 0, offset: 6, angle: 135,
color: C.carbon, opacity: 1.0
});
Slide layout patterns
Global settings
pres.layout = "LAYOUT_16x9";
pres.author = "Junhao Zhang";
1. Cover slide (浅色)
- Background:
C.paper (light warm)
- Red accent bar at top (full width, 0.06" height)
- Teal accent bar at bottom
- Decorative square brand mark: red fill, ink border,
plateShadow()
- Eyebrow text: sans, 11pt, muted, bold, letter-spacing 3
- Main title: serif, 40pt, ink, bold, multi-line
- Subtitle: sans, 18pt, ochre
- Lead description: sans, 12pt, muted
- Bottom metadata: sans, 10pt, muted italic (left) + red bold section numbers (right)
2. Section header slide
- Background:
C.paper
- Section number plate:
panelSolid fill, ink border 1px, plateShadow(), size ~0.65" square
- Number text: sans, 20pt, red, bold, centered
- Section title: serif, 24–30pt, ink, bold, next to plate
- Section subtitle: sans, 12–13pt, muted, below title
3. Content slide with table
- Section plate + title at top (same pattern as section header)
- Problem/intro card: left accent bar (0.06" wide, colored) +
panelSolid panel + cardShadow()
- Title: serif, 15pt, ink, bold
- Body: sans, 11pt, ink2
- Matrix table:
- Header row: carbon fill, panelSolid text, sans 9–10pt, bold
- Body rows: alternating panelSolid / paper fill, sans 9.5–10.5pt
- First column: ink color, bold
- Border: 0.5pt, line color
- Margins:
[3-4, 5-6, 3-4, 5-6]
- Callout strip: left accent bar (0.06") + soft-accent fill
- Use
addText with rich text array for bold label + normal explanation
4. Formula box slide
- Background panel:
softOchre fill, line border, cardShadow()
- Each formula row:
- Tag label: sans, 10pt, ochre, bold (fixed width ~1.2")
- Vertical separator line
- Formula image: 用 MathJax 渲染的 PNG 图片(
addImage),不是纯文本
- Horizontal separator between rows: line color, 0.3pt
- Explanation note at bottom: left accent bar + softCobalt/softTeal background
- 注意: 完整数学表达式必须用渲染图片,简单单符号($t$, $N$)可保留文本
5. Comparison table slide
- Full comparison table with 3+ columns
- Header: carbon fill, panelSolid text
- Body: alternating row fills
- Conclusion callout at bottom: green left bar + softGreen fill, rich text
6. Metric cards slide (2×2 + optional full-width)
- 2×2 grid of cards: panelSolid fill, line border,
cardShadow()
- Top accent strip (0.07" height) per card, cycling red/teal/ochre/green
- Title: serif, 16pt, ink, bold
- Description: sans, 10.5pt, ink2
- Optional 5th card: full width, cobalt accent
7. Sprint timeline
- Vertical red line on left side
- Sprint markers: paper fill, carbon border, red text, small square
- Sprint title: serif, 11pt, ink, bold
- Sprint description: sans, 10pt, ink2
8. Thank-you / closing slide (浅色)
- Background:
C.paper (light warm)
- Red accent bar top, teal accent bar bottom
- Centered brand mark: red square, ink border,
plateShadow(), with serif letter
- "谢谢": serif, 44pt, ink, bold, centered
- Subtitle: sans, 14pt, muted, centered
- Tagline: sans, 11pt, ochre, italic, centered
Composition rules
- Cover and closing slides use light (
paper) backgrounds. Use dark (carbon) backgrounds only for deliberate high-contrast emphasis slides, not for bookend slides.
- Section consistency: every content slide starts with a section number plate + title at top-left.
- Accent color semantics: red = emphasis/risk, teal = workflow/pipeline, ochre = formulas/tradeoff, green = validation/benchmark, cobalt = technical/reference.
- Card variety: alternate between tables, formula boxes, callout strips, card grids, and timeline patterns — do not repeat the same layout for every slide.
- Information density: slides should be information-dense but scannable. Use tables and structured layouts over long paragraphs.
- Margin conventions: content area is roughly x:0.5–9.5", y:0.4–5.5" with 0.7" left margin for text inside panels.
- Rich text for callouts: use
addText with array of { text, options } objects for bold label + normal text in callout strips.
Steps
- Load the
pptx skill first to get pptxgenjs API reference.
- Set up design tokens (colors
C, fonts F, shadow factories).
- Plan slide structure based on content outline.
- Identify all LaTeX formulas — 提取所有需要渲染的数学公式。
- 渲染公式为 PNG:用 MathJax + Sharp 将每个 LaTeX 公式渲染为 400 DPI 高清 PNG。
- Build each slide following the layout patterns above,用
addImage 嵌入公式图片替代纯文本。
- Use appropriate component patterns: section plates, tables, formula boxes, callouts, card grids, timelines.
- Generate the PPTX file.
- Run content QA (extract text to verify completeness, check image count matches公式数).
- Deliver the file.
Formula rendering (IguanaTex equivalent)
PPT 中的 LaTeX 公式必须渲染为图片嵌入,不能用纯文本 / mono 字体代替。
方案
IguanaTex 是 PowerPoint GUI 插件(.ppam),无法在命令行使用。采用等效的自动化方案:
LaTeX source → MathJax (mathjax-full) → SVG → Sharp (400 DPI) → PNG → pptxgenjs addImage
实现步骤
- 安装依赖:
npm install mathjax-full sharp(安装到 node workspace)
- 渲染脚本核心:
const { mathjax } = require("mathjax-full/js/mathjax.js");
const { TeX } = require("mathjax-full/js/input/tex.js");
const { SVG } = require("mathjax-full/js/output/svg.js");
const { liteAdaptor } = require("mathjax-full/js/adaptors/liteAdaptor.js");
const { RegisterHTMLHandler } = require("mathjax-full/js/handlers/html.js");
const { AllPackages } = require("mathjax-full/js/input/tex/AllPackages.js");
const sharp = require("sharp");
const adaptor = liteAdaptor();
RegisterHTMLHandler(adaptor);
const tex = new TeX({ packages: AllPackages });
const svg = new SVG({ fontCache: "none" });
const html = mathjax.document("", { InputJax: tex, OutputJax: svg });
async function renderFormula(latex, outputPath, scale = 8) {
const node = html.convert(latex, { display: true });
let svgStr = adaptor.innerHTML(node);
if (!svgStr.includes('xmlns="http://www.w3.org/2000/svg"')) {
svgStr = svgStr.replace(/^<svg /, '<svg xmlns="http://www.w3.org/2000/svg" ');
}
svgStr = svgStr.replace(/currentColor/g, "#25231F");
const vbMatch = svgStr.match(/viewBox="([^"]+)"/);
if (vbMatch) {
const [x, y, w, h] = vbMatch[1].split(" ").map(Number);
const pw = Math.ceil(w * scale);
const ph = Math.ceil(h * scale);
svgStr = svgStr.replace(/width="[^"]*"/, `width="${pw}"`);
svgStr = svgStr.replace(/height="[^"]*"/, `height="${ph}"`);
}
await sharp(Buffer.from(svgStr)).png({ quality: 100 }).toFile(outputPath);
const meta = await sharp(outputPath).metadata();
return { width: meta.width, height: meta.height };
}
- 嵌入 PPT:
const DPI = 400;
const imgW = meta.width / DPI;
const imgH = meta.height / DPI;
const maxW = 7.5;
const displayW = Math.min(imgW, maxW);
const displayH = imgH * (displayW / imgW);
slide.addImage({
path: outputPath,
x: centerX - displayW / 2,
y: currentY,
w: displayW,
h: displayH,
});
关键注意事项
- MathJax SVG 已自带 xmlns:不要重复添加,否则 sharp 报 "xmlns redefined" 错误
- scale = 8:产出 ~400 DPI 的高清公式图片,在投影仪上也清晰
- 颜色匹配:用
#25231F(ink)替换 currentColor,与 PPT 正文色一致
- 公式居中:在 formula box 中按
(panelWidth - displayW) / 2 居中放置
- 背景透明:PNG 背景透明,可叠加在任何底色面板上
- Tag 标签:公式左侧加 text tag(如 "History", "Reward"),右侧放公式图片,形成标签+公式的布局
何时使用
- PPT 中出现任何数学公式时,必须用此方案渲染为图片
- 不要用 Consolas 纯文本模拟公式——那是 fallback,不是标准做法
- 简单的单符号(如 $t$, $N$)可以保留纯文本,但完整公式表达式必须渲染
Pitfalls
- Shadow mutation: pptxgenjs mutates shadow objects in place. Always use factory functions (
cardShadow(), plateShadow()) that return fresh objects, never reuse a single shadow object.
- Chinese quotation marks: Characters like
" and " inside JS string literals cause syntax errors. Use Unicode escapes (\u201C, \u201D) or straight quotes.
- Font availability:
Noto Serif SC and IBM Plex Sans must be installed on the machine where the PPT will be presented. They are Google Fonts and widely available. Fallback: on systems without these fonts, PowerPoint will substitute — mention this to the user.
- MathJax xmlns 重复: MathJax 生成的 SVG 已包含
xmlns 属性,再次添加会导致 sharp 解析报错 "xmlns redefined"。必须先检查再添加。
- IguanaTex 不可用: IguanaTex 是 PowerPoint GUI 插件,无法在 CLI/脚本中调用。始终使用 MathJax + Sharp 方案作为等效替代。
- Table column widths: Always specify
colW array to control column proportions. Let the widths sum to roughly 9" (the usable width).
- Don't overuse dark slides: The warm paper aesthetic is the primary identity. Dark slides dilute it.
- Line spacing: Use
lineSpacingMultiple: 1.3–1.5 for body text in cards/callouts for readability.
Verification
Before delivering:
- Confirm slide count matches the outline structure.
- Confirm all slides have consistent section number plates and titles.
- Confirm color palette uses only the defined tokens, not arbitrary hex values.
- Confirm fonts are set to Noto Serif SC (headings), IBM Plex Sans (body), Consolas (formulas).
- Confirm cover and closing slides use light paper background.
- Confirm tables have carbon headers and alternating row fills.
- Confirm the file generates without JS errors.
- Run text extraction QA to verify all content is present.