Skip to content

fix(export): create the output directory for every format - #2745

Open
stn1slv wants to merge 1 commit into
slidevjs:mainfrom
stn1slv:fix/export-create-output-dir
Open

stn1slv wants to merge 1 commit into
slidevjs:mainfrom
stn1slv:fix/export-create-output-dir

Conversation

@stn1slv

@stn1slv stn1slv commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

What

exportSlides now creates the directory of --output once, before the browser starts, so every format can write into a path that does not exist yet.

Why

Whether a missing output directory is an error depends on the format:

slidev export slides.md --format pdf  --output dist/slides.pdf    # works, creates dist/
slidev export slides.md --format pptx --output dist/slides.pptx   # ENOENT

The writers disagree about whose job it is. page.pdf({ path }) creates the directory, since Playwright creates parent directories, and genPagePng calls fs.mkdir(..., { recursive: true }), which Markdown also goes through. Everything that calls fs.writeFile directly does not, which covers both PowerPoint formats and, less obviously, --format pdf --per-slide: that path renders each slide into a buffer, merges them and writes the result itself, so it never touches the Playwright call that would have created the directory.

Tested on v53.0.0 against a deck with no dist/ folder:

Command Before After
--format pdf works works
--format pdf --per-slide ENOENT works
--format png works works
--format md works works
--format pptx ENOENT works
--format pptx-editable ENOENT works

dist/ is where most people put an export, and it is what the docs use in their examples, so this is easy to hit on a fresh checkout.

Tests

packages/slidev/node/commands/export.test.ts is new, and it is the first test around exportSlides. A real export needs a browser and a dev server, but the test never gets that far. importPlaywright asks getRoots for the user root, and that throws without an entry, so every call rejects before anything renders. The directory is created before that point, so the assertion still says whether the step ran. Each rejection is matched against that known failure, otherwise an error thrown by the mkdir itself would satisfy the test instead of failing it. Four of the five cases fail without the one-line fix, and the file runs in milliseconds with no browser.

Notes

The fs.mkdir call sits before chromium.launch, so an unwritable path fails straight away instead of after the whole deck has rendered. It does nothing when the directory already exists, or when --output has no directory part.

For PNG, --output names a directory rather than a file, so this creates its parent and the existing fs.mkdir in genPagePng still creates the directory itself.

A narrower fix would be to add the same call at each failing write site, in genPagePdfPerSlide, genPagePptx and packages/slidev/node/commands/pptx/index.ts. That leaves the shared path alone but keeps the difference between formats. I am happy to switch if you prefer it.

pnpm lint passes. vitest run reports the same 11 failures with and without this change, in api-snapshots.test.ts and node/syntax/integration.test.ts, so they look like snapshot drift on main.

The writers that call `fs.writeFile` directly failed with ENOENT when
the directory of `--output` did not exist, so `dist/slides.pptx` broke
while one-piece PDF worked.
@netlify

netlify Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for slidev ready!

Name Link
🔨 Latest commit eed553f
🔍 Latest deploy log https://app.netlify.com/projects/slidev/deploys/6aaa3bc07a4a080008471b66
😎 Deploy Preview https://deploy-preview-2745--slidev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@pkg-pr-new

pkg-pr-new Bot commented Sep 16, 2026

Copy link
Copy Markdown

Open in StackBlitz

@slidev/client

npm i https://pkg.pr.new/@slidev/client@2745

create-slidev

npm i https://pkg.pr.new/create-slidev@2745

create-slidev-theme

npm i https://pkg.pr.new/create-slidev-theme@2745

@slidev/parser

npm i https://pkg.pr.new/@slidev/parser@2745

@slidev/cli

npm i https://pkg.pr.new/@slidev/cli@2745

@slidev/types

npm i https://pkg.pr.new/@slidev/types@2745

commit: eed553f

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant