Functions
child
function child(record: PptRecord | undefined, type: number): PptRecord | undefined
The first child of a type.
childrenOf
function childrenOf(record: PptRecord | undefined, type: number): readonly PptRecord[]
Every child of a type, immediate children only.
colorFromIndexStruct
function colorFromIndexStruct(value: number, scheme: ColorScheme | undefined): ResolvedColor | undefined
A four-byte colour field, which is two different things told apart by a byte.
The high byte is not part of the colour. `0xFE` means the three below it are
a literal `RGB`; `0x00`–`0x07` mean they are to be ignored and the byte is an
index into the colour scheme; `0xFF` means the field says nothing at all.
Reading the whole word as a colour gives a deck whose every text run is one
of eight shades of near-black, which looks plausible enough to ship.
currentEditOffset
function currentEditOffset(currentUser: Uint8Array | undefined): number | undefined
The offset the `Current User` stream points at, if it can be believed.
The stream *is* the atom — its eight-byte record header is the first thing in
it, with no length in front — and the four bytes after that header are the
atom's own stated size rather than anything to read. Both of those are easy
to get wrong by one field, and being wrong by one field here reads the header
token as a version number, fails the check, and silently falls back to
scanning for the last save.
currentUserSaysEncrypted
function currentUserSaysEncrypted(currentUser: Uint8Array | undefined): boolean
Whether the `Current User` stream says the presentation is enciphered.
descendants
function descendants(record: PptRecord, type: number): Generator<PptRecord>
Every record of a type at any depth, the record itself included.
find
function find(record: PptRecord | undefined, type: number): PptRecord | undefined
The first record of a type at any depth.
flag
function flag(props: TextProps | undefined, field: string, bit: number): boolean | undefined
A flag out of a bit-mask property, distinguishing "off" from "not stated".
The whole subtlety of the format is in this function. `bold` is bit 0 of the
`flags` field, and that field is *itself* selected by bits 0-15 of the mask —
so a run whose mask has bit 0 set and whose flags have bit 0 clear says "not
bold" and overrides the master, while a run whose mask lacks bit 0 says
nothing and inherits. Collapsing the two makes every inherited bold run
plain, which on a template that bolds its titles is the whole deck.
levelsForKind
function levelsForKind(styles: MasterStyles, kind: number): readonly StyleLevel[]
The levels stated for a kind of text, falling back the way PowerPoint does.
A master states the kinds its design uses and no others, so asking for the
centred body of a deck that has none must give the body rather than nothing:
nothing means the browser's default face at the browser's default size, which
is never what the deck looks like.
levelStyleOf
function levelStyleOf(styles: MasterStyles, placeholderType: string | undefined, level: number, context: { scheme: ColorScheme | undefined; fonts: FontCollection; }): TextLevelStyle | undefined
The master's typography for one role at one outline level.
The `.ppt` half of the ladder a paragraph climbs. In the modern format the
rungs are the run, the shape's list style, the layout's and the master's; in
this one there is no layout, so the ladder is shorter — the run's own
properties over the master's level style — but the master's rung carries
exactly the same information and matters exactly as much. A title in a deck
of this age states nothing about itself at all: not its size, not its colour,
not its face. All of that is here, and a reader that skips it renders every
presentation ever made in Times New Roman at twelve points.
openPpt
function openPpt(source: ByteSource, options?: OpenPptOptions): Promise<PptxDocument>
openPptx
function openPptx(source: ByteSource, options?: OpenOptions): Promise<PptxDocument>
Opens a PowerPoint presentation.
Reads the table of contents: slide order and canvas size. Each slide is a
separate package part and is therefore parsed on demand: showing the first
slide need not touch the other ninety-nine.
parseBackground
function parseBackground(root: XmlElement): DiagramFill | undefined
Reads `p:cSld/p:bg`: what the slide, layout or master is drawn on.
Two spellings. `p:bgPr` states the fill outright; `p:bgRef` names an entry of
the theme's background list and the colour to fill its placeholder with,
exactly as a shape's `a:fillRef` does — so the same resolution serves both,
and the reference is returned as a solid fill of the referenced colour when
the theme is not at hand.
parseDiagramShapes
function parseDiagramShapes(root: XmlElement): Shape[]
The shapes of a SmartArt drawing, as slide shapes.
A `dsp:sp` is a `p:sp` under another namespace — same transform, same
geometry, same text body — so a deck needs no second renderer for SmartArt:
the shapes go through the one that draws everything else, and inherit its
text layout and its effects with them.
That is why this is not `parseDiagramDrawing` from `@genomdev/office-core`,
which reads the same part into a model of its own. A document and a workbook
have no general shape renderer to hand the result to; a deck does, and using
it draws more rather than less.
parseGraphicFrame
function parseGraphicFrame(element: XmlElement, ns?: string): Shape | undefined
Reads `p:graphicFrame`: a chart, a table or a diagram on a slide.
Only the chart is followed further, because only the chart has a renderer
already — the frame itself is read whatever it holds, so that the space it
takes is not silently lost.
Exported because a `.ppt` needs it and has no slide to reach it through.
PowerPoint 2007 and later hide the modern form of a table or a diagram inside
a binary presentation as a small package of their own, whose one part holds
a `p:E2oFrame` — a graphic frame under another name, with the same children
in the same namespace. `@genomdev/pptx` opens the package and hands the
element here, so the table it holds is the same `SlideTable` a `.pptx` would
have produced and everything above is unchanged.
parseListStyle
function parseListStyle(container: XmlElement | undefined): TextLevelStyle[]
Reads nine `a:lvlNpPr` out of a list style.
The same nine levels appear in four places — the master's `p:txStyles`, a
layout placeholder's `a:lstStyle`, the shape's own, and the presentation's
default — and a paragraph takes the first answer it finds walking outwards.
One reader serves all four.
parseRecords
function parseRecords(bytes: Uint8Array, from: number, to: number): PptRecord[]
Reads a sequence of records filling a range.
Stops at the first header that cannot be believed. Continuing past one is
worse than stopping: the reader would be somewhere inside a payload, where
every eight bytes look like a header and the records it invents are indexed
by the same code that indexes real ones.
parseSlide
function parseSlide(root: XmlElement): Shape[]
Parses a slide part (`ppt/slides/slideN.xml`).
Shapes nest inside groups (`p:grpSp`), so the walk is recursive.
Inheritance from the layout and master is deliberately not resolved here:
that is a separate layer which needs access to the whole package, and it
belongs to rendering rather than to parsing.
parseTableStyles
function parseTableStyles(root: XmlElement): Map<string, TableStyle>
Reads the part into a lookup by style id, braces and all.
parseTextBody
function parseTextBody(textBody: XmlElement): TextParagraph[]
placeholderOfKind
function placeholderOfKind(kind: number): string | undefined
The placeholder name a story's kind stands for, `title` and friends.
propValue
function propValue(props: TextProps | undefined, name: string): number | undefined
readColorScheme
function readColorScheme(data: Uint8Array): ColorScheme | undefined
Reads a `ColorSchemeAtom`.
Eight four-byte values, each `red, green, blue, unused` — so the bytes are in
the opposite order from the hex a person writes, and a reader that takes the
low three bytes as `RGB` renders every deck in its own complement.
readCoreRecords
function readCoreRecords(stream: Uint8Array, directory: PersistDirectory): Map<number, PptRecord>
The records the directory names, read once and indexed by persist identifier.
Reading them eagerly rather than on demand is deliberate and cheap: a
presentation is a few megabytes at most, the records are already in memory,
and the alternative — parsing a slide the first time somebody looks at it —
would have to keep the stream alive anyway. What *is* deferred is the work
above a record: turning it into shapes and paragraphs, which is where the
time actually goes.
readDrawing
function readDrawing(drawing: PptRecord | undefined, context: DrawingContext): Shape[]
Reads a slide's drawing into shapes.
The top of the tree is one group holding everything, and its own shape is the
slide's canvas rather than something drawn — it is skipped, or the deck gets
one full-slide rectangle in front of every slide.
readMasterStyleAtom
function readMasterStyleAtom(data: Uint8Array, instance: number): { paragraph: TextProps; character: TextProps; }[]
`TxMasterStyleAtom`: the deck's typography, one entry per outline level.
The master's answer to `p:txStyles`, and the same information — but written
as pairs, a paragraph exception and a character exception per level, and with
one quirk that has to be got right. The record's instance number says which
kind of text these levels describe, and the styles for a *centred* body and
everything numbered above it write the level number before each pair, while
a title's and a plain body's do not. Read the wrong way the two bytes are
taken for the top half of the next mask, and the whole master comes out
unformatted.
readMasterStyles
function readMasterStyles(master: PptRecord | undefined): MasterStyles
Reads the `TxMasterStyleAtom`s a master carries.
Which kind an atom describes comes from its instance number and from nothing
else: the atoms sit side by side in the master with no marker between them,
so taking the first as the title and the second as the body by position
happens to work for most files and fails for exactly those whose master
states only one of the two.
readOutline
function readOutline(document: PptRecord | undefined, codePage: number): Outline
readPersistDirectory
function readPersistDirectory(stream: Uint8Array, startOffset: number | undefined): PersistDirectory
Reads the persist directory by walking the chain of saves.
Each `UserEditAtom` is visited once. The guard matters more than it looks:
a file whose chain loops — and fuzzers produce them, as do a few real files
whose last save was interrupted — would otherwise be read until memory ran
out, and the presentation is perfectly readable from the part of the chain
that came before the loop.
readRecordAt
function readRecordAt(bytes: Uint8Array, at: number): PptRecord | undefined
Reads the record at an offset, and its children if it has any.
A length running past the end of the stream is clamped rather than refused: a
`.ppt` truncated by whatever copied it is common enough that losing the whole
presentation over the last record would be the wrong trade. What is not
clamped is a *nested* length — see {@link parseRecords}.
readStories
function readStories(records: readonly PptRecord[], codePage: number): TextStory[]
Splits a run of records into stories.
Driven by the headers rather than by container structure, because there is no
container: `[header][chars][styles][header][chars][styles]` is one list, and
a reader that groups by anything else pairs the second story's characters
with the first story's styles.
readStyleAtom
function readStyleAtom(data: Uint8Array, textLength: number): { paragraphs: StyleRun[]; characters: StyleRun[]; }
`StyleTextPropAtom`: the paragraph runs, then the character runs.
Both lists cover the same text and neither states where it starts — each run
says only how many characters it covers, so position is the running sum. The
two lists are read one after the other out of one payload, which is why the
character list cannot be read without the paragraph list being read correctly
first: there is no offset to seek to.
The text length is passed in because the atom does not carry it. The stated
lengths are checked against it — a run claiming more characters than the
story holds is a corrupt file, and believing it walks the reader off the end
of a list that has no terminator.
schemeReference
function schemeReference(index: number): DiagramColor
A scheme slot as a theme reference, for the places that state an index.
shapesToText
function shapesToText(shapes: readonly Shape[]): string
Collects all shape text of a slide, for search and previews.
showsMasterShapes
function showsMasterShapes(root: XmlElement): boolean
Whether a part draws the master's own shapes.
`showMasterSp="0"` on a layout or a slide means "my design, not the one
behind me" — 88 parts of the corpus say so, and drawing the master's logo
over a layout that turned it off is worse than not drawing it at all.
storyToParagraphs
function storyToParagraphs(story: TextStory, context: TextContext): TextParagraph[]
Turns a story into the paragraphs the modern model uses.
Three lists have to be walked at once and none of them is indexed: the
characters, the paragraph runs and the character runs each say only how long
they are. The walk below keeps one cursor over the text and consumes from the
other two as it passes them, which is the only way to pair them — and it is
why a single wrong length earlier in the file misformats everything after it
rather than one run.
textStyleListFor
function textStyleListFor(styles: TextStyleDefaults, placeholderType: string | undefined): readonly TextLevelStyle[]
Which of the master's three lists describes a placeholder's text.
Only three kinds of text exist as far as `p:txStyles` is concerned: a title,
the body of a slide, and everything else.
themeOfScheme
function themeOfScheme(scheme: ColorScheme | undefined, fonts: { major: string | undefined; minor: string | undefined; }): Theme
The scheme as a theme, so that everything above this line stays unchanged.
The renderer resolves `accent1` through a `Theme`, and a presentation that
cannot hand it one is a presentation drawn without colours. The twelve slots
are filled from the eight: the four the scheme has no opinion about take the
value of the slot they are nearest to, which is what PowerPoint does when it
converts a deck of this age.
topLevelRecords
function topLevelRecords(stream: Uint8Array): PptRecord[]
Every top-level record of the stream, for the tools rather than the reader.
The reader has no use for this — a record not named by the directory is by
definition not part of the presentation — but a person looking at a file that
disagrees with PowerPoint does, and so does the dump tool.
walkPptx
function walkPptx(document: PptxDocument, hash: string, options: ResolvedOptions): Promise<{ blocks: Block[]; annotations: Annotation[]; }>
Reading a deck as content.
Simpler than a document in one way and harder in another. A slide *is* a
page, so there is no pagination to be honest about and the section structure
is given. But a slide has no reading order: it is a bag of shapes at
coordinates, and the order they appear in the file is the order they were
drawn, which is z-order and not the order anybody reads them in.
So shapes are sorted before they are walked — title first because it is the
title, then top to bottom and left to right. A deck extracted in file order
routinely puts the page number before the heading, and every chunk from it
starts with "4".
Interfaces
ColorScheme
interface ColorScheme
colors
readonly string[]
The eight colours as `RRGGBB`, by slot.
DrawingContext
interface DrawingContext
A slide's drawing, read into the shapes the modern model uses.
This is the part of a `.ppt` that is *not* peculiar to it. Everything a slide
shows is an Office Art tree — the same tree a `.doc` anchors to its text and
an `.xls` floats over its grid — so the walk below is the third of three, and
the record layer under it is shared.
What is peculiar is where the words are, and there are two answers rather
than one. A text box carries its own story inside the shape, in a record that
Office Art treats as opaque bytes and that turns out to hold PowerPoint
records. A *placeholder* — the title and the bullets, which is most of the
text in most decks — carries nothing at all: its words are in the document's
outline list, and the shape names them by number. A reader that handles only
the first shows every deck as its pictures and its captions with the title
and the body missing, which is a plausible-looking presentation of nothing.
outline
readonly TextStory[]
The stories the outline list holds for this slide, in order.
partName
string
The part name shapes of this drawing are addressed against.
codePage
number
The code page eight-bit text in this presentation is written in.
claimed
Set<number>
Which outline stories this slide has already given to a shape.
A slide's stories belong to its shapes one apiece, and the only rule that
can hand the same one out twice is the fallback below — matching a
placeholder to a story by *kind*, where a slide with six body placeholders
matches all six to the first body story. `poi/datetime` is the extreme
case: thirteen date placeholders, one story, and the same word thirteen
times on the slide.
metro
Map<string, Uint8Array<ArrayBufferLike>>
The metro blobs met along the way, by shape id.
Collected rather than read here because reading one means unzipping it, and
this walk is synchronous by design — a slide's geometry should not have to
wait on a decompressor. What comes out is applied in `document.ts`, where
there is already a promise to hang it on.
metroMembers
Map<string, string[]>
The members a metro group would otherwise contribute, by the group's id.
A table's blob sits on the *group* — the grid as a whole — and the group's
members are the cells drawn the old way. Both are emitted, because whether
the blob can be read is not known until it has been unzipped, and losing a
grid to an unreadable blob would be worse than showing it twice. Whichever
of the two survives is decided in `document.ts`, once the answer is in.
MasterStyles
interface MasterStyles
A master's typography, by kind of text and outline level.
The `.ppt` counterpart of `p:txStyles`, and it is finer-grained than the
modern format's three lists: a master carries one `TxMasterStyleAtom` per
*text kind*, and there are nine of them. The title and the body are the two
everyone knows about; the interesting one is the fifth, the centred body,
which is what a subtitle on a title slide is.
Collapsing the nine into three was worth exactly one visible bug and it is
the kind to remember: a subtitle taking the body's style is a subtitle with a
bullet in front of it, on the first slide of every deck built from the
shipped template. Nothing about the number was wrong — the size, the face and
the colour were all the body's, and the body's are nearly the subtitle's.
byKind
ReadonlyMap<number, readonly StyleLevel[]>
By `TextHeaderAtom` kind: 0 a title, 1 a body, 5 a centred body, and so on.
MediaPart
interface MediaPart
The presentation's picture store.
The same Office Art store the other two binary formats keep, found in a
different place and pointing somewhere else again. A `.ppt` puts the store in
the document's `PPDrawingGroup` record and the *bytes* in a stream of their
own, called `Pictures`, which each entry names by offset. So the store looks
empty on inspection and the pictures are in a stream nothing else refers to —
the same shape of trap Word sets by keeping them among its text, and it costs
the whole deck's imagery when missed.
Names are invented rather than read. The model addresses a picture by package
part name and relationship id, because that is what the modern format gives
it; a binary presentation has neither. `ppt/media/image3.png` is therefore a
name this module makes up and answers to, which is what keeps the renderer,
the extractor and the addressing scheme identical for both generations.
OpenPptOptions
interface OpenPptOptions extends OpenOptions
password?
string | undefined
Accepted for symmetry with the other readers; encryption is not supported.
PersistDirectory
interface PersistDirectory
Finding out which bytes of the stream are the presentation.
This is the one structure a `.ppt` has that neither of its siblings does, and
it exists because PowerPoint saved incrementally. Editing a slide appended a
new copy of it to the end of the stream and left the old one where it was; a
file of forty slides may hold four hundred, most of them superseded. Nothing
in the stream marks a record as dead.
What decides is a chain, and it is read backwards:
`Current User`, a stream of its own, points at the *last* `UserEditAtom`.
A `UserEditAtom` points at the persist directory of its own save, and at
the `UserEditAtom` of the save before it.
A persist directory maps *persist identifiers* — small numbers a slide is
named by — to byte offsets.
Walking the chain from the last save to the first, and letting each earlier
directory fill only the identifiers no later one claimed, gives the current
offset for every object. A reader that instead takes the first match walking
forwards shows the presentation as it was when it was created.
offsets
ReadonlyMap<number, number>
Persist identifier to the offset of the record it currently names.
documentPersistId
number
Which persist identifier the `Document` record has, per the last save.
encrypted
boolean
True when a `DocumentEncryptionAtom` was found along the way.
PptRecord
interface PptRecord
offset
number
Where the record's header begins in the stream that holds it.
data
Uint8Array<ArrayBufferLike>
The payload, always — a container's included.
A view rather than a copy, so keeping it for records that also have
children costs nothing, and it is the only way to read the two records
whose children are in another language.
PptxDocument
interface PptxDocument extends GenomDocument, PresentationTheme
format
"pptx" | "ppt"
Which generation of the format the deck was read from.
Both readers produce this one model — `@genomdev/pptx` reads the binary
record stream into it rather than converting — so the field is the only
place the difference survives, and it is kept because a caller reporting
what it opened should be able to say the truth.
slideSize
{ width: number; height: number; }
Slide size in EMUs, from `p:sldSz`.
loadImage
(slide: Slide, relationshipId: string) => Promise<{ bytes: Uint8Array; contentType: string; } | undefined>
imageUrl
(slide: Slide, relationshipId: string) => Promise<string | undefined>
A URL for a slide's picture, metafiles translated.
imageUrlFrom
(partName: string, relationshipId: string) => Promise<string | undefined>
The same, for a picture belonging to any part: a layout's background.
imageSvgFrom
(partName: string, relationshipId: string) => Promise<string | undefined>
A translated metafile's SVG source, when its text is worth inlining.
oleImageUrl
(partName: string, shapeId: string) => Promise<string | undefined>
The picture an older embedded object keeps in the slide's VML drawing.
oleImageSvg
(partName: string, shapeId: string) => Promise<string | undefined>
The same, as SVG source, when that picture is a metafile worth inlining.
hyperlink
(slide: Slide, relationshipId: string) => Promise<string | undefined>
Where a run's `a:hlinkClick` points, when it points outside the deck.
Rect
interface Rect
A rectangle in EMUs, the DrawingML coordinate system.
Shape
interface Shape
A shape holding text or a picture.
frame
Rect | undefined
Position and size; `undefined` when inherited from the layout.
placeholderType
string | undefined
The shape role in the layout (`ph type`): `title`, `body`, `ctrTitle`.
It tells the renderer that a shape is a title even when the styling lives
in the slide layout rather than in the shape itself.
placeholderIndex
number | undefined
`p:ph/@idx`: which placeholder of its kind this is.
PowerPoint matches a slide's placeholder to its layout's, and a layout's to
its master's, on the type **and** this number — a template numbers its body
1, its date 2, its footer 3, and every placeholder a designer adds from ten
up. Without it a subtitle and a content box are indistinguishable, and the
chain hands one the other's anchor.
imageRelationshipId
string | undefined
Image relationship id when the shape is a picture (`p:pic`).
oleShapeId?
string | undefined
The `spid` of an embedded object whose picture is not beside it.
Older files keep the picture of an embedded worksheet or document as a VML
shape of this id, in a drawing part related to the slide, rather than in the
`mc:Fallback` where a modern file puts it. Set only when there is no
{@link imageRelationshipId} to use instead.
sourcePart
string | undefined
The part the shape was read from, when that is not the slide.
A logo in the master is drawn on every slide of the deck, but the picture
it points at is the master's: the relationship has to be resolved against
the part that stated it, or the image is simply not found.
listStyle
readonly TextLevelStyle[] | undefined
`p:txBody/a:lstStyle`: what this shape sets for each outline level.
The third rung of the ladder a paragraph climbs — its own properties, then
its shape's list style, then the one its placeholder inherits from the
layout and the master, then the master's `p:txStyles`. Layouts state 7 561
non-empty list styles across the corpus, and every one of them was ignored.
inheritedListStyle
readonly TextLevelStyle[] | undefined
The list style of the layout or master placeholder this shape matches.
inheritedListStyles
readonly (readonly TextLevelStyle[] | undefined)[] | undefined
The rest of the chain behind it: the master's placeholder, then anything
behind that, outermost last.
The layout and the master are rungs of one ladder and each states only what
it changes, so taking the first that states *anything* discards the rest.
A Google Slides export is the clearest case: its layout's title placeholder
states a bullet size and an empty `a:defRPr`, which is enough to count as
stating something, and the master's twenty-five points behind it were never
read — `13928819-02_20241010_Vos_Code-and-software` drew its titles at the
renderer's own fourteen.
geometry
DiagramGeometry | undefined
How the shape is painted, `p:spPr`.
The same three things a shape has in a workbook and in a document —
geometry, fill, outline — read into the same types, so that the renderer
that draws an Excel shape draws this one.
paint
DiagramFill | undefined
The fill as stated, when it is not a flat colour.
A gradient panel, a hatched box and a shape filled with a photograph were
all drawn as nothing, because only `a:solidFill` was read.
outline
DiagramOutline | undefined
style
ShapeStyleReference | undefined
`p:style`: how the deck's theme paints this shape.
Most shapes state no colour at all — they name an entry of the theme's
format scheme and the colour to fill its placeholder with. Ignored, they
are drawn unpainted, with their labels in the default colour on the default
background: which is white on white for a third of the corpus's slides.
shadow
DiagramShadow | undefined
`a:effectLst/a:outerShdw`: the shadow the shape casts, if any.
rotation
number
`a:xfrm/@rot`, in degrees clockwise; a slide states sixtieths of one.
flipHorizontal
boolean
`a:xfrm/@flipH` and `@flipV`: the shape drawn mirrored.
verticalAlignment
"center" | "top" | "bottom" | undefined
`a:bodyPr`: where the text sits inside the shape.
A shape is a box and its text is placed in it: `@anchor` says against which
edge, `@lIns` and friends say how far from it. Both have defaults that are
not zero and not centre — PowerPoint anchors to the top and insets by a
tenth of an inch — so a reader that ignores them puts every caption in a
different place from the one the deck was designed with.
statesBody
boolean | undefined
Whether the shape carried an `a:bodyPr` of its own at all.
`@wrap` and `@vert` have defaults that are indistinguishable from silence
once read — `wrap` is `square` and `vert` is `horz` — so the only way to
tell a shape that asked for wrapping from one that said nothing is to
record that the element was there. Without it a slide placeholder with an
empty `<a:bodyPr/>` would override a layout that turns wrapping off.
wrap
boolean
`a:bodyPr/@wrap`: `none` lets a long line run past the shape.
spaceFirstLastParagraph
boolean | undefined
`a:bodyPr/@spcFirstLastPara`: the space before the first paragraph counts.
Off by default, and the probes say so: `paragraph-spacing` and
`placeholder-spacing` both put the first line of three boxes stating
nothing, twelve points and twenty per cent on one baseline. On, the space
is drawn — `13683066-Bijloke_AnatomicalTheatre` states ten points and
PowerPoint sets the whole block 13.33 px lower, which is those ten points.
**7979 shapes of the corpus state it**, in 160 decks: everything Google
Slides exports, which writes the attribute on every box it makes.
textDirection
"horizontal" | "vertical" | "vertical270" | "eastAsian"
`a:bodyPr/@vert`: text set on its side.
A side caption, a table's rotated header, the spine of a poster: the file
turns the text rather than the shape. Drawn horizontally it overflows the
narrow box it was given and covers whatever is beside it.
textRotation?
number | undefined
`a:bodyPr/@rot`: the text's own turn inside the shape, in 60000ths of a
degree, on top of whatever the shape itself is turned by.
textFrame?
Rect | undefined
`dsp:txXfrm`: the rectangle a SmartArt label is set in, in the diagram's
space. Shares its centre with the shape's own frame.
fontScale
number | undefined
`a:normAutofit/@fontScale`: how far PowerPoint shrank the text to fit.
A stated number rather than a guess — the application worked it out when
the deck was saved and wrote it down, so a reader that ignores it draws
text at a size the author never saw, overflowing the box it was shrunk to
fit.
lineSpacingReduction
number | undefined
`a:normAutofit/@lnSpcReduction`, as a fraction.
table
SlideTable | undefined
`a:tbl` inside a graphic frame: the rows, in reading order.
chartRelationshipId
string | undefined
`p:graphicFrame` pointing at a chart part, by relationship id.
diagram
readonly Shape[] | undefined
A SmartArt diagram, once the drawing PowerPoint saved with it is read.
The diagram itself is a data model and a layout algorithm — laying it out
is a program, not a parse — but every deck written since 2010 also carries
the shapes the application produced, in ordinary DrawingML. Those are what
is drawn: 54 decks of the corpus have one, and without it a SmartArt frame
is an empty rectangle in the middle of the slide.
diagramData
string | undefined
`dgm:relIds/@r:dm`: the data part, which names the drawing beside it.
chart
ChartDefinition | undefined
The chart itself, once the slide has read the part it points at.
Parsed rather than referenced: `c:chartSpace` is the same part on a slide
as in a workbook, and the renderer that draws it is the same too.
Slide
interface Slide
index
number
Zero-based position in the presentation.
load
() => Promise<SlideContent>
SlideBackground
interface SlideBackground
A background, and the part whose relationships resolve its picture.
styleIndex?
number | undefined
`p:bgRef/@idx`, zero-based: the entry of the theme's background list.
Present only when the part named one. The fill beside it is the colour
that entry is filled *with*; the entry itself may be a picture, and only
the theme knows.
partName
string
The part the fill was found in: a slide, a layout or a master.
SlideContent
interface SlideContent
themePart?
string | undefined
The theme part this slide inherits, reached through its layout and
master.
A deck has one theme per master and a notes theme besides, and the
document's own `theme` can only be one of them. A slide knows which is
its own, and it is the only thing that does.
masterPart?
string | undefined
The slide master this slide's layout belongs to.
A deck may carry several, and 114 of the corpus's 1775 do — every merged
presentation and every template with two designs. The master is where the
default size, colour, bullet and paragraph gap of every placeholder come
from, so reading the *first* master in the package described those slides
with another design's typography.
colorMap?
Readonly<Record<string, string>> | undefined
`p:clrMap`, as this slide inherits it: which theme colour each role uses.
Per slide because a layout may override it and the layouts of one deck
differ — a dark section in a light deck is exactly this and nothing else.
notes
string | undefined
Speaker notes, when the package contains that part.
background
SlideBackground | undefined
What the slide is drawn on: its own background, or the one it inherits.
Slides state a background 41 times in the corpus and masters 505 — a deck's
background is a property of its design, not of its slides — so a reader
that looks only at the slide draws every designed deck on white.
SlideEntry
interface SlideEntry
The document's outline: which slides there are, in which order, and what
their placeholders say.
`SlideListWithText` is two things at once and that is the whole of its
awkwardness. It is the presentation's table of contents — a `SlidePersistAtom`
per slide, naming the record that holds it — and it is *also* where the text
of every outline placeholder lives, as stories following the atom they belong
to. So a slide's title is not in the slide; it is here, and the slide's title
shape merely points back at it by number.
There are three of these lists and they are told apart by the record's
instance number, not by their position among the document's children: the
masters, the slides, the notes. Taking them by position puts the masters'
text on the slides for any file whose lists are not all present.
reference
number
The persist identifier of the record holding the slide.
slideId
number
The slide's own identifier, which the notes refer to it by.
stories
readonly TextStory[]
The stories this slide's placeholders hold, in the order they appear.
SlideTable
interface SlideTable
A table on a slide: column widths and rows of cells.
columns
readonly number[]
Column widths in EMUs, from `a:gridCol`.
styleId
string | undefined
`a:tableStyleId`: the GUID of the style in `ppt/tableStyles.xml`.
A table states almost nothing about its own look; it names a style and sets
the flags below, and the part says what those mean. Without it every table
in every deck is drawn as the same grey grid.
firstRow
boolean
`a:tblPr` flags: which special parts of the style apply.
SlideTableCell
interface SlideTableCell
merged
boolean
Cells a merge swallowed carry no content and are not drawn.
insets
{ left: number; top: number; right: number; bottom: number; }
`a:tcPr/@marL`, `@marR`, `@marT`, `@marB`: the cell's own insets, in EMUs.
Defaulted here rather than left unstated, because DrawingML defaults them
and a table states them only to depart: a tenth of an inch left and right,
a twentieth top and bottom. They were not read at all until now and the
renderer padded cells by a percentage of the table's width instead — which
is neither the right distance nor the same distance twice, since a
percentage padding resolves against the width on all four sides.
verticalAlignment
"center" | "top" | "bottom"
`a:tcPr/@anchor`: which edge of the cell the text sits against.
SlideTableRow
interface SlideTableRow
height
number
Row height in EMUs, from `a:tr/@h`; Word calls this a minimum.
cells
readonly SlideTableCell[]
StyleRun
interface StyleRun
One run of a style atom: how many characters it covers, and what it says.
level
number
Outline level, paragraph runs only.
TableBorder
interface TableBorder
A rule, stated outright or as a reference into the theme's line list.
outline
DiagramOutline | undefined
reference
StyleReference | undefined
TableBorders
interface TableBorders
TablePartStyle
interface TablePartStyle
One part of a table style: the whole table, a band, a header row.
fill
DiagramFill | undefined
`a:tcStyle/a:fill`, stated outright.
fillReference
StyleReference | undefined
`a:tcStyle/a:fillRef`: the theme entry the part is filled from.
textReference
StyleReference | undefined
TableStyle
interface TableStyle
A whole table style: the parts, in the order they override each other.
PowerPoint applies them from the least specific to the most: the whole table,
then the banding, then the first and last rows and columns. A cell in the
header row of a banded table is painted by three of them in turn.
wholeTable
TablePartStyle | undefined
band1Horizontal
TablePartStyle | undefined
band2Horizontal
TablePartStyle | undefined
band1Vertical
TablePartStyle | undefined
band2Vertical
TablePartStyle | undefined
firstRow
TablePartStyle | undefined
lastRow
TablePartStyle | undefined
firstColumn
TablePartStyle | undefined
lastColumn
TablePartStyle | undefined
TextContext
interface TextContext
What a story needs from the deck to become paragraphs.
The colour scheme because a run's colour is usually an index into it, and the
font collection because a run's typeface is an index too — a `.ppt` states
"font seven", and only the document knows that font seven is Verdana.
slideNumber?
number | undefined
Which slide this is, one-based, for a story that holds a page number.
The number is nowhere in the file — a `.ppt` marks the position and leaves
the arithmetic to whatever draws the slide, which is the same arrangement
the modern format has and the same reason a renderer has to be told.
TextLevelStyle
interface TextLevelStyle
What the master sets for one outline level of one kind of placeholder.
`p:txStyles` is the deck's typography: it says a title is 40pt, bold, and
coloured `tx2`, and a first-level bullet 20pt in `tx1`. Reading only the size
out of it — which is where this started — gives every deck the right scale in
the wrong colour.
caps
"all" | "none" | "small" | undefined
`a:defRPr/@cap`: a level set in capitals, which a run need not repeat.
alignment
"left" | "center" | "right" | "justify" | undefined
lineSpacing
TextSpacing | undefined
The spacing and the bullet the level carries.
The master is where a deck's list looks like a list: the step between
lines, the gap above an item, how far it is indented, and which glyph
marks it. A slide states these only when it departs from them, so a reader
that takes them from the paragraph alone renders most decks unbulleted and
unspaced.
tabSize
number | undefined
`a:lvlNpPr/@defTabSz`; see {@link TextParagraph.tabSize}.
rightToLeft
boolean | undefined
`a:lvlNpPr/@rtl`: the level runs right to left; see {@link TextParagraph.rightToLeft}.
bulletPicture
boolean | undefined
`a:buBlip`; see {@link TextParagraph.bulletPicture}.
bulletStated?
boolean | undefined
Whether the level *said* whether it is bulleted, as against leaving it
unsaid. PowerPoint 97-2003 only: the binary format writes the marker's
character and the flag that turns it on as two independent fields, and a
master states the character far more often than the flag.
bulletSizePoints
number | undefined
`a:buSzPts`: the marker's size in points; see {@link TextParagraph.bulletSizePoints}.
kerningFrom
number | undefined
`a:defRPr/@kern`: the size from which text at this level is kerned.
The masters state it and the runs almost never do — the shipped template
writes `kern="1200"` on every level of every style — so a rule that read
the run alone kerned nothing at all. `45541_Footer` shows the cost on its
title: 711 pixels in PowerPoint and 743 in ours, four and a half per cent
of a line that has to wrap in the same place.
TextParagraph
interface TextParagraph
A paragraph of a text body (`a:p`).
level
number
List nesting level; 0 is the top level.
alignment
"left" | "center" | "right" | "justify" | undefined
bulletChar
string | undefined
Bullet glyph, when the paragraph is bulleted.
bulletNumbering
{ readonly scheme: string; readonly startAt: number; } | undefined
`a:buAutoNum`: the paragraph is numbered rather than bulleted.
The scheme names the shape of the number — `arabicPeriod` is `1.`,
`alphaLcParenR` is `a)` — and `startAt` restarts the count. The number
itself is not in the file: it is the paragraph's position among its
neighbours at the same level, which only the renderer knows.
bulletPicture
boolean
`a:buBlip`: the marker is a picture rather than a character.
The image itself is a relationship of the part the bullet was written in —
usually a master — and is not drawn yet. What matters for the text is that
a marker is *there*: it occupies the hanging indent, so the words start at
`marL` like any other bulleted paragraph rather than at the hang.
`19944360-Lecture-4` sets every second-level bullet this way, and without
it the whole block sits 36 px left of PowerPoint's.
bulletNone
boolean
`a:buNone`: the paragraph states that it has no bullet at all.
bulletColor
DiagramColor | undefined
`a:buClr`, `a:buSzPct`, `a:buFont`: how the marker itself is set.
bulletSizePoints
number | undefined
`a:buSzPts`: the marker's size in points, stated outright.
The commoner of the two forms by a distance — **167 decks and 65132
occurrences against 4937 of `a:buSzPct`** — and it was not read at all, so
every such marker was drawn at the text's size instead of its own. It is
not only the marker that moves: a bullet is the widest thing on the first
line of its paragraph as often as not, and its box is what holds the hang
open, so the whole text column starts somewhere else.
A length, and therefore not autofit's to shrink; see `autofitSize`.
lineSpacing
TextSpacing | undefined
The spacing a paragraph asks for, which nothing used to read.
`a:lnSpc` is the step between its lines and `a:spcBef`/`a:spcAft` the gaps
around it, each stated either as a percentage of the type size or as a
number of points. Ignored, every list in every deck comes out at the
browser's own line height with no space between items: the commonest thing
in a presentation, set wrong.
marginLeft
number | undefined
`a:pPr/@marL` and `@indent`, in EMUs: the list's own indentation.
tabSize
number | undefined
`a:pPr/@defTabSz`: how far apart this paragraph's tab stops are, in EMUs.
An inch unless the file says otherwise — and the file says it *here*, or on
the level style behind it, and not on `a:bodyPr`: the probe `tab-grid`
states half an inch in both places and PowerPoint honours only the
paragraph's. A deck converted from `.ppt` carries the value on every level
of its master.
rightToLeft
boolean | undefined
`a:pPr/@rtl`: the paragraph runs right to left.
Arabic, Hebrew and Persian decks state it on every paragraph, and it
decides three things at once — which edge the text starts from, which end
the bullet sits at, and the order the words of a mixed line come out in.
Unread, such a deck is drawn left-aligned with its runs in file order, and
the corpus shows what that costs: the nine decks that state it produce
37.6% of their lines against 73.8% for the rest, and place 7.7% against
25.2%. It is the widest gap any construct in the census shows.
endProperties
TextRunProperties | undefined
`a:endParaRPr`: the properties of the paragraph mark itself.
Only interesting when the paragraph holds nothing else — and then it is the
whole of it. PowerPoint gives an empty paragraph a line box of *this* type,
not of the level's: `poi/alterman_security` separates two bullets with an
empty paragraph whose mark states 28 points where its level says 32, and a
reader that takes the level puts everything below it six pixels low.
TextProps
interface TextProps
The values a mask named, by property name, and which bits were set.
values
ReadonlyMap<string, number>
TextRun
interface TextRun
field?
string | undefined
`a:fld/@type` where the run is a field: `slidenum`, `datetime1`… The text
beside it is what the application last cached, which for a slide number
inherited from a layout is a placeholder rather than a number.
math?
readonly MathNode[] | undefined
An equation, where the run is one.
`m:oMath` sits among a paragraph's runs and holds a tree rather than a
string — a fraction, a root, a sum with its limits. It is text: PowerPoint
draws it as letters and its export writes every one of them into the PDF.
The run's `text` is the same letters in reading order, so anything that
only wants the words still gets them.
TextRunProperties
interface TextRunProperties
Formatting of a text fragment (`a:rPr`).
fontSize?
number | undefined
Size in points; the file stores hundredths of a point.
color?
string | undefined
Colour as `RRGGBB`, when given literally.
colorReference?
DiagramColor | undefined
The colour as the file states it, theme slots and all.
Most templates colour their text by theme (`a:schemeClr val="tx1"`) rather
than literally, and a reader that only takes `a:srgbClr` renders those runs
in whatever the stylesheet happens to inherit.
hyperlinkId?
string | undefined
`a:hlinkClick`: the relationship the run links through.
shadow?
DiagramShadow | undefined
`a:rPr/a:effectLst/a:outerShdw`: the shadow behind the letters.
The commonest effect in the corpus by a distance — 514 runs of 1 044 effect
lists — because a title over a photograph is unreadable without one.
textOutline?
DiagramOutline | undefined
`a:rPr/a:ln`: the line drawn around the letters.
A title outlined in white over a photograph is the commonest use, and
fourteen decks of the corpus draw one on their first slide alone. Without
it such a title is the fill alone, which over a busy picture is nothing.
textPicture?
string | undefined
`a:rPr/a:blipFill`: the picture the letters are filled with.
Twenty-two decks of the corpus do it — a heading cut out of a photograph
or a pattern — and drawn as flat text it is the wrong colour entirely.
The relationship belongs to the part the shape came from.
baseline?
number | undefined
`@baseline`: the run is raised or lowered, as a share of the type size.
How a presentation writes a superscript — 522 runs of the corpus do — and
drawn on the baseline they read as ordinary digits: "m2" for "m²".
letterSpacing?
number | undefined
`@spc`: letter spacing in points, positive to open the line up.
caps?
"all" | "none" | "small" | undefined
`@cap`: `all` for capitals, `small` for small ones, `none` for neither.
`none` is recorded rather than dropped because the level style above the
run may state `all`, and a run departing from it has to be able to say so.
strike?
"single" | "double" | undefined
`@strike`: `sngStrike` or `dblStrike`.
kerningFrom?
number | undefined
`@kern`: the size, in points, from which the run is kerned.
A *threshold*, not a switch, and its absence means no kerning at all —
which is not the browser's default and never was. The probe `kerning`
measures the difference: the same line of Times New Roman at 44 points
comes out 694 pixels wide when the file states `kern="1200"` and **743**
when it states nothing, and a line seven per cent wide wraps a word early
— after which neither side has the same lines at all.
eastAsianFont?
string | undefined
`a:ea`: the typeface for East Asian text, when it differs from the Latin.
complexScriptFont?
string | undefined
`a:cs`: the face for Arabic, Hebrew and the other complex scripts.
TextSpacing
interface TextSpacing
A spacing, as a share of the type size or as an absolute measure.
percent
number | undefined
`a:spcPct/@val`, as a fraction: 1.5 for one and a half lines.
points
number | undefined
`a:spcPts/@val`, in points.
TextStory
interface TextStory
A text story, and turning one into paragraphs.
A story is a run of records rather than a container: a `TextHeaderAtom`
saying what kind of text follows, then the characters — as bytes or as
UTF-16, never both — then the styles that cover them. They sit side by side
in whatever holds them, a slide's drawing or the document's outline list, and
a story ends where the next header begins.
The characters are one string with `\r` between paragraphs. Nothing marks a
paragraph otherwise; the styles are stated as runs over that string, so a
paragraph's formatting is found by counting characters, not by looking it up.
kind
number
`TextHeaderAtom`'s kind: title, body, notes, other.
index
number
Position among the stories of the list this one came from.
indents
readonly { length: number; level: number; }[]
`MasterTextPropAtom`: the outline level of each run, when stated apart.
fields
readonly { position: number; kind: "slideNumber" | "date" | "footer"; }[]
Where the story holds a field rather than a character.
A slide number, a date and a footer are not text in a `.ppt`: the story
holds one placeholder character and a *metacharacter atom* beside it saying
which position that character stands at and what it stands for. The
character itself is usually `*`, which is why a reader that ignores these
draws an asterisk where PowerPoint draws the page number — thirteen of them
on the first slide of `poi/datetime`.
ruler
TextRuler | undefined
`TextRulerAtom`: the story's own tab grid, where it states one.
Values
BulletFlag
BulletFlag: { readonly Bulleted: 1; readonly HardFont: 2; readonly HardColor: 4; readonly HardSize: 8; }
Bits of the paragraph `bulletFlags` field.
CharFlag
CharFlag: { readonly Bold: 1; readonly Italic: 2; readonly Underline: 4; readonly Shadow: 16; readonly Strike: 256; readonly Emboss: 512; }
Bits of the character `flags` field.
CURRENT_USER_STREAM
CURRENT_USER_STREAM: "Current User"
Where the pointer to the most recent edit is kept, outside the document.
DEFAULT_PPT_SLIDE_SIZE
DEFAULT_PPT_SLIDE_SIZE: { readonly width: number; readonly height: number; }
Slide size when a document states none: the 10 by 7.5 inch default of 1997.
DEFAULT_SLIDE_SIZE
DEFAULT_SLIDE_SIZE: { readonly width: 12192000; readonly height: 6858000; }
Default slide size: widescreen 16:9, 13.333 by 7.5 inches.
DEFAULT_TEXT_INSETS
DEFAULT_TEXT_INSETS: { readonly left: 91440; readonly top: 45720; readonly right: 91440; readonly bottom: 45720; }
`a:bodyPr` insets when the file states none, in EMUs.
A tenth of an inch left and right, a twentieth top and bottom — PowerPoint's
defaults, and not zero, so text never touches the edge of its shape.
DOCUMENT_STREAMS
DOCUMENT_STREAMS: readonly ["PowerPoint Document", "PP97_DUALSTORAGE"]
The streams a presentation may live in.
`PowerPoint Document` is the one every version since 97 writes. The second is
a curiosity worth handling: a file saved by PowerPoint 95 for compatibility
keeps *both* generations side by side, and the modern stream is the one to
read — but some tools keep only the old name.
EMPTY_OUTLINE
EMPTY_OUTLINE: Outline
EMU_PER_MASTER_UNIT
EMU_PER_MASTER_UNIT: number
Master units to EMUs.
A `.ppt` measures in 576ths of an inch and a `.pptx` in 914 400ths; the ratio
is exact, which is the only reason the two models can share a rectangle type
without either side rounding.
PLACEHOLDER_OF_ID
PLACEHOLDER_OF_ID: Readonly<Record<number, string>>
`OEPlaceholderAtom`'s identifier as the placeholder name `.pptx` uses.
PLACEHOLDER_OF_TEXT_KIND
PLACEHOLDER_OF_TEXT_KIND: Readonly<Record<number, string>>
The text kind translated into the placeholder name the modern format uses.
The whole point of the exercise: once a story says `ctrTitle` rather than
`6`, the typography ladder, the extractor and the renderer built for `.pptx`
treat it as the title it is, with no code anywhere that knows the deck came
out of PowerPoint 97.
PlaceholderId
PlaceholderId: { readonly None: 0; readonly MasterTitle: 1; readonly MasterBody: 2; readonly MasterCenteredTitle: 3; readonly MasterSubTitle: 4; readonly MasterNotesSlideImage: 5; readonly MasterNotesBody: 6; readonly MasterDate: 7; readonly MasterSlideNumber: 8; readonly MasterFooter: 9; readonly MasterHeader: 10; readonly NotesSlideImage: 11; readonly NotesBody: 12; readonly Title: 13; readonly Body: 14; readonly CenteredTitle: 15; readonly SubTitle: 16; readonly VerticalTextTitle: 17; readonly VerticalTextBody: 18; readonly Object: 19; readonly Graph: 20; readonly Table: 21; readonly ClipArt: 22; readonly OrganisationChart: 23; readonly MediaClip: 24; }
`OEPlaceholderAtom`'s placeholder identifiers.
A superset of the text kinds above: it also names the three things that are
placeholders but hold no outline text — the date, the footer and the slide
number — which is exactly the set a renderer must not draw as body text.
pptx
pptx: FormatModule<PptxDocument>
PowerPoint presentations, both generations, as one module.
Recognition is stated as data so the registry can pick this module out of
six without loading any of them: an OPC package announces its main part's
content type, and that is the only thing that tells the three OOXML formats
apart. The compound file is the case rules cannot settle — a `.doc`, an
`.xls` and a `.ppt` share one signature — so it shortlists itself and
`canOpen` reads the directory to be sure.
One module rather than two because the binary reader produces the same model:
nothing above here has to know which generation it was handed.
Rec
Rec: { readonly Document: 1000; readonly DocumentAtom: 1001; readonly EndDocument: 1002; readonly Slide: 1006; readonly SlideAtom: 1007; readonly Notes: 1008; readonly NotesAtom: 1009; readonly Environment: 1010; readonly SlidePersistAtom: 1011; readonly MainMaster: 1016; readonly SSSlideInfoAtom: 1017; readonly RoundTripHFPlaceholder12: 1056; readonly ExObjList: 1033; readonly PPDrawingGroup: 1035; readonly PPDrawing: 1036; readonly List: 2000; readonly FontCollection: 2005; readonly ColorSchemeAtom: 2032; readonly ExObjRefAtom: 3009; readonly OEPlaceholderAtom: 3011; readonly OutlineTextRefAtom: 3998; readonly TextHeaderAtom: 3999; readonly TextCharsAtom: 4000; readonly StyleTextPropAtom: 4001; readonly MasterTextPropAtom: 4002; readonly TxMasterStyleAtom: 4003; readonly TxCFStyleAtom: 4004; readonly TxPFStyleAtom: 4005; readonly TextRulerAtom: 4006; readonly TextBytesAtom: 4008; readonly TextSpecInfoAtom: 4010; readonly FontEntityAtom: 4023; readonly CString: 4026; readonly ExOleObjAtom: 4035; readonly ExEmbed: 4044; readonly ExHyperlinkAtom: 4051; readonly ExHyperlink: 4055; readonly SlideNumberMCAtom: 4056; readonly HeadersFooters: 4057; readonly HeadersFootersAtom: 4058; readonly TxInteractiveInfoAtom: 4063; readonly SlideListWithText: 4080; readonly InteractiveInfo: 4082; readonly InteractiveInfoAtom: 4083; readonly UserEditAtom: 4085; readonly DateTimeMCAtom: 4087; readonly GenericDateMCAtom: 4088; readonly FooterMCAtom: 4090; readonly ExOleObjStg: 4113; readonly ProgTags: 5000; readonly ProgStringTag: 5001; readonly ProgBinaryTag: 5002; readonly PersistPtrFullBlock: 6001; readonly PersistPtrIncrementalBlock: 6002; readonly Comment2000: 12000; readonly Comment2000Atom: 12001; readonly DocumentEncryptionAtom: 12052; }
The record types a PowerPoint 97-2003 stream is made of.
Numbered rather than named — a `.ppt` has no XML and no vocabulary, only
these numbers — and grouped the way the format groups them: the document and
its slides in the 1000s, the collections in the 2000s, text in the 4000s.
Only the types this reader acts on are listed; everything else is stepped
over by its stated length, which is what lets a reader written against
PowerPoint 97 walk a file PowerPoint 2003 saved.
SchemeSlot
SchemeSlot: { readonly Background: 0; readonly TextAndLines: 1; readonly Shadows: 2; readonly TitleText: 3; readonly Fills: 4; readonly Accent: 5; readonly AccentAndHyperlink: 6; readonly AccentAndFollowedHyperlink: 7; }
The eight slots, in the order the atom writes them.
SlideListRole
SlideListRole: { readonly Slides: 0; readonly Masters: 1; readonly Notes: 2; }
Which of a `SlideListWithText`'s three roles this one holds.
The instance number of the record says it, and the three are not
interchangeable: the first lists the masters, the second the slides in their
presentation order, the third the notes pages. A reader that takes them by
position among the document's children gets the masters and the slides the
right way round only by luck.
TextKind
TextKind: { readonly Title: 0; readonly Body: 1; readonly Notes: 2; readonly Outline: 3; readonly Other: 4; readonly CenterBody: 5; readonly CenterTitle: 6; readonly HalfBody: 7; readonly QuarterBody: 8; }
What kind of text a story holds, from `TextHeaderAtom`.
The nearest thing the binary format has to `p:ph/@type`, and it is what turns
a box of words into a title: the outline placeholders are numbered here and
the renderer asks the master for a title's typography by this number.