Skip to content

Class: Presentation ​

Properties ​

opc ​

readonly opc: OpcPackage

Accessors ​

appProperties ​

Get Signature ​

get appProperties(): ExtendedProperties

The deck's extended document properties (docProps/app.xml): the producing application and its version, the company, and the flat TitlesOfParts vector. {} when the deck carries no extended-properties part. The read counterpart of the write-side pptx.company setter — the only one of the four this library writes from a caller's value; the other three it states about itself.

A deliberate subset of the part: see ExtendedProperties for why the statistics (Slides, Words, Paragraphs, …) are not reported.

Returns ​

ExtendedProperties


commentAuthors ​

Get Signature ​

get commentAuthors(): CommentAuthor[]

The deck-wide legacy comment-author registry (p:cmAuthorLst in ppt/commentAuthors.xml), [] when the deck has no comments. Each slide's Slide.comments resolves its @authorId against this list. The 2018 modern comment authors (ppt/authors.xml) are a separate part, read by modernCommentAuthors.

Returns ​

CommentAuthor[]


commentSchema ​

Get Signature ​

get commentSchema(): CommentSchema

Which comment schema this deck uses: 'modern' when it carries any 2018 modernComment_* part (read via Slide.modernComments / modernCommentAuthors), 'legacy' when it carries classic commentN.xml parts (read via Slide.comments / commentAuthors), or 'none'. The two schemas do not coexist in practice, so this tells a consumer which accessor to read without probing both.

Returns ​

CommentSchema


coreProperties ​

Get Signature ​

get coreProperties(): CoreProperties

The deck's core document properties (docProps/core.xml): title, subject, creator, keywords, revision, and the created/modified/lastPrinted timestamps (kept as raw W3CDTF strings). {} when the deck carries no core-properties part. The read counterpart of the write-side pptx.title/subject/author (→ creator)/revision setters.

Returns ​

CoreProperties


customProperties ​

Get Signature ​

get customProperties(): CustomProperty[]

The deck's user-defined custom document properties (docProps/custom.xml) as { name, value } pairs, each value typed from its vt: element (string, number, boolean, or a raw filetime string). [] when the deck carries no custom-properties part. The read counterpart of pptx.setCustomProperty(...).

Returns ​

CustomProperty[]


embeddedFonts ​

Get Signature ​

get embeddedFonts(): EmbeddedFontInfo[]

The deck's embedded font families (p:embeddedFontLst in presentation.xml), [] when it embeds none. Each entry names the typeface and resolves every embedded face's r:id to the absolute partname of its .fntdata binary — the read counterpart to the write-side pptx.embedFont / importSlide({ embedFonts }) carry. An entry whose p:font has no @typeface, or a face whose r:id is missing or dangling, is skipped (faithful degradation, no throw). Read-only.

Returns ​

EmbeddedFontInfo[]


modernCommentAuthors ​

Get Signature ​

get modernCommentAuthors(): ModernCommentAuthor[]

The deck-wide modern (2018) comment-author registry (p188:authorLst in ppt/authors.xml), [] when the deck carries no modern comments. Unlike the legacy commentAuthors, each entry is keyed by a GUID id (plus userId/providerId); each slide's Slide.modernComments resolves its @authorId against this list. Read-only — the writer emits legacy comments.

Returns ​

ModernCommentAuthor[]


presentationPart ​

Get Signature ​

get presentationPart(): Part

The main presentation part (/ppt/presentation.xml), resolved via the package officeDocument relationship.

Returns ​

Part


slides ​

Get Signature ​

get slides(): Slide[]

The slides in presentation order (resolved from p:sldIdLst + the presentation's relationships).

Returns ​

Slide[]


slideSize ​

Get Signature ​

get slideSize(): SlideSize | null

Slide dimensions (p:sldSz), or null if the presentation declares none.

Returns ​

SlideSize | null


tags ​

Get Signature ​

get tags(): Tag[]

The deck-level programmatic tags (p:custDataLst/p:tags on presentation.xml, resolved to ppt/tags/tagN.xml) as { name, val } string pairs, [] when the deck carries none. These are add-in/host metadata with no visible rendering and no writer — read-only, preserved byte-for-byte on round-trip. Per-slide tags are Slide.tags.

Returns ​

Tag[]

Methods ​

appendSlides() ​

appendSlides(source, options): Promise<Slide[]>

Append generator-produced slides onto this deck, binding each to an existing layout, and return the new Slides. This is the hybrid "generate-onto-existing" path: the deck's masters, layouts, theme — and every other untouched part — stay byte-identical (only presentation.xml, its .rels, [Content_Types].xml, and the freshly-added slide/media parts change), because the existing chrome is never regenerated.

source is any slide producer (a TsPptx instance); its authored slides are serialized via SlideSource.extractSlides and spliced in under fresh partnames, with each slide's slideLayout relationship pointed at the layout named by options.layout and its image/hyperlink relationships rebuilt (preserving the body's relationship ids). Insert position follows options.at (see AppendSlidesOptions).

Charts and internal slide-to-slide hyperlinks are carried across: chart parts (chart XML + .rels + embedded workbook) are injected under fresh names, and a slide:N link is repointed at the Nth appended slide's new partname. A chartEx (Office 2016 — waterfall, funnel, treemap, ...) chart carries too, as its own chartEx{N}.xml part behind the MS chartEx rel, with the style and color-style sidecars PowerPoint requires alongside it.

The generator's presentation-level embedded fonts (pptx.embedFont) are also carried into this deck and merged into its p:embeddedFontLst, de-duped by typeface + face slot — so author-side embedded fonts survive the append onto a template that may itself already embed fonts.

Embedded audio/video is carried too: the media part backs the ECMA audio/video rel and the MS-2007 media rel sharing one Target, plus a separate preview image part, with the media content type registered as a Default extension entry (what PowerPoint authors). Online (external-link) video rides as two External rels over the link.

Speaker notes ride across too: a slide authored with addNotes gets a notesSlide part wired back to it, with its hyperlink rels preserved. A notes slide must bind to a notes master, and a template commonly has none, so the generator's is installed (with the theme its .rels needs) — but only when this deck has none of its own, so an existing notes master and its styling always win.

Limitations:

  • An internal link to a source slide outside the appended batch throws (its target has no counterpart in the destination).
  • Appended slides are concrete absolute-positioned content with no placeholder inheritance from the bound layout; the binding governs theme/clrMap resolution and the "based on" link, not placeholder geometry. Author with concrete colours — any schemeClr re-resolves against the destination theme.
  • Source and destination slide sizes must match (no geometry rescale).

Parameters ​

ParameterType
sourceSlideSource
optionsAppendSlidesOptions

Returns ​

Promise<Slide[]>


cloneSlide() ​

cloneSlide(index, options?): Slide

Duplicate the slide at index and insert the copy at options.at (deck order; 0 = first), defaulting to appending at the end when at is omitted or out of range. Returns the new slide. The new slide part copies the source bytes verbatim and shares the source's deck-wide relationship targets (layout, images, media) by copying its .rels; a new presentation→slide relationship and a p:sldId entry are wired up. Marks the presentation part dirty.

What the source page owns is copied rather than shared: its notes slide, charts, SmartArt diagrams and OLE embeddings, each with the subtree under it (a chart's embedded workbook comes along; the image inside its user-shapes drawing stays shared). PowerPoint refuses to open a deck where two slides resolve to one chart or diagram, so this is not tidiness — see page-owned.ts for the rule and the evidence behind it.

Parameters ​

ParameterType
indexnumber
options{ at?: number; }
options.at?number

Returns ​

Slide


importShape() ​

importShape(target, source, shapeIndex, options?): AnyShape

Copy one shape — an autoshape, picture, table/chart graphic frame, connector, or group — from source.shapes[shapeIndex] onto target, returning the new Shape. target must be a slide of this presentation; source may belong to any open presentation.

The lifted subtree is copied self-consistently: every media/chart/embedding it depends on is dragged into this package (deduped against earlier imports from the same source), its r:embed/r:id/… are rewritten to fresh host-slide relationships, and its drawing ids (including a group's children) are reassigned so they cannot collide with the host. With theme: 'preserve' (default) the shape's theme references are baked to literals against the source theme so it renders the same on a foreign host; restyle leaves them symbolic to re-brand; copy brings the XML across untouched — see ImportShapeOptions.

Differing slide sizes need { rescale } (see ImportShapeOptions.rescale); a lifted preserve placeholder is baked self-contained and demoted to a plain shape (see ImportShapeOptions.theme), so it neither re-inherits from nor collides with the host. A shape's build animation lives in the slide-scoped p:timing, not in its subtree, so the shape lands static unless { carryAnimation: true } opts in (see ImportShapeOptions.carryAnimation).

Parameters ​

ParameterType
targetSlide
sourceSlide
shapeIndexnumber
optionsImportShapeOptions

Returns ​

AnyShape


importShapes() ​

importShapes(target, source, shapeIndices, options?): AnyShape[]

Batch form of importShape: copy several shapes from one source slide onto target in the given order. Media/chart/embedding parts shared by the lifted shapes (and by earlier imports from the same source deck) are copied once via the copy registry, and shared images resolve to a single host-slide relationship. Returns the new Shapes in shapeIndices order.

Parameters ​

ParameterType
targetSlide
sourceSlide
shapeIndicesnumber[]
optionsImportShapeOptions

Returns ​

AnyShape[]


importSlide() ​

importSlide(source, index, options?): Slide

Append a copy of source.slides[index] to this presentation and return it.

Unlike cloneSlide (same-deck duplicate), this copies a slide across a package boundary: it brings the connected sub-graph the slide depends on — its slideLayout → slideMaster → theme, plus any media, charts, and embeddings — into this package under fresh partnames, rewriting every partname, relationship id, and content-type registration so the result is a self-consistent OPC package. Parts of this (target) package that are not touched stay byte-identical, matching cloneSlide's fidelity contract.

Only the layout(s) actually used by imported slides are copied; the imported master's p:sldLayoutIdLst is pruned to exactly those, mirroring how PowerPoint's "Reuse Slides" brings a slide across. Parts shared by repeated imports from the same source deck are copied once and reused — every part except the page itself. Importing the same source slide twice yields two independent copies over one shared layout/master/theme, which is what lets a deck show one page twice (verbatim, then edited).

With { theme: 'preserve' } the slide's source theme is instead flattened into the slide XML and the slide is bound to this deck's existing master/layout; with { theme: 'restyle' } the slide is bound to this deck's master/layout with its theme references left symbolic, so it re-brands to the destination palette — see ImportSlideOptions.

By default the source slide size must equal this presentation's. Pass { rescale: 'fit' | 'stretch' } to rescale the imported geometry onto this deck's canvas instead (geometry only, not fonts or line widths). Source notes are dropped unless you pass { importNotes: true }.

A jump link on the page must land on a page an earlier import from the same source already brought across, the rule importSlides applies to a batch: a link to any other page throws import/unresolved-slide-link. Like that check, a missing or unparseable source part is found before anything is copied, so a refused import leaves this deck unchanged.

Parameters ​

ParameterType
sourcePresentation
indexnumber
optionsImportSlideOptions

Returns ​

Slide


importSlideMasters() ​

importSlideMasters(source, options?): ImportedSlideMaster[]

Graft slide master(s) from another open package into this one and return what was copied. Unlike importSlide — which brings a master across only as the dependency of an imported slide and prunes it to the one layout that slide uses — this copies a master together with its whole layout family and attaches it to no slide: the master and its layouts land in this deck's layout gallery (PowerPoint's Insert ▸ New Slide / Layout picker) without changing any existing slide.

It is the "ship a brand template's layouts into a generated deck" capability, kept brand-agnostic here: the caller supplies the source .pptx. Each grafted master is wired into p:sldMasterIdLst (so renderers treat it as active) and its p:sldLayoutIdLst is rebuilt to list exactly the copied layouts; the connected theme/media/tag parts come across under fresh partnames, and parts shared with earlier imports from the same source are reused (the copy registry), so a re-call is idempotent. Untouched parts of this package stay byte-identical, matching importSlide's fidelity contract.

options.masters / options.layouts narrow what is grafted; by default every master and every layout comes across. The source and destination slide sizes must match unless options.requireEqualSize is false (see ImportSlideMastersOptions).

Presentation-level parts are carried only on request: embedded fonts via options.embedFonts and table styles via options.tableStyles. By default a grafted master is appended after the deck's existing masters; options.primary moves the grafted masters to the front so the deck presents as their theme (see ImportSlideMastersOptions). Geometry is never rescaled: unlike importSlide, importSlides and importShape, this method takes no rescale option.

Parameters ​

ParameterType
sourcePresentation
optionsImportSlideMastersOptions

Returns ​

ImportedSlideMaster[]


importSlides() ​

importSlides(requests): Slide[]

Import selected pages from one or more loaded source presentations as one batch. Each imported page lands at its outputIndex in the complete destination slide list after the batch, and the returned array is parallel to requests — result[i] is the page requests[i] asked for, whatever order the output positions were given in.

Everything is checked before a single byte of this deck moves: every request names an existing source page, final output positions are unique, each source has this deck's slide size, and a read-only dry run of the copy proves every part it would reach is present. A batch therefore either applies in full or leaves this deck byte-identical, where a per-page loop of importSlide can leave a half-stitched deck behind.

The batch also decides what a slide → slide link means: an internal link on a selected page must target another selected page (or one this deck already contains via an earlier import from that source), and is rewritten to the fresh partname — importing page 3 of 10 does not drag pages 1–2 across as dependencies, and never strands the link. This mirrors appendSlides' import/unresolved-slide-link, which the write side already enforces for generator decks.

One request is one output page, so naming the same source page in several requests is how you ask for several independent copies of it — the page part is the one thing an import never shares, exactly as in importSlide. Everything under it (layout, master, theme, media) is still copied once and shared. Where such a page is the target of a slide → slide link, the link resolves to one of its copies: pages duplicated together are copied in lockstep and link to their round-mates, and a link into a page requested only once always lands on that single copy.

Speaker notes travel per request: { importNotes: true } carries that page's notesSlide part across, wired to the new page and bound to a single notesMaster under the same 0..1 rule importSlide and appendSlides follow — the destination's own master wins when it has one. Notes are part of the up-front dry run too, so a batch that would fail carrying them is refused with the deck still byte-identical. A page named in several requests gets its own copy of its notes each time, as of everything else that page owns.

embedFonts and rescale travel per request as well, and both are whole-deck decisions wearing a per-page spelling, so the batch reconciles them before it moves anything. A source deck's embedded fonts are carried once when any of its requests asks for them (the list does not record which page uses which face, so there is nothing finer to carry), and the font parts are part of the up-front dry run like everything else. rescale must agree across every request naming one source: a 'copy' import rescales the imported layout and master alongside the page, and those are shared, so a batch that rescaled one page of a source and not another would leave the second bound to a rescaled master. Disagreement is import/rescale-conflict rather than a silent pick.

Scope: pages come across under 'copy' theme semantics (their own layout → master → theme subgraph, shared parts deduped via the copy registry). There is still no batch spelling for theme, carryMasterGraphics or remapLiterals; use importSlide when you need one of those.

Parameters ​

ParameterType
requestsreadonly ImportSlidesRequest[]

Returns ​

Slide[]


layouts() ​

layouts(): LayoutHandle[]

The deck's slide layouts, in master then layout order — the gallery a new slide can bind to. Each LayoutHandle addresses one layout for appendSlides; the name is its p:cSld@name. Read-only enumeration: it copies nothing and leaves the package byte-identical.

Returns ​

LayoutHandle[]


masters() ​

masters(): SlideMaster[]

The deck's slide masters, in p:sldMasterIdLst order, as modeled SlideMasters — the typed read model over the shared chrome (each master's colour map, theme, placeholders, and the layouts built on it). Walk pres.masters()[i].layouts for the rich layout model, or use layouts for the flat LayoutHandle gallery appendSlides binds to. Read-only: it copies nothing and leaves the package byte-identical.

Returns ​

SlideMaster[]


removeSlide() ​

removeSlide(index): string

Remove the slide at index (deck order) and return its former partname. The p:sldId entry and the presentation→slide relationship are dropped, the slide part and its .rels are deleted, and any part the slide privately owned (its notes slide, slide-only media, charts/embeddings) that no remaining part references is pruned too — recursively. Shared deck chrome (layout, master, theme, …) is never pruned, so the deck stays renderable; removing every slide leaves a valid master/layout-only package (a template shell). The slide also leaves every custom show and section it was in, which stay even when that empties them, as PowerPoint leaves them.

Untouched parts stay byte-identical, matching the package fidelity contract. Throws when there is no slide at index.

Parameters ​

ParameterType
indexnumber

Returns ​

string


save() ​

save(): Promise<Uint8Array<ArrayBufferLike>>

Re-emit the package; untouched parts stay byte-identical (see OpcPackage.save).

Returns ​

Promise<Uint8Array<ArrayBufferLike>>


fromPackage() ​

static fromPackage(opc): Presentation

Wrap an already-loaded OPC package (e.g. from the lower-level API).

Parameters ​

ParameterType
opcOpcPackage

Returns ​

Presentation


fromTemplate() ​

static fromTemplate(input, options?): Promise<Presentation>

Open a PowerPoint template (.pptx or .potx) and return it as an empty deck shell ready to author onto: its slide masters, layouts, and theme are kept byte-identical, while any sample slides the template carried are stripped so only the shared chrome remains.

Use it to build a fresh deck on a corporate template without rebuilding the masters in code: discover the bindable layouts with layouts, then author slides with a generator sized to match the template and graft them in with appendSlides (which enforces an equal slide size). Saving yields an editable .pptx that reuses the template's authored chrome verbatim.

ts
const deck = await Presentation.fromTemplate(templateBytes) // .pptx or .potx
deck.layouts().map(l => l.name)                             // discover layouts
await deck.appendSlides(pptx, { layout: 'Title and Content' })
const out = await deck.save()                               // editable .pptx

A .potx package declares its main part with the template content type; by default that override is flipped to the editable presentation type so the saved output opens as a normal deck. Pass keepTemplateContentType: true to preserve the template type. A .pptx input needs no flip, and a template that already carries zero slides makes the strip a no-op.

Parameters ​

ParameterType
inputOpcInput
optionsFromTemplateOptions

Returns ​

Promise<Presentation>


load() ​

static load(input): Promise<Presentation>

Open a .pptx from bytes and wrap it as a navigable Presentation.

Parameters ​

ParameterType
inputOpcInput

Returns ​

Promise<Presentation>