This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
pptx-glimpse is a TypeScript library that converts PPTX slides to SVG / PNG.
Input: Buffer | Uint8Array, Output: SVG string or PNG Buffer.
npm run build # Build with tsup (CJS + ESM + .d.ts)
npm run test # Run all tests with vitest
npm run test -- src/utils/emu.test.ts # Run a single test file
npm run test:watch # Watch mode for tests
npm run lint # ESLint check
npm run lint:fix # ESLint auto-fix
npm run format # Prettier formatting
npm run format:check # Prettier check
npm run typecheck # Type check with tsc --noEmit
npm run render # Test rendering with tsx scripts/test-render.ts
npm run inspect # Inspect PPTX internal XML (e.g., npm run inspect -- file.pptx slide1)
npm run dev -- file.pptx # Live preview dev server (auto-reload on src/ changes)CI consists of 4 jobs:
- lint:
knip→lint→format:check→typecheck(Node 22 only, 1回実行) - test:
testwith coverage →build→ package verification (Node 20/22/24, coverage report on Node 22) - vrt: Snapshot VRT (Docker-based, self-comparison)
- libreoffice-vrt: LibreOffice VRT (generates fixtures and reference images via Docker)
Data flow: PPTX binary → Parser (ZIP extraction + XML parsing) → Intermediate model → Renderer (SVG generation) → PNG conversion (optional)
src/parser/— Builds intermediate model from PPTX via ZIP extraction (fflate) and XML parsing (fast-xml-parser)src/model/— TypeScript interfaces for the intermediate model (Slide, Shape, Fill, Text, Theme, Table, Chart, Image, Line, Effect, Presentation, etc.)src/renderer/— Generates SVG strings from the intermediate model. Includes preset shape definitions ingeometry/, plus dedicated renderers for tables, charts, and imagessrc/color/— Theme color resolution (schemeClr → colorMap → colorScheme) and color transformations (lumMod/tint/shade)src/font/— Font loading (system font scanning), font mapping (proprietary → OSS alternatives), text measurement and text-to-SVG-path conversion viaopentype.jssrc/png/— SVG → PNG conversion using sharpsrc/data/— Font metrics data (fallback character width information)src/utils/— EMU ↔ pixel conversion (1 inch = 914400 EMU, 96 DPI) and text wrapping
Entry point: src/index.ts exports convertPptxToSvg, convertPptxToPng, warning utilities (getWarningSummary, getWarningEntries), font utilities (collectUsedFonts, DEFAULT_FONT_MAPPING, createFontMapping, getMappedFont), and related types.
- SVG uses inline attributes only — No CSS classes. sharp (librsvg) does not correctly interpret CSS
isArrayconfiguration in fast-xml-parser is required — Tags such assp,pic,p,rmust be returned as arrays even for single elements (ARRAY_TAGSinxml-parser.ts)- EMU units & branded types — PPTX internal coordinates use EMU (English Metric Units). Convert with
emuToPixels(). A 16:9 slide is 9144000×5143500 EMU = 960×540 px. Model fields use branded types (Emu,Pt,HundredthPtinsrc/utils/unit-types.ts) to prevent unit confusion at compile time. UseasEmu(),asPt(),asHundredthPt()to create branded values from raw numbers - Background fallback — Backgrounds are resolved in order: slide → slide layout → slide master
Visual regression tests for rendering output. When modifying the parser or renderer, always check whether VRT updates are needed.
shared-fixtures/ # Real PPTX files shared by e2e and VRT
├── real-basic-theme.pptx
└── real-product-page.pptx
vrt/
├── compare-utils.ts # Shared image comparison utilities
├── snapshot/ # Standard VRT (self-comparison, Docker-based)
│ ├── vrt-cases.ts # Shared test case definitions (VRT_CASES + SHARED_FIXTURE_CASES)
│ ├── regression.test.ts # Test file
│ ├── create-fixtures.ts # Fixture generation script
│ ├── update-snapshots.ts # Snapshot update script
│ ├── docker-run.sh # Docker entrypoint (npm ci + exec)
│ ├── diffs/ # Diff images on test failure (gitignored)
│ ├── fixtures/ # VRT PPTX fixtures (dynamically generated)
│ └── snapshots/ # Reference snapshot images (Docker-generated)
└── libreoffice/ # LibreOffice VRT
├── regression.test.ts # Test file
├── create_fixtures.py # Fixture generation (Python, Docker)
├── update_snapshots.sh # Snapshot update (Docker)
├── diffs/ # Diff images on test failure (gitignored)
├── fixtures/ # Dynamically generated in CI
└── snapshots/ # Dynamically generated in CI
Snapshots are generated inside a Docker container (Node.js + sharp + fonts) to ensure consistent rendering across macOS and Linux. Both snapshot generation and CI test execution use the same Docker image.
npm run vrt:snapshot:docker-build # Build the Docker image
npm run vrt:snapshot:update # Generate fixtures + snapshots (Docker required)When changes to the parser, renderer, or model affect rendering output:
- Update fixtures (if adding new features or modifying existing fixtures): Edit
vrt/snapshot/create-fixtures.tsand runnpm run vrt:snapshot:update - Update snapshots:
npm run vrt:snapshot:updateregenerates both fixtures and snapshots in Docker - Verify tests: Confirm VRT tests pass in CI after pushing
When adding a new rendering feature, all 3 of the following must be updated:
vrt/snapshot/vrt-cases.ts— Add a new entry to theVRT_CASESarrayvrt/snapshot/create-fixtures.ts— Add a fixture creator function and register it inFIXTURE_CREATORSvrt/snapshot/snapshots/— Regenerate snapshots withnpm run vrt:snapshot:update
VRT_CASES is the single source of truth shared by both create-fixtures.ts and regression.test.ts. If a case is added to VRT_CASES without a corresponding creator in FIXTURE_CREATORS, the fixture generation script will fail with an error.
Common mistake: Modifying the parser or renderer but forgetting to update snapshots, causing VRT tests to fail. Always run npm run vrt:snapshot:update after making changes that affect rendering.
Renders PPTX files generated with python-pptx using LibreOffice and compares them against pptx-glimpse output. Docker ensures a consistent environment.
npm run vrt:lo:docker-build # Build the Docker image
npm run vrt:lo:update # Generate fixtures + reference images (Docker required)
npm run test # Run tests (including LibreOffice VRT)PIXEL_THRESHOLD = 0.3(per-pixel color difference tolerance)MISMATCH_TOLERANCE = 0.05(allows up to 5% pixel mismatch)
Since LibreOffice ≠ PowerPoint, differences in font rendering and anti-aliasing are tolerated. The goal is to detect obvious rendering omissions and structural errors.
LibreOffice VRT tests are automatically skipped in environments without Docker. npm run test will pass without issues.
This project uses Changesets for version management and releases.
When a PR includes changes that affect the published package (bug fixes, new features, breaking changes), run npx changeset before committing and select the appropriate version bump type (patch / minor / major) with a summary of the change. This creates a markdown file in .changeset/ that should be committed with the PR.
Changes that do NOT require a changeset: docs-only updates, CI config, test-only changes, refactoring with no public API impact.
- PR with changeset is merged to main
release.yml(changesets/action) automatically creates a "Version Packages" PR that bumpspackage.jsonand updatesCHANGELOG.md- "Version Packages" PR is reviewed and merged
release.ymlrunsnpx changeset publish— creates av{version}tag and publishes to npm with provenance (Trusted Publishing)
- Prettier: double quotes, semicolons, trailing commas, printWidth 100
- ESLint: unused variables with
_prefix are allowed - ESM (
"type": "module") — imports require.jsextension - Tests are colocated with source files (
src/parser/slide-parser.test.ts, etc.)