Skip to content

Export & Print

The Svelte viewer can turn slides into a range of formats and save the document back to .pptx. Everything is available both from the built-in toolbar's export menu (with a progress modal and cancellation) and programmatically on the component instance.

Supported formats

FormatPipeline
PNGhtml2canvas-pro rasterisation (dynamically imported on first use)
PDFjspdf (dynamically imported) + rasterisation, multi-page, one slide per page
GIFAnimated GIF frame encoder over rasterised frames
WebMMediaRecorder over a canvas capture stream (codec picked from the shared WebM candidates)
SVGVector export straight from the parsed data model (no rasterisation), via standalone functions
PrintShared print document (slides / handouts / notes / outline) in a hidden same-origin iframe
PPTXCore serializer via save(format), downloadAs, downloadPptx ('pptx' | 'ppsx' | 'pptm')

Lazy dependencies

html2canvas-pro and jspdf are dynamic imports: the first raster/PDF export pays a one-time load cost, and apps that never export never ship them to the client.

Raster and video export

All methods live on the component instance (bind:this):

svelte
<script lang="ts">
	import { PowerPointViewer, type PowerPointViewerApi } from 'pptx-svelte-viewer';

	let { bytes }: { bytes: Uint8Array } = $props();
	let viewer = $state<PowerPointViewerApi>();
	let progress = $state('');

	async function exportPdf() {
		await viewer?.exportPdf({
			onProgress: (current, total) => (progress = `${current}/${total}`),
		});
	}
</script>

<PowerPointViewer source={bytes} bind:this={viewer} />
<button onclick={() => viewer?.exportSlidePng()}>PNG (current slide)</button>
<button onclick={() => viewer?.copySlideAsImage()}>Copy as image</button>
<button onclick={exportPdf}>PDF {progress}</button>

ExportPdfOptions

OptionTypeDefaultDescription
onProgress(current: number, total: number) => void-Capture-phase progress callback.
signalAbortSignal-Abort the export early (checked between slides).

ExportGifOptions

OptionTypeDefaultDescription
slideDurationMsnumber2000Duration each slide is shown.
slideTimingsMsnumber[]-Per-slide duration overrides (index maps to slide index).
maxDimensionnumber960Longest allowed output side in pixels; frames scale down proportionally.
onProgress(current: number, total: number) => void-Capture-phase progress callback.
signalAbortSignal-Abort the export early.

ExportVideoOptions

OptionTypeDefaultDescription
slideDurationMsnumber3000Duration each slide is shown.
slideTimingsMsnumber[]-Per-slide duration overrides.
fpsnumber30Recording frame rate.
videoBitsPerSecondnumber5_000_000Recorder bitrate.
onProgress(current: number, total: number) => void-Capture-phase progress callback.
onRecordProgress(current: number, total: number) => void-Recording-phase progress callback.
signalAbortSignal-Abort between slides and between frames.

Print

print(options) assembles the shared print document and opens the browser print dialog. The default print surface is a hidden same-origin iframe, so no popup window is involved. It resolves true once the print surface opened.

ts
await viewer?.print({ printWhat: 'handouts', slidesPerPage: 6, colorMode: 'grayscale' });
await viewer?.print({
	printWhat: 'slides',
	slideRange: 'custom',
	customRangeFrom: 2,
	customRangeTo: 5,
});

PrintOptions is any subset of the shared print settings:

OptionTypeDefaultDescription
printWhat'slides' | 'handouts' | 'notes' | 'outline''slides'What to print.
orientation'landscape' | 'portrait''landscape'Page orientation.
colorMode'color' | 'grayscale' | 'blackAndWhite''color'Colour treatment.
frameSlidesbooleanfalseDraw a border around each slide.
slidesPerPagehandout slides-per-page count6Handout layout density.
slideRange'all' | 'current' | 'custom''all'Which slides to include.
customRangeFromnumber1Custom range start (1-based).
customRangeTonumber1Custom range end (1-based).

Popup blockers

The default iframe surface is immune to popup blockers. A custom window.open-based opener (injectable at the controller level) is not; when blocked, the promise resolves false.

Saving the document

MethodSignatureDescription
save(format?: PptxSaveFormat) => Promise<Uint8Array>Serialise the (edited) slides via the core handler.
getContent() => Promise<Uint8Array>Alias of save() from the shared viewer contract.
downloadAs(format: PptxSaveFormat, fileName?: string) => Promise<void>Save + browser download in pptx, ppsx, or pptm.
downloadPptx(fileName?: string) => Promise<void>Save + download as .pptx with a default name.
packageForSharing(fileName?: string) => Promise<void>Assemble and download the sharing package.

SVG: standalone functions

SVG export is vector output straight from the parsed data model, exported as plain functions from the package root (no component instance needed):

ts
import { exportSlideToSvg, exportSlideToSvgBlob, exportSlideAsSvg } from 'pptx-svelte-viewer';
FunctionSignatureReturns
exportSlideToSvg(slide, width, height, options?)SVG markup string
exportSlideToSvgBlob(slide, width, height, options?)Blob (image/svg+xml)
exportSlideAsSvg(slide, slideIndex, width, height, options?)triggers a download
exportAllSlidesToSvg(data, options?)string[]
exportAllSlidesToSvgBlobs(data, options?)Blob[]

slide is a PptxSlide (get one from the instance's getSlides() / getActiveSlide()); width/height are the canvas size in pixels from the onload payload. The exportAll* variants take the full parsed PptxData from a pptx-viewer-core handler.

Options (SvgExportSingleSlideOptions / SvgExportAllOptions):

OptionTypeDefaultDescription
includeHiddenbooleanfalseInclude hidden slides when exporting all.
slideIndicesnumber[]allSlide indices to export (0-based).
defaultFontFamilystring-Fallback font family for elements without one.
defaultFontSizenumber-Fallback font size in points.
ts
const slide = viewer?.getActiveSlide();
if (slide) {
	const svg = exportSlideToSvg(slide, canvasSize.width, canvasSize.height);
	// e.g. inline it, upload it, or hand it to a design tool
}

Pipeline limitations

Raster export inherits the html2canvas-pro constraints (see Limitations): some CSS features (backdrop-filter, CSS 3D transforms) lose fidelity in capture, mix-blend-mode is approximated, and canvas size is capped by the browser's maximum, bounding the export resolution. The SVG path avoids rasterisation entirely but covers the data model, not arbitrary DOM styling.

Released under the Apache-2.0 License.