Fix broken fonts in PowerPoint — in one click.
EN · Font won't change in PowerPoint? We fix it.
RU · Шрифт не меняется в PowerPoint? Мы починим.
UK · Шрифт не змінюється в PowerPoint? Ми виправимо.
ZH · PowerPoint 中字体无法更改?我们来修复。
DE · Schriftart ändert sich nicht in PowerPoint? Wir reparieren es.
ES · ¿La fuente no cambia en PowerPoint? Lo arreglamos.
FR · La police ne change pas dans PowerPoint ? On répare ça.
I'm currently writing academic papers, and part of the process involves redrawing figures in PowerPoint so they can later be inserted into Word. Don't ask me why — that's just how the workflow goes.
At some point I ran into a maddening issue: when you import shapes or figures into .pptx, the text inside them refuses to change font. You select everything, pick Arial — nothing happens. The font dropdown shows one thing, the slide shows another. It's completely broken.
This isn't a one-off thing. When you have dozens of figures to process, doing it manually is not an option. I've always solved problems like this with code — so I dug into the .pptx XML, found the root causes (CJK language attributes, theme font references, broken inheritance chains), and built a tool to fix it automatically.
That tool is PowerPain.
PowerPoint silently ignores your font changes in these common scenarios:
| Problem | Root Cause | What PowerPain Does |
|---|---|---|
| Font doesn't change via UI | lang="zh-CN" → PowerPoint reads <a:ea>, ignores <a:latin> |
Sets lang="en-US", writes explicit <a:latin> and <a:ea> |
| Theme font overrides everything | +mj-lt / +mn-lt references in run properties |
Replaces all theme references with target font |
| CJK font in theme | 等线, 等线 Light in majorFont/minorFont |
Normalizes theme1.xml directly |
| Layout/master inheritance | Fonts defined in layouts override slide-level settings | Processes all layers: slides, layouts, masters, themes |
- One-click fix — upload
.pptx, get fixed file back - 100% client-side — all processing runs in your browser via JSZip + DOMParser, files never leave your device
- Deep normalization — processes
a:rPr,a:defRPr,a:endParaRPracross all XML files - Theme repair — fixes
majorFont/minorFontin theme files - 11 font choices — Arial, Calibri, Times New Roman, Helvetica, Verdana, Tahoma, Georgia, Segoe UI, Roboto, Open Sans, Inter
- Zero upload — nothing is sent to any server, ever
- 7 languages — EN, RU, UK, ZH, DE, ES, FR
- Privacy-first — no accounts, no tracking, no analytics
- Modern UI — dark theme, PowerPoint color palette, responsive design
| Layer | Technology | Why |
|---|---|---|
| Runtime | Bun | Fastest JS runtime, native TypeScript |
| Static Server | Hono | 14KB, fastest Bun-native HTTP framework |
| PPTX Processing | JSZip + DOMParser (browser) | Client-side ZIP + XML manipulation, no server needed |
| Frontend | Vanilla HTML/CSS/JS | No framework overhead for a single page |
| QR Code | qrcode | MIT-licensed, SVG generation |
All dependencies are MIT-licensed.
# Clone
git clone https://github.com/yatskovskyi/PowerPain.git
cd PowerPain
# Install
bun install
# Run
bun run startbun run devPowerPain/
├── src/
│ ├── server.ts # Hono server — static files, QR API, security headers
│ └── public/
│ ├── index.html # Single-page UI with full SEO
│ ├── style.css # Dark theme, PowerPoint palette
│ ├── app.js # Client-side PPTX processing, i18n, drag&drop
│ ├── jszip.min.js # JSZip library for in-browser ZIP handling
│ ├── 404.html # Custom 404 page
│ ├── robots.txt # Search engine + AI bot rules
│ ├── sitemap.xml # XML sitemap
│ └── img/ # Favicon, OG image, donate photo
├── package.json
├── tsconfig.json
├── LICENSE # MIT
└── README.md
All PPTX processing happens entirely in the browser. The server only serves static files and the donation QR code.
- User drops a
.pptxfile JSZipunpacks the archive in the browserDOMParserparses each XML file (slides, layouts, masters, themes)- JavaScript normalizes fonts: fixes
langattributes, replaces theme references (+mj-lt,+mn-lt), sets explicit<a:latin>and<a:ea>typefaces XMLSerializerconverts the DOM back to XML stringsJSZiprepacks everything into a new.pptxblob- User downloads the fixed file — nothing was ever uploaded
The server is minimal — it only has one API endpoint:
Returns the donation QR code as SVG.
| Variable | Default | Description |
|---|---|---|
PORT |
3000 |
Server port |
- Open a PowerPoint file with CJK font issues
- Upload it to PowerPain
- Download the fixed file
- Open in PowerPoint — fonts should now be changeable
- Check:
langattributes should been-US, no+mj-ltreferences remain
- CSP — strict Content-Security-Policy (self + Google Fonts only)
- HSTS — enforced HTTPS with 1-year max-age
- X-Frame-Options: DENY — clickjacking protection
- No server processing — zero attack surface for file uploads
- Rate limiting — dotfile / sensitive path blocking
- Full meta tags (OG, Twitter Card, JSON-LD)
FAQPagestructured data for rich snippetsWebApplicationschema markup- Hreflang tags for 7 languages
- XML sitemap
robots.txtwith AI crawler instructions
Issues and PRs welcome at github.com/yatskovskyi/PowerPain.
MIT — Dmytro Yatskovskyi
If PowerPain saved your day — consider supporting the project
USDT (TRC-20): TBxEquczDy6ZSRPAyYrNbczoaP9YThaJuZ