model
Slides, layouts, masters and themes as one document, with a resolver that says where every value came from.
Slides, layouts, masters and themes as one document, with a resolver that reports where every value came from.
npm install @pptx-studio/model @pptx-studio/opc @pptx-studio/xml @pptx-studio/geometry @pptx-studio/paint
What it is
A shape on a slide usually declares only what differs from its layout placeholder, which declares only what differs from the master's, which reads its colours and fonts from the theme. @pptx-studio/model parses all of those from a PartStore, binds them through each part's own relationships, and exposes a resolver that answers with the value and its origin.
A property the file did not state stays undefined. That is the one decision the later phases - change layout, theme swap, per-property reset - rest on.
30-second example
const doc = loadDocument(PartStore.open(bytes));
const slide = doc.slides[0];
if (slide === undefined) throw new Error('no slides');
for (const shape of slide.shapes) {
const xfrm = resolveXfrm(shape, slide);
console.log(shape.name, xfrm?.origin, xfrm?.value); // 'Title 1' 'masterPh' { x, y, cx, cy, rot, … }
console.log(
inheritanceChain(shape, slide).map((link) => `${link.origin} ${link.sheet.partName}`),
);
}Key concepts
undefined means the file did not say
Other editors bake inherited values into the slide the moment they open it and lose the fact that the slide never had them. Here shape.xfrm === undefined is information, and resolveXfrm walks the chain on demand.
The two hops use different keys
A slide placeholder finds its layout placeholder by idx alone; a layout placeholder finds its master placeholder by a folded type. inheritanceChain shows the hops and what matched.
Every binding comes from the part's own rels
Which layout a slide uses, which master a layout uses, which theme a master uses: each is one relationship in that part's .rels, and nothing is looked up by name.
The style matrix and phClr
A shape with an a:style reference takes its fill and line from the theme's format scheme, with the placeholder colour substituted in. resolveAppearance reports which of the three sources answered.
The resolver reports where it looked
Every Resolved<T> carries origin, explicit, sheet and shape, so a provenance panel is a rendering of the answer, not a second computation.
API reference
190 exports of @pptx-studio/model 0.5.0, read from the package this site installed. Click a name for its declaration.
index.ts
COLOR_TRANSFORM_OPSre-exportre-exported from @pptx-studio/paint
src/errors.ts
ModelErrorCodetypeTyped failures, as everywhere else in this repository.type ModelErrorCode = /** A part the chain needs is not in the package. */ 'MODEL_PART_MISSING' | /** A part is present but its root element is not the one its rel promised. */ 'MODEL_PART_KIND' | /** `ppt/presentation.xml` is missing, or the root rels do not name it. */ 'MODEL_NO_PRESENTATION' | /** A slide has no `slideLayout` relationship, or a layout no `slideMaster`. */ 'MODEL_NO_PARENT' | /** A master has no `theme` relationship. */ 'MODEL_NO_THEME' | /** A `p:clrMap` or `a:overrideClrMapping` missing one of its twelve attributes. */ 'MODEL_CLRMAP_INCOMPLETE' | /** A `p:clrMap` attribute naming something that is not one of the twelve slots. */ 'MODEL_CLRMAP_SLOT' | /** A `p:ph/@idx` that is not a non-negative integer below 2^32. */ 'MODEL_PLACEHOLDER_IDX' | /** An `a:off`/`a:ext`/`@rot` attribute that is not an integer. */ 'MODEL_XFRM_NUMBER' | /** A style-matrix reference whose `@idx` does not parse. */ 'MODEL_STYLE_IDX' | /** An `a:fontRef/@idx` outside `major`, `minor` and `none`. */ 'MODEL_FONT_COLLECTION' | /** A theme with no `a:fmtScheme`, asked for a style-matrix entry. */ 'MODEL_NO_STYLE_MATRIX' | /** A `a:fillStyleLst`/`a:lnStyleLst`/`a:bgFillStyleLst` with no entries at all. */ 'MODEL_STYLE_LIST_EMPTY' | /** A sheet chain that returns to a sheet it has already visited. */ 'MODEL_SHEET_CYCLE' | /** A sheet that does not belong to the document it was asked about. */ 'MODEL_FOREIGN_SHEET' | /** `a:prstGeom` with no `@prst`, or an `a:custGeom` command missing a point. */ 'MODEL_GEOMETRY' | /** A text attribute whose value is not of the type its schema names. */ 'MODEL_TEXT_ATTR' | /** An `a:fld` with no `@id`, which is a required `ST_Guid`. */ 'MODEL_TEXT_FIELD' | /** * A bullet that contradicts itself or omits what the schema requires. * * The four kinds are an exclusive group, `a:buAutoNum` must carry a @type and * `a:buBlip` must resolve to a relationship. A file that breaks one of those is * one PowerPoint would repair, and repairing it here quietly would hide which. */ 'MODEL_TEXT_BULLET' | /** A paragraph level that is not an integer. */ 'MODEL_TEXT_LEVEL' | 'MODEL_TEXT_TYPEFACE' | /** A table attribute missing where the schema requires it, or not of the type it names. */ 'MODEL_TABLE_ATTR' | /** A table-style edge with neither `a:ln` nor `a:lnRef`, or an `a:fill` holding no fill. */ 'MODEL_TABLE_STYLE' | /** A grid position or grid edge asked of a table that has no such position or edge. */ 'MODEL_TABLE_POSITION' | 'BLIP_NO_EMBED' | 'BLIP_DUOTONE' | 'BLIP_CLR_CHANGE' | 'BLIP_TILE_ALIGN' | 'BLIP_TILE_FLIP';
ModelErrorclassclass ModelError extends Error { readonly name = "ModelError"; readonly code: ModelErrorCode; /** The part the failure is about, when there is one. */ readonly partName: string | null; /** Whatever detail names the failure: an attribute value, a rel id, a slot. */ readonly detail: string | null; constructor(code: ModelErrorCode, message: string, partName?: string | null, detail?: string | null); }isModelErrorfunctionfunction isModelError(value: unknown): value is ModelError;
MODEL_ERROR_CODESconstconst MODEL_ERROR_CODES: readonly ["MODEL_PART_MISSING", "MODEL_PART_KIND", "MODEL_NO_PRESENTATION", "MODEL_NO_PARENT", "MODEL_NO_THEME", "MODEL_CLRMAP_INCOMPLETE", "MODEL_CLRMAP_SLOT", "MODEL_PLACEHOLDER_IDX", "MODEL_XFRM_NUMBER", "MODEL_GEOMETRY", "MODEL_STYLE_IDX", "MODEL_FONT_COLLECTION", "MODEL_NO_STYLE_MATRIX", "MODEL_STYLE_LIST_EMPTY", "MODEL_SHEET_CYCLE", "MODEL_FOREIGN_SHEET", "MODEL_TEXT_ATTR", "MODEL_TEXT_FIELD", "MODEL_TEXT_LEVEL", "MODEL_TEXT_BULLET", "MODEL_TEXT_TYPEFACE", "MODEL_TABLE_ATTR", "MODEL_TABLE_STYLE", "MODEL_TABLE_POSITION", "BLIP_NO_EMBED", "BLIP_DUOTONE", "BLIP_CLR_CHANGE", "BLIP_TILE_ALIGN", "BLIP_TILE_FLIP"];
src/parse/geometry.ts
ShapeGeometrytypeWhat a shape says it is.type ShapeGeometry = { readonly kind: 'preset'; readonly prst: string; readonly adjust: readonly PresetGuide[]; } | { readonly kind: 'custom'; readonly geometry: Geometry; };parseGeometryfunctionThe geometry a shape declares, orundefinedwhen it declares none.function parseGeometry(spPr: XElement | undefined, partName: string): ShapeGeometry | undefined;
src/text.ts
TextAligntypeST_TextAlignType.type TextAlign = 'l' | 'ctr' | 'r' | 'just' | 'justLow' | 'dist' | 'thaiDist';
FontAligntypeST_TextFontAlignType.type FontAlign = 'auto' | 't' | 'ctr' | 'base' | 'b';
UnderlinetypeST_TextUnderlineType, all seventeen, as written.type Underline = 'none' | 'words' | 'sng' | 'dbl' | 'heavy' | 'dotted' | 'dottedHeavy' | 'dash' | 'dashHeavy' | 'dashLong' | 'dashLongHeavy' | 'dotDash' | 'dotDashHeavy' | 'dotDotDash' | 'dotDotDashHeavy' | 'wavy' | 'wavyHeavy' | 'wavyDbl';
StriketypeST_TextStrikeType.type Strike = 'noStrike' | 'sngStrike' | 'dblStrike';
CapstypeST_TextCapsType.type Caps = 'none' | 'small' | 'all';
Spacingtypea:lnSpc,a:spcBefanda:spcAft, which are one of two quite different things and say which in their child element's name.type Spacing = { readonly kind: 'percent'; readonly value: number; } | { readonly kind: 'points'; readonly value: number; };TypefacetypeOne of the four typeface slots on a run.interface Typeface { readonly typeface: string; /** `@panose`, twenty hex characters. */ readonly panose: string | undefined; /** `@pitchFamily`, `(family << 4) | pitch`. */ readonly pitchFamily: number | undefined; /** `@charset`, **signed**: Shift-JIS is -128, not 128. */ readonly charset: number | undefined; }ThemeFontReftypeWhich of a theme's two font collections a+mj-/+mn-reference names.type ThemeFontRef = { readonly collection: 'major' | 'minor'; readonly script: 'latin' | 'ea' | 'cs'; };themeFontReffunction+mn-ltand its five siblings, ornullfor a real typeface name.function themeFontRef(typeface: string): ThemeFontRef | null;
RunPropstypeCT_TextCharacterProperties-a:rPr,a:defRPranda:endParaRPr.interface RunProps { /** `@sz`, hundredths of a point. 2400 is 24pt. */ readonly sz: number | undefined; readonly b: boolean | undefined; readonly i: boolean | undefined; readonly u: Underline | undefined; readonly strike: Strike | undefined; readonly cap: Caps | undefined; /** `@spc`, hundredths of a point. May be negative. */ readonly spc: number | undefined; /** `@kern`, hundredths of a point: the size at or above which to kern. */ readonly kern: number | undefined; /** `@baseline`, hundred-thousandths. 30000 is superscript. */ readonly baseline: number | undefined; readonly noProof: boolean | undefined; readonly lang: string | undefined; readonly altLang: string | undefined; readonly latin: Typeface | undefined; readonly ea: Typeface | undefined; readonly cs: Typeface | undefined; readonly sym: Typeface | undefined; /** The text's own fill: `a:solidFill` and its siblings inside `a:rPr`. */ readonly fill: Fill | undefined; /** `a:ln` inside `a:rPr`: the outline of the glyphs. */ readonly line: Line | undefined; readonly effects: readonly Effect[] | undefined; /** `a:highlight`, which is a colour and not a fill. */ readonly highlight: Color | undefined; /** The element this was read from. Edits go here, never to the fields above. */ readonly node: XElement; }BulletKindtypeThe exclusive group inCT_TextParagraphProperties: one of four, or nothing.type BulletKind = 'none' | 'char' | 'autonum' | 'blip';
BulletFonttypea:buFont/a:buFontTx, which are exclusive of each other.type BulletFont = { readonly kind: 'typeface'; readonly value: Typeface; } | /** `a:buFontTx`: follow the text, and cancel anything inherited. */ { readonly kind: 'text'; };BulletSizetypea:buSzPct/a:buSzPts/a:buSzTx.type BulletSize = /** `a:buSzPct/@val`, thousandths of a percent of the first run's size. */ { readonly kind: 'percent'; readonly value: number; } | /** `a:buSzPts/@val`, hundredths of a point, absolute. */ { readonly kind: 'points'; readonly value: number; } | { readonly kind: 'text'; };BulletColortypea:buClr/a:buClrTx.type BulletColor = { readonly kind: 'color'; readonly value: Color; } | { readonly kind: 'text'; };BulletAutoNumtypea:buAutoNum.interface BulletAutoNum { /** `@type`, one of the 41 `ST_TextAutonumberScheme` values. */ readonly type: string; /** * `@startAt`. Absent is measured to behave exactly as `1` - but the two are * kept apart, because a paragraph whose `startAt` differs from its * predecessor's begins a new run, and "absent" has to compare equal to "1" * for that rule rather than to nothing. */ readonly startAt: number | undefined; }ParaPropstypeCT_TextParagraphProperties-a:pPrand everya:lvlNpPr.interface ParaProps { /** `@marL`, EMU. Measured to default to **0**, not to the schema's 347663. */ readonly marL: number | undefined; readonly marR: number | undefined; /** `@indent`, EMU, usually negative. Defaults to 0, not to -342900. */ readonly indent: number | undefined; readonly algn: TextAlign | undefined; /** `@defTabSz`, EMU. */ readonly defTabSz: number | undefined; readonly rtl: boolean | undefined; readonly eaLnBrk: boolean | undefined; readonly fontAlgn: FontAlign | undefined; /** `@latinLnBrk`. ECMA says the default is true; PowerPoint behaves as false. */ readonly latinLnBrk: boolean | undefined; readonly hangingPunct: boolean | undefined; readonly lnSpc: Spacing | undefined; readonly spcBef: Spacing | undefined; readonly spcAft: Spacing | undefined; /** `a:defRPr`: the run properties every run in this paragraph starts from. */ readonly defRPr: RunProps | undefined; /** * Which of `a:buNone`, `a:buChar`, `a:buAutoNum` and `a:buBlip` this level * states, or `undefined` where it states none and inherits instead. */ readonly buKind: BulletKind | undefined; /** `a:buChar/@char`, exactly as written. The symbol mapping happens at draw time. */ readonly buChar: string | undefined; readonly buAutoNum: BulletAutoNum | undefined; /** `a:buBlip/a:blip/@r:embed`. */ readonly buBlip: string | undefined; /** * The three decorations, each its own slot. * * They merge independently of the kind and of each other, which is measured * rather than assumed: a level declaring only `a:buFont` re-faces the * character it inherits and keeps its size and colour, and a level declaring * only `a:buSzTx` cancels an inherited `a:buSzPct` and keeps the rest. * Measured on eleven cases twice - once through a shape's own `a:lstStyle` * and once through three hops of the master chain. */ readonly buFont: BulletFont | undefined; readonly buSize: BulletSize | undefined; readonly buColor: BulletColor | undefined; readonly node: XElement; }ListStyletypeCT_TextListStyle: nine levels, and ana:defPPrnothing reads.interface ListStyle { /** Nine entries, `a:lvl1pPr` through `a:lvl9pPr`, absent ones `undefined`. */ readonly levels: readonly (ParaProps | undefined)[]; /** `a:defPPr`. Preserved, never resolved against. */ readonly defPPr: ParaProps | undefined; readonly node: XElement; }LEVELSconstThe number of levels aCT_TextListStyleholds, and@lvl's range plus one.const LEVELS = 9;
TextRuntypea:r: a run of text with its own properties.interface TextRun { readonly kind: 'run'; readonly props: RunProps | undefined; readonly text: string; readonly node: XElement; }TextBreaktypea:br: a hard line break.interface TextBreak { readonly kind: 'br'; readonly props: RunProps | undefined; readonly node: XElement; }TextFieldtypea:fld: a field, with the text PowerPoint last cached for it.interface TextField { readonly kind: 'field'; /** `@id`, a required `ST_Guid`. Regenerating it is a repair risk. */ readonly id: string; /** `@type`, one of the fourteen reserved names or a custom one. */ readonly fieldType: string | undefined; readonly props: RunProps | undefined; readonly text: string; readonly node: XElement; }TextContenttypetype TextContent = TextRun | TextBreak | TextField;
Paragraphtypea:p.interface Paragraph { readonly props: ParaProps | undefined; /** * `a:pPr/@lvl`, 0 through 8, defaulting to 0. * * Read off the paragraph rather than inherited, and clamped rather than * thrown on: `ST_TextIndentLevelType` bounds it at 8, and a file outside the * bound is one PowerPoint still opens. */ readonly level: number; readonly content: readonly TextContent[]; /** `a:endParaRPr`: the properties of the (empty) run after the last one. */ readonly endParaRPr: RunProps | undefined; readonly node: XElement; }TextAnchortypeST_TextAnchoringType. PowerPoint laysjustanddistout asb.type TextAnchor = 't' | 'ctr' | 'b' | 'just' | 'dist';
VerticalTexttypeST_TextVerticalType.type VerticalText = 'horz' | 'vert' | 'vert270' | 'wordArtVert' | 'eaVert' | 'mongolianVert' | 'wordArtVertRtl';
TextBodytypep:txBody/a:txBody.interface TextBody { readonly bodyPr: BodyProps | undefined; readonly lstStyle: ListStyle | undefined; readonly paragraphs: readonly Paragraph[]; readonly node: XElement; }TextStyleBuckettypeThe bucket ofp:txStylesa shape reads, ornullfor one that reads none.type TextStyleBucket = 'title' | 'body' | 'other';
TextStylestypep:txStyleson a master.interface TextStyles { readonly title: ListStyle | undefined; readonly body: ListStyle | undefined; readonly other: ListStyle | undefined; readonly node: XElement; }
src/table.ts
TABLE_URIconsta:graphicData/@uriof a table.const TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table";
INVENTED_COLUMN_WIDTHconstThe column PowerPoint invents for a grid that declares none, empty: two margins and 2 pt.const INVENTED_COLUMN_WIDTH = 208280;
TablePropstypea:tblPr. The seven flags are the file's own and inherit from nothing, so absent is false.interface TableProps { readonly rtl: boolean; readonly firstRow: boolean; readonly firstCol: boolean; readonly lastRow: boolean; readonly lastCol: boolean; readonly bandRow: boolean; readonly bandCol: boolean; readonly fill: Fill | undefined; readonly effects: readonly Effect[] | undefined; readonly style: TableStyleRef | undefined; readonly node: XElement; }TableStyleReftypea:tableStyleId, or an inlinea:tableStyle, which PowerPoint resolves by its@styleIdalone.type TableStyleRef = { readonly kind: 'id'; readonly id: string; } | { readonly kind: 'inline'; readonly id: string; readonly node: XElement; };TableColumntypea:gridCol.interface TableColumn { /** `@w` in EMU. */ readonly w: number; readonly node: XElement; }TableRowtypea:tr.interface TableRow { /** `@h` in EMU: the least the row is drawn at, never the most. */ readonly h: number; readonly cells: readonly TableCell[]; readonly node: XElement; }TableCelltypea:tc: an absent span reads as 1 and an absent flag as false;tableGridsays what they mean.interface TableCell { readonly gridSpan: number; readonly rowSpan: number; readonly hMerge: boolean; readonly vMerge: boolean; /** `@id`, which `a:headers` in other cells name. */ readonly id: string | null; readonly text: TextBody | undefined; readonly props: TableCellProps | undefined; readonly node: XElement; }TableCellBorderstypeThe sixa:tcPrborders, each ana:lnunder another name.interface TableCellBorders { readonly left: Line | undefined; readonly right: Line | undefined; readonly top: Line | undefined; readonly bottom: Line | undefined; readonly tlToBr: Line | undefined; readonly blToTr: Line | undefined; }TableCellPropstypea:tcPr. Margins are EMU as written; the schema's defaults are 91440 and 45720.interface TableCellProps { readonly marL: number | undefined; readonly marR: number | undefined; readonly marT: number | undefined; readonly marB: number | undefined; readonly vert: VerticalText | undefined; readonly anchor: TextAnchor | undefined; readonly anchorCtr: boolean | undefined; readonly horzOverflow: HorzOverflow | undefined; readonly borders: TableCellBorders; readonly fill: Fill | undefined; /** `a:headers/a:header`, the ids of the cells that head this one. */ readonly headers: readonly string[]; readonly node: XElement; }Tabletypeinterface Table { readonly props: TableProps | undefined; readonly columns: readonly TableColumn[]; readonly rows: readonly TableRow[]; readonly node: XElement; }GridCelltypeA grid position's owner: the anchor cell, its clamped span, and thea:tcthere.interface GridCell { readonly row: number; readonly col: number; readonly rows: number; readonly cols: number; /** `null` for a position no `a:tc` reached, which PowerPoint draws empty. */ readonly cell: TableCell | null; }TableGridtypeThe grid as drawn:positions[r][c]is the owner of (r, c);anchorslists each owner once.interface TableGrid { readonly rows: number; readonly cols: number; /** Column widths in EMU. */ readonly widths: readonly number[]; /** Row heights in EMU, each the least its row is drawn at. */ readonly heights: readonly number[]; readonly positions: readonly (readonly GridCell[])[]; readonly anchors: readonly GridCell[]; }tableGridfunctionThe occupancy C7 measured, 76/76 against 52/76 for the flags: eacha:tctakes the next column, a claimed position is covered whatever it says, a span stops at the edge or a claim.function tableGrid(table: Table): TableGrid;
OnOffStyletypeST_OnOffStyleType.type OnOffStyle = 'on' | 'off' | 'def';
ThemeabletypeA value written out, or a reference into the theme: theEG_Themeable*choices.type Themeable<T, Ref = StyleRef> = { readonly kind: 'value'; readonly value: T; } | { readonly kind: 'ref'; readonly ref: Ref; };TableStyleTexttypea:tcTxStyle.interface TableStyleText { readonly b: OnOffStyle | undefined; readonly i: OnOffStyle | undefined; readonly font: Themeable<FontCollection, FontRef> | undefined; readonly color: Color | undefined; }TableStyleBorderstypea:tcBdr;tl2brandtr2bltake the namesTableCellBordersgives the diagonals.interface TableStyleBorders { readonly left: Themeable<Line> | undefined; readonly right: Themeable<Line> | undefined; readonly top: Themeable<Line> | undefined; readonly bottom: Themeable<Line> | undefined; readonly insideH: Themeable<Line> | undefined; readonly insideV: Themeable<Line> | undefined; readonly tlToBr: Themeable<Line> | undefined; readonly blToTr: Themeable<Line> | undefined; }TableStyleCelltypea:tcStyle.interface TableStyleCell { readonly borders: TableStyleBorders | undefined; readonly fill: Themeable<Fill> | undefined; /** `a:cell3D`, kept as written. */ readonly cell3D: XElement | undefined; }TableStyleParttypeOne of a style's thirteen parts.interface TableStylePart { readonly text: TableStyleText | undefined; readonly cell: TableStyleCell | undefined; }TableBackgroundtypea:tblBg. Ana:effectholding ana:effectDagreads asundefined, asparseEffectsdoes.interface TableBackground { readonly fill: Themeable<Fill> | undefined; readonly effect: Themeable<readonly Effect[] | undefined> | undefined; }TableStylePartNametypeThe thirteen parts in schema order, which is the order they compose in, lowest first (C9).type TableStylePartName = 'wholeTbl' | 'band1H' | 'band2H' | 'band1V' | 'band2V' | 'lastCol' | 'firstCol' | 'lastRow' | 'seCell' | 'swCell' | 'firstRow' | 'neCell' | 'nwCell';
TableStyletypeCT_TableStyle: ana:tblStyle, or an inlinea:tableStyle. Nothing absent is defaulted.interface TableStyle { readonly id: string; readonly name: string; readonly background: TableBackground | undefined; readonly parts: Readonly<Partial<Record<TableStylePartName, TableStylePart>>>; readonly node: XElement; }TableBackgroundLayerstypeWhat paints under a table's cells, each layer with where it came from.interface TableBackgroundLayers { readonly fill: TableSourced<Themeable<Fill>> | null; readonly effects: TableSourced<Themeable<readonly Effect[] | undefined>> | null; }TableDiagonalstypeA cell's diagonals as drawn:downfrom its visual top left,upfrom its visual bottom left.interface TableDiagonals { readonly down: Line | null; readonly up: Line | null; }TableEdgetypeA grid edge:his the top of rowrowat columncol(row = rowsis the bottom);vthe left of columncol.interface TableEdge { readonly axis: 'h' | 'v'; readonly row: number; readonly col: number; }TableSourcetypeWhere a table's format came from: a style part,tblBg, a cell'sa:tcPr,a:tblPr, or the default grid.type TableSource = TableStylePartName | 'tblBg' | 'tcPr' | 'tblPr' | 'grid';
TableSourcedtypeinterface TableSourced<T> { readonly value: T; readonly source: TableSource; }
src/types.ts
Xfrmtypea:offanda:exttogether, in EMU, plus the three transform attributes.interface Xfrm { readonly x: number; readonly y: number; readonly cx: number; readonly cy: number; /** `@rot`, sixtieths of a degree. Zero when the attribute was absent. */ readonly rot: number; readonly flipH: boolean; readonly flipV: boolean; /** `a:chOff`/`a:chExt`, present only on a group's `a:xfrm`. */ readonly child: { readonly x: number; readonly y: number; readonly cx: number; readonly cy: number; } | null; }PlaceholderTypetypeST_PlaceholderType. All nineteen, as written.type PlaceholderType = 'title' | 'body' | 'ctrTitle' | 'subTitle' | 'obj' | 'chart' | 'tbl' | 'clipArt' | 'dgm' | 'media' | 'sldImg' | 'pic' | 'sldNum' | 'hdr' | 'ftr' | 'dt';
PLACEHOLDER_TYPESconstconst PLACEHOLDER_TYPES: readonly PlaceholderType[];
MASTER_PLACEHOLDER_TYPESconstThe six a slide master may carry. Measured; seePlaceholderType.const MASTER_PLACEHOLDER_TYPES: readonly PlaceholderType[];
PlaceholderSizetype@sz, a sizing hint. Recorded, and not part of matching - measured.type PlaceholderSize = 'full' | 'half' | 'quarter';
Placeholdertypeinterface Placeholder { /** * `@type` as written, or `null` when the attribute was absent. * * `null` is kept rather than defaulted, because "the file said `obj`" and * "the file said nothing" are different facts and only the second one is safe * to rewrite. `normalizePlaceholder` supplies the default when a comparison * needs one. */ readonly type: PlaceholderType | null; /** `@idx` as written, or `null` when absent. Defaults to 0 when compared. */ readonly idx: number | null; readonly size: PlaceholderSize | null; /** `@orient`. Recorded, and not part of matching. */ readonly orient: 'horz' | 'vert' | null; readonly hasCustomPrompt: boolean; }NormalPlaceholdertypeA placeholder with its defaults supplied: what the matcher compares.interface NormalPlaceholder { readonly type: PlaceholderType; readonly idx: number; }ShapeKindtypeOne of the six things ap:spTreemay contain.type ShapeKind = 'sp' | 'pic' | 'grpSp' | 'graphicFrame' | 'cxnSp' | 'contentPart';
StyleReftypea:lnRef,a:fillRefanda:effectRef: an index into the style matrix.interface StyleRef { /** * `@idx`. Zero means none; 1..999 index the main list; 1001 and up index the * background list, offset by 1000. Measured on both `a:fillRef` and * `p:bgRef`, which turn out to be the same rule over the same six entries. */ readonly idx: number; /** The colour `phClr` takes inside the entry this reference names. */ readonly color: Color | null; }FontReftypea:fontRef.@idxis a collection name, never a number.interface FontRef { readonly idx: 'major' | 'minor' | 'none'; readonly color: Color | null; }ShapeStyletypep:style: four references into the theme'sa:fmtSchemeanda:fontScheme.interface ShapeStyle { readonly lnRef: StyleRef; readonly fillRef: StyleRef; readonly effectRef: StyleRef; readonly fontRef: FontRef; }ShapetypeA shape, exactly as its part wrote it.interface Shape { readonly kind: ShapeKind; /** `p:cNvPr/@id`. Unique within a part, and may repeat across parts. */ readonly cNvPrId: number; readonly name: string; /** `p:cNvPr/@descr`, the alt text. */ readonly descr: string | null; readonly hidden: boolean; readonly placeholder: Placeholder | null; readonly xfrm: Xfrm | undefined; readonly fill: Fill | undefined; readonly line: Line | undefined; readonly effects: readonly Effect[] | undefined; readonly style: ShapeStyle | undefined; /** `a:prstGeom/@prst`, or `null` for a `custGeom` or no geometry at all. */ readonly prstGeom: string | undefined; /** * `a:prstGeom` or `a:custGeom`, parsed far enough to draw. * * `undefined` when the shape declares neither, which is the ordinary state of * a slide placeholder: it inherits its outline from its layout exactly as it * inherits its rectangle, and `resolve` is what asks. */ readonly geometry: ShapeGeometry | undefined; /** * `p:txBody`, when the shape has one. * * Present on every `p:sp` PowerPoint writes, including the ones with no text * in them, and absent from a `p:pic` or a `p:graphicFrame`. Its `a:lstStyle` * is one level of the text cascade; the paragraphs are the text itself. */ readonly text: TextBody | undefined; /** The `a:tbl` of a `p:graphicFrame` whose graphic data is a table. */ readonly table: Table | undefined; /** Children, for a `grpSp`. Empty for everything else. */ readonly children: readonly Shape[]; /** The element this was read from. Edits go here, never to the fields above. */ readonly node: XElement; }Backgroundtypep:bg, which is one of two quite different things.type Background = { readonly kind: 'fill'; readonly fill: Fill; readonly effects: readonly Effect[] | undefined; } | { readonly kind: 'ref'; readonly ref: StyleRef; };FormatSchemetypea:fmtScheme: four lists of style entries, held as the elements they were.interface FormatScheme { readonly name: string | null; /** `a:fillStyleLst`. Each entry is a whole `EG_FillProperties` element. */ readonly fillStyles: readonly Fill[]; /** `a:lnStyleLst`. Each entry is a whole `a:ln`. */ readonly lineStyles: readonly Line[]; /** `a:effectStyleLst`. Each entry's `a:effectLst`, flattened. */ readonly effectStyles: readonly (readonly Effect[])[]; /** `a:bgFillStyleLst`, which `@idx` 1001 and up reach. */ readonly bgFillStyles: readonly Fill[]; }FontCollectiontypea:fontScheme: the two collections+mj-and+mn-name.interface FontCollection { /** `a:latin/@typeface`. An empty string means the theme states none. */ readonly latin: string | null; readonly ea: string | null; readonly cs: string | null; }FontSchemetypeinterface FontScheme { readonly name: string | null; readonly major: FontCollection; readonly minor: FontCollection; }Themetypeinterface Theme { readonly partName: string; readonly name: string | null; readonly scheme: ClrScheme; readonly fonts: FontScheme; readonly format: FormatScheme | null; readonly node: XElement; }SheetKindtypetype SheetKind = 'slide' | 'layout' | 'master';
ColorMapOverridetypep:clrMapOvr, which has exactly two forms and one surprise.type ColorMapOverride = { readonly kind: 'inherit'; } | { readonly kind: 'override'; readonly map: ClrMap; };SheettypeA slide, a layout or a master, with its parent already resolved.interface Sheet { readonly kind: SheetKind; readonly partName: string; /** `p:cSld/@name`. */ readonly name: string | null; /** `p:sldLayout/@type`, one of `ST_SlideLayoutType`. Layouts only. */ readonly layoutType: string | null; /** `p:sldLayout/@matchingName`. Layouts only, and only when written. */ readonly matchingName: string | null; readonly shapes: readonly Shape[]; readonly background: Background | undefined; /** `p:clrMap`, on a master. `undefined` everywhere else. */ readonly clrMap: ClrMap | undefined; /** * `p:txStyles`, on a master. `undefined` everywhere else, and meaningfully so. * * A master that declares none does not get a partial one: PowerPoint * substitutes its whole built-in set, measured in 3.1. So the difference * between `undefined` and a `p:txStyles` whose buckets say nothing is the * difference between a 28-point body placeholder and an 18-point one. */ readonly txStyles: TextStyles | undefined; /** `p:clrMapOvr`, on a layout or a slide. */ readonly clrMapOvr: ColorMapOverride | undefined; /** `@showMasterSp`, defaulting to true. Slides and layouts. */ readonly showMasterShapes: boolean; /** The layout of a slide, the master of a layout, `null` for a master and for * a sheet whose binding is missing - which PowerPoint repairs rather than * refuses, so it has to be representable. */ readonly parent: Sheet | null; /** The theme, on a master. Every other sheet reaches it through `parent`. */ readonly theme: Theme | null; readonly node: XElement; }OrigintypeWhere a resolved value came from: each member is a level the text cascade reads (ADR 0027, 0064).type Origin = /** The run's own `a:rPr`. */ 'run' | /** The paragraph's `a:pPr`, or its `a:defRPr`. */ 'paragraph' | /** The shape itself: its `p:spPr`, or its own `a:lstStyle`. */ 'shape' | /** A table cell's own `a:txBody/a:lstStyle`. */ 'cell' | /** What a table's style, or PowerPoint's default grid, gives a cell's text. */ 'tableStyle' | 'layoutPh' | 'masterPh' | /** The master's `p:txStyles`: the bucket a shape's chain selects, `p:otherStyle` for a cell. */ 'txStyles' | /** `p:defaultTextStyle`, which only a shape with no bucket reaches. */ 'defaultTextStyle' | /** PowerPoint's own text styles, substituted for a master that declares none. */ 'builtin' | 'theme' | 'schemaDefault';
ResolvedtypeA value, where it came from, and whether the thing that owns it said so.interface Resolved<T> { readonly value: T; readonly origin: Origin; readonly explicit: boolean; /** The sheet the value was found on, when one was involved. */ readonly sheet: Sheet | null; /** The shape the value was found on, when one was involved. */ readonly shape: Shape | null; }
src/parse/paint.ts
parseColorElementfunctionOne of the sixEG_ColorChoicemembers.function parseColorElement(element: XElement): Color;
parseColorChildfunctionThe first colour child of a wrapper such asa:solidFillora:fillRef.function parseColorChild(parent: XElement | undefined): Color | null;
parseFillElementfunctionOne member ofEG_FillProperties.function parseFillElement(element: XElement, partName: string): Fill;
parseFillfunctionThe fill a container declares, orundefinedwhen it declares none.function parseFill(parent: XElement, partName: string): Fill | undefined;
parseLineElementfunctiona:ln, lazily: every field isnullwhen the attribute was absent.function parseLineElement(element: XElement, partName: string): Line;
parseLinefunctionfunction parseLine(parent: XElement, partName: string): Line | undefined;
parseEffectsfunctiona:effectLst, in the order the file wrote it.function parseEffects(parent: XElement): readonly Effect[] | undefined;
src/parse/sheet.ts
parseClrMapfunctionp:clrMapora:overrideClrMapping: all twelve attributes, every time.function parseClrMap(element: XElement, partName: string): ClrMap;
parseThemefunctionfunction parseTheme(root: XElement, partName: string): Theme;
parseSheetfunctionOne part into one sheet. The parent and the theme are filled in bydocument.ts, which is the only thing that can follow a relationship.function parseSheet(root: XElement, partName: string): Omit<Sheet, 'parent' | 'theme'>;
src/resolve/placeholder.ts
DEFAULT_PLACEHOLDER_TYPEconstThe type of ap:phthat has none.const DEFAULT_PLACEHOLDER_TYPE: PlaceholderType;
DEFAULT_PLACEHOLDER_IDXconstThe@idxof ap:phthat has none.const DEFAULT_PLACEHOLDER_IDX = 0;
normalizePlaceholderfunctionSupply the two defaults, so a comparison has something to compare.function normalizePlaceholder(ph: Placeholder): NormalPlaceholder;
masterPlaceholderTypefunctionThe type a placeholder presents when it asks a master for its parent.function masterPlaceholderType(type: PlaceholderType): PlaceholderType;
placeholdersfunctionEvery placeholder in a sheet's top-level shape tree, in document order.function placeholders(sheet: Sheet): readonly Shape[];
matchInLayoutfunctionSlide to layout: the first placeholder whose@idxagrees.function matchInLayout(ph: Placeholder, layout: Sheet): Shape | null;
matchInMasterfunctionLayout to master: the first placeholder of the folded type.function matchInMaster(ph: Placeholder, master: Sheet): Shape | null;
ChainLinktypeOne link of the chain: a shape, the sheet it is on, and how it was reached.interface ChainLink { readonly shape: Shape; readonly sheet: Sheet; /** `shape` for the first link, then `layoutPh`, then `masterPh`. */ readonly origin: 'shape' | 'layoutPh' | 'masterPh'; }inheritanceChainfunctionThe chain a shape inherits along, nearest first.function inheritanceChain(shape: Shape, sheet: Sheet): readonly ChainLink[];
ORPHAN_RECTconstA placeholder that reached no parent and states no geometry of its own.const ORPHAN_RECT: { readonly x: 0; readonly y: 0; readonly cx: 0; readonly cy: 0; };
src/resolve/resolve.ts
resolvefunctionThe first level of the chain that declared something.function resolve<T>(shape: Shape, sheet: Sheet, pick: (shape: Shape) => T | undefined): Resolved<T> | undefined;
resolveXfrmfunctionThe rectangle a shape occupies, and which sheet stated it.function resolveXfrm(shape: Shape, sheet: Sheet): Resolved<Xfrm> | undefined;
sheetChainfunctionEvery sheet from this one up to its master, nearest first.function sheetChain(sheet: Sheet): readonly Sheet[];
masterOffunctionThe master at the top of a sheet's chain, ornullif the chain is broken.function masterOf(sheet: Sheet): Sheet | null;
themeOffunctionThe theme a sheet resolves against.function themeOf(sheet: Sheet): Theme | null;
schemeOffunctionfunction schemeOf(sheet: Sheet): ClrScheme | undefined;
colorMapOffunctionThe colour map in force on a sheet.function colorMapOf(sheet: Sheet): ClrMap | undefined;
colorContextOffunctionEverythingresolveColorneeds, for a colour written on this sheet.function colorContextOf(sheet: Sheet, phClr?: Rgba): ColorContext;
src/style.ts
STYLE_MATRIX_OFFSETconstThe offset that separates the two style lists.const STYLE_MATRIX_OFFSET = 1000;
StyleMatrixTargettypeWhich of the two lists an index reaches, and where in it.type StyleMatrixTarget = { readonly list: 'none'; } | { readonly list: 'main'; readonly at: number; } | { readonly list: 'background'; readonly at: number; };styleMatrixTargetfunctionWhere an index points, before anything is fetched.function styleMatrixTarget(idx: number): StyleMatrixTarget;
styleMatrixFillfunctionThe fill afillRef/bgRefindex names, ornullfor none.function styleMatrixFill(ref: StyleRef, theme: Theme): Fill | null;
styleMatrixLinefunctionThe line anlnRefindex names, ornullfor none.function styleMatrixLine(ref: StyleRef, theme: Theme): Line | null;
styleMatrixEffectsfunctionThe effects aneffectRefindex names. Empty for none.function styleMatrixEffects(ref: StyleRef, theme: Theme): readonly Effect[];
phClrOffunctionThe colour a style reference invokes its entry with.function phClrOf(ref: StyleRef, sheet: Sheet): Rgba | null;
ResolvedAppearancetypeWhat a shape paints, and where each half of the answer came from.interface ResolvedAppearance { /** `null` means nothing is painted: no fill was declared and no style names one. */ readonly fill: Fill | null; readonly fillOrigin: Origin | null; /** The colour `phClr` resolves to inside `fill`, when it came from the theme. */ readonly fillPhClr: Rgba | null; readonly line: Line | null; readonly lineOrigin: Origin | null; readonly linePhClr: Rgba | null; readonly effects: readonly Effect[] | null; }resolveAppearancefunctionWhat a shape paints, following both routes and in the right order.function resolveAppearance(shape: Shape, sheet: Sheet): ResolvedAppearance;
resolveSolidFillfunctionA shape's fill as a single colour, when it is one.function resolveSolidFill(shape: Shape, sheet: Sheet): Rgba | null;
resolveOnSheetfunctionResolve any colour written on a sheet, with an optionalphClrin scope.function resolveOnSheet(color: Color, sheet: Sheet, phClr?: Rgba): Rgba;
src/resolve/background.ts
ResolvedBackgroundtypeA background, with the sheet that declared it and how it was expressed.interface ResolvedBackground { readonly fill: Fill; /** The sheet whose `p:bg` this is. */ readonly sheet: Sheet; /** True when the sheet asked for it is the one that declared it. */ readonly explicit: boolean; /** `bgPr` or `bgRef`, because they round-trip differently. */ readonly form: 'bgPr' | 'bgRef'; /** The colour `phClr` takes inside `fill`, for a `bgRef`. */ readonly phClr: Rgba | null; }backgroundSheetfunctionWhich sheet'sp:bgapplies, without unpacking it.function backgroundSheet(sheet: Sheet): { sheet: Sheet; background: Background; } | null;resolveBackgroundfunctionThe background of a slide, layout or master.function resolveBackground(sheet: Sheet): ResolvedBackground | null;
resolveBackgroundColorfunctionThe background as one colour, when it is a solid.nullotherwise.function resolveBackgroundColor(sheet: Sheet): Rgba | null;
src/document.ts
DocumentProblemtypeOne thing wrong with the package that did not stop the load.interface DocumentProblem { readonly code: 'MODEL_NO_PARENT' | 'MODEL_NO_THEME' | 'MODEL_PART_MISSING' | 'MODEL_PART_KIND'; readonly partName: string; readonly message: string; }DocumenttypeA loaded presentation: its slides, inp:sldIdLstorder, each with its chain.interface Document { /** The presentation part, for the parts of it 2.9 does not model. */ readonly presentation: XElement; readonly presentationPartName: string; /** In `p:sldIdLst` order, which *is* the deck's order. */ readonly slides: readonly Sheet[]; /** In `p:sldMasterIdLst` order. */ readonly masters: readonly Sheet[]; /** Every layout reachable from a master, in the order its master lists it. */ readonly layouts: readonly Sheet[]; readonly themes: readonly Theme[]; readonly problems: readonly DocumentProblem[]; /** * `p:defaultTextStyle`, the terminus of the text cascade for every shape that * reaches no `p:txStyles` bucket - which is every shape that is not a * placeholder, and the `dt`, `ftr`, `sldNum` and `hdr` placeholders besides. * * It lives on the presentation part, so it belongs to the package rather than * to any sheet, and `undefined` means the package declared none. */ readonly defaultTextStyle: ListStyle | undefined; /** Slide size in EMU, from `p:sldSz`. */ readonly slideSize: { readonly cx: number; readonly cy: number; }; sheet(partName: string): Sheet | undefined; }loadDocumentfunctionfunction loadDocument(store: PartStore): Document;
src/parse/text.ts
parseRunPropsfunctiona:rPr,a:defRProra:endParaRPr- one type under three names.function parseRunProps(element: XElement, partName: string): RunProps;
parseParaPropsfunctiona:pPr,a:defPPror anya:lvlNpPr- one type under eleven names.function parseParaProps(element: XElement, partName: string): ParaProps;
parseListStylefunctiona:lstStyle, or ap:txStylesbucket, which is the same type unwrapped.function parseListStyle(element: XElement, partName: string): ListStyle;
parseTextStylesfunctionp:txStyleson a master.function parseTextStyles(element: XElement, partName: string): TextStyles;
parseDefaultTextStylefunctionp:defaultTextStyleonppt/presentation.xml, which is aCT_TextListStyle.function parseDefaultTextStyle(presentation: XElement, partName: string): ListStyle | undefined;
parseTextBodyfunctionAp:txBodyor ana:txBody.function parseTextBody(element: XElement, partName: string): TextBody;
parseTextBodyChildfunctionThep:txBodyof a shape, when it has one.function parseTextBodyChild(parent: XElement, partName: string): TextBody | undefined;
src/builtin/text-styles.ts
BuiltinLeveltypeOne level of a built-in list style.interface BuiltinLevel { /** Hundredths of a point, as `a:defRPr/@sz` holds it. */ readonly sz: number; /** EMU, as `a:lvlNpPr/@marL` holds it. */ readonly marL: number; /** EMU, as `a:lvlNpPr/@indent` holds it. Negative is a hanging indent. */ readonly indent: number; readonly bullet: boolean; /** * The theme reference this level names, or `null` where it names none. * * A reference and not a face, because the built-in styles are the same * whatever theme a package carries: `+mj-lt` measured as the theme's major * face and `+mn-lt` as its minor. */ readonly typeface: string | null; }BUILTIN_TEXT_STYLESconstThe three buckets, nine levels each, level 1 first.const BUILTIN_TEXT_STYLES: { readonly title: readonly BuiltinLevel[]; readonly body: readonly BuiltinLevel[]; readonly other: readonly BuiltinLevel[]; };TEXT_FLOORconstWhat is left when every source is silent and the master *does* declarep:txStyles.const TEXT_FLOOR: BuiltinLevel;
src/builtin/table-styles.ts
BuiltinTableStyletypePowerPoint's 74 built-in table styles, eacha:tblStylebyte for byte as PowerPoint writes it. GENERATED by tools/ground-truth/model/tables/styles/write-tables.ts from corpus/ground-truth/table-styles.json. Do not edit: table.test.ts re-derives it.interface BuiltinTableStyle { readonly id: string; readonly name: string; /** The `a:tblStyle` PowerPoint writes into `ppt/tableStyles.xml` for this style. */ readonly xml: string; }BUILTIN_TABLE_STYLESconstIn the order of PowerPoint's Table Styles gallery.const BUILTIN_TABLE_STYLES: readonly BuiltinTableStyle[];
src/resolve/text.ts
bucketOffunctionWhichp:txStylesbucket a placeholder type reads, ornullfor none.function bucketOf(type: string): 'title' | 'body' | null;
TextContexttypeEverything the cascade needs that is not on the shape.defaultTextStyleis the package's, fromppt/presentation.xml;undefinedis a package that declares none, which PowerPoint tells apart.interface TextContext { readonly sheet: Sheet; readonly shape: Shape; readonly defaultTextStyle: ListStyle | undefined; /** Set for the text of a table cell, whose walk is its own (C9, ADR 0064). */ readonly cell?: TableCellText; }TableCellTexttypeA table cell's two levels of its own: itsa:lstStyle, and what the table's style gives it.interface TableCellText { readonly lstStyle: ListStyle | undefined; /** `tableTextLayer`'s answer for the cell. */ readonly layer: RunProps; }textLevelsfunctionThe list styles a shape or a table cell reads, nearest first, ending at whichever terminus it reaches. Exported so a caller that shows where a value could come from walks the same list.function textLevels(context: TextContext): readonly Level[];
floorOffunctionThe values left when every level has been asked and none of them said (ADR 0027). A master withp:txStylesleavesTEXT_FLOOR; one without substitutes PowerPoint's built-ins.function floorOf(context: TextContext, level: number): BuiltinLevel;
resolveParagraphfunctionA paragraph property, from the paragraph's owna:pPror up the walk.function resolveParagraph<T>(context: TextContext, paragraph: Paragraph, pick: (props: ParaProps) => T | undefined): Resolved<T> | undefined;
resolveRunfunctionA run property, from the run's owna:rPrand then everya:defRPrabove it.function resolveRun<T>(context: TextContext, paragraph: Paragraph, run: TextContent | undefined, pick: (props: RunProps) => T | undefined): Resolved<T> | undefined;
resolveSizefunctionThe font size of a run, in hundredths of a point, always.function resolveSize(context: TextContext, paragraph: Paragraph, run: TextContent | undefined): Resolved<number>;
resolveLatinTypefacefunctionThe Latin typeface of a run, with any theme reference followed.function resolveLatinTypeface(context: TextContext, paragraph: Paragraph, run: TextContent | undefined): Resolved<string>;
resolveMarginLeftfunction@marLin EMU. Measured to be 0 when nothing declares it, not 347663.function resolveMarginLeft(context: TextContext, paragraph: Paragraph): Resolved<number>;
resolveIndentfunction@indentin EMU. Measured to be 0 when nothing declares it, not -342900.function resolveIndent(context: TextContext, paragraph: Paragraph): Resolved<number>;
resolveBulletKindfunctionThe bullet, merged the way T5 measured it: five slots, each on its own.function resolveBulletKind(context: TextContext, paragraph: Paragraph): Resolved<BulletKind> | undefined;
resolveBulletCharfunctiona:buChar/@char, as written. The symbol mapping belongs to the renderer.function resolveBulletChar(context: TextContext, paragraph: Paragraph): Resolved<string> | undefined;
resolveBulletAutoNumfunctiona:buAutoNum, type and start value together, since one is meaningless alone.function resolveBulletAutoNum(context: TextContext, paragraph: Paragraph): Resolved<BulletAutoNum> | undefined;
resolveBulletBlipfunctiona:buBlip/a:blip/@r:embed, which the caller resolves against the part's rels.function resolveBulletBlip(context: TextContext, paragraph: Paragraph): Resolved<string> | undefined;
resolveBulletFontfunctiona:buFontora:buFontTx.function resolveBulletFont(context: TextContext, paragraph: Paragraph): Resolved<BulletFont> | undefined;
resolveBulletSizefunctiona:buSzPct,a:buSzPtsora:buSzTx; a percentage is of the first run's size.function resolveBulletSize(context: TextContext, paragraph: Paragraph): Resolved<BulletSize> | undefined;
resolveBulletColorfunctiona:buClrora:buClrTx. Unlike the font, this one *does* reach an autonumber.function resolveBulletColor(context: TextContext, paragraph: Paragraph): Resolved<BulletColor> | undefined;
src/resolve/body.ts
ResolvedInsetstypeThe four insets in points, per attribute.interface ResolvedInsets { readonly left: number; readonly top: number; readonly right: number; readonly bottom: number; }resolveBodyfunctionOne property of the text frame, from the shape's owna:bodyPror above it.function resolveBody<T>(shape: Shape, sheet: Sheet, pick: (props: BodyProps) => T | undefined): Resolved<T> | undefined;
resolveAnchorfunctionfunction resolveAnchor(shape: Shape, sheet: Sheet): Resolved<TextAnchor> | undefined;
resolveAnchorCtrfunctionfunction resolveAnchorCtr(shape: Shape, sheet: Sheet): Resolved<boolean> | undefined;
resolveVerticalfunctionfunction resolveVertical(shape: Shape, sheet: Sheet): Resolved<VerticalText> | undefined;
resolveWrapfunctionfunction resolveWrap(shape: Shape, sheet: Sheet): Resolved<TextWrap> | undefined;
resolveColumnsfunctionfunction resolveColumns(shape: Shape, sheet: Sheet): Resolved<number> | undefined;
resolveInsetsfunctionThe four insets, in points, each falling back on its own.function resolveInsets(shape: Shape, sheet: Sheet): ResolvedInsets;
src/parse/body.ts
parseBodyPropsfunctionParse ana:bodyPr. Lengths stay in EMU and angles in 60000ths of a degree.function parseBodyProps(element: XElement, partName: string): BodyProps;
parseBodyPropsChildfunctionThea:bodyProf ap:txBody, when it has one.function parseBodyPropsChild(parent: XElement, partName: string): BodyProps | undefined;
src/parse/table.ts
parseTablefunctionAna:tbl.function parseTable(element: XElement, part: string): Table;
parseTableChildfunctionThe table of ap:graphicFrame, when itsa:graphicDatacarries one.function parseTableChild(frame: XElement, part: string): Table | undefined;
parseTableStylefunctionAna:tblStyleor an inlinea:tableStyle:CT_TableStyle.function parseTableStyle(element: XElement, part: string): TableStyle;
src/resolve/table.ts
builtinTableStylefunctionOne of PowerPoint's 74 built-ins by GUID, in any case, parsed afresh;undefinedfor any other.function builtinTableStyle(id: string): TableStyle | undefined;
tableStyleOffunctionThe built-in style a table is drawn with, ornullfor PowerPoint's default: a 1-pt black grid and no fill, whatever the theme and whatever the package defines.function tableStyleOf(table: Table): TableStyle | null;
TABLE_PART_ORDERconstThe order the parts compose in, lowest first: C9 on every drawable table (ADR 0064).const TABLE_PART_ORDER: readonly ["wholeTbl", "band1H", "band2H", "band1V", "band2V", "lastCol", "firstCol", "lastRow", "seCell", "swCell", "firstRow", "neCell", "nwCell"];
tablePartsAtfunctionThe parts reaching grid position (row, col), highest first: ECMA-376's reading, which C9 found alone fits (ADR 0064). Bands skip the rows and columns their end flags take, and a corner part needs both of its flags.function tablePartsAt(props: TableProps | undefined, rows: number, cols: number, row: number, col: number): readonly TableStylePartName[];
tableCellFillfunctionThe fill of the cell at grid position (row, col): its owna:tcPrfill, else the highest part that states one. Parts compose per property (C9);nullpaints nothing, and one translucent fill is painted alone, never over another part's.function tableCellFill(table: Table, style: TableStyle | null, grid: TableGrid, row: number, col: number): TableSourced<Themeable<Fill>> | null;
tableBackgroundfunctionWhat paints under the cells, over the grid and never the frame as written:a:tblPr's own fill and effect list, each in place of the style'stblBgone, an empty list included (C9).function tableBackground(table: Table, style: TableStyle | null): TableBackgroundLayers;
tableCellDiagonalsfunctionThe diagonals of the cell at (row, col) as drawn across its whole span:downfrom its visual top left,upfrom its visual bottom left. Only the anchor's own lines draw, mirrored in an rtl table; no built-in states a diagonal (C8) and a covered position's own are never read (C9).function tableCellDiagonals(table: Table, grid: TableGrid, row: number, col: number): TableDiagonals;
DEFAULT_GRID_LINEconstPowerPoint's default grid: a 1-pt black line on every edge of a table that names no built-in (C8).const DEFAULT_GRID_LINE: Line;
tableEdgeLinefunctionThe line a grid edge draws: its owner'sa:tcPrline, else the highest part of either cell that states it, a part reaching both offering its inside edge (C9). The owner is the cell before (above, left) where its anchor is level with the edge, else the cell after where its anchor is, else the cell before;nullinside a merged cell.function tableEdgeLine(table: Table, style: TableStyle | null, grid: TableGrid, edge: TableEdge): TableSourced<Themeable<Line>> | null;
tableTextLayerfunctionWhat the style gives the text of the cell at (row, col): bold, italic, face and colour, each from the highest part that states it (C9), as run properties for the text cascade. The default grid givestx1in the minor face whatever the flags;nodeis the style's element, or the table's for the grid.function tableTextLayer(table: Table, style: TableStyle | null, grid: TableGrid, row: number, col: number): RunProps;
themedFillfunctionA style fill with afillReffollowed into the theme, and the colourphClrtakes in it.function themedFill(fill: Themeable<Fill>, theme: Theme, colors: ColorContext): { readonly fill: Fill | null; readonly phClr: Rgba | null; };themedEffectsfunctionA style effect list with aneffectReffollowed into the theme, and the colourphClrtakes.function themedEffects(effects: Themeable<readonly Effect[] | undefined>, theme: Theme, colors: ColorContext): { readonly effects: readonly Effect[]; readonly phClr: Rgba | null; };themedLinefunctionA style line with anlnReffollowed into the theme, and the colourphClrtakes in it.function themedLine(line: Themeable<Line>, theme: Theme, colors: ColorContext): { readonly line: Line | null; readonly phClr: Rgba | null; };
src/resolve/typeface.ts
ScriptSlottypeThe four slots aCT_TextCharacterPropertiescan name.type ScriptSlot = 'latin' | 'ea' | 'cs' | 'sym';
resolveTypefacefunctionThe typeface a slot asks for, with any theme reference followed.function resolveTypeface(typeface: string, scheme: FontScheme): string | undefined;
resolveTypefaceOffunctionThe same, for a wholeCT_TextFont.function resolveTypefaceOf(font: Typeface, scheme: FontScheme): string | undefined;
requestedTypefacesfunctionEvery distinct typeface a set of runs asks for, theme references followed.function requestedTypefaces(fonts: Iterable<Typeface | undefined>, scheme: FontScheme): readonly string[];
Errors
Throws ModelError, whose code is one of:
- MODEL_PART_MISSING
- MODEL_PART_KIND
- MODEL_NO_PRESENTATION
- MODEL_NO_PARENT
- MODEL_NO_THEME
- MODEL_CLRMAP_INCOMPLETE
- MODEL_CLRMAP_SLOT
- MODEL_PLACEHOLDER_IDX
- MODEL_XFRM_NUMBER
- MODEL_GEOMETRY
- MODEL_STYLE_IDX
- MODEL_FONT_COLLECTION
- MODEL_NO_STYLE_MATRIX
- MODEL_STYLE_LIST_EMPTY
- MODEL_SHEET_CYCLE
- MODEL_FOREIGN_SHEET
- MODEL_TEXT_ATTR
- MODEL_TEXT_FIELD
- MODEL_TEXT_LEVEL
- MODEL_TEXT_BULLET
- MODEL_TEXT_TYPEFACE
- MODEL_TABLE_ATTR
- MODEL_TABLE_STYLE
- MODEL_TABLE_POSITION
- BLIP_NO_EMBED
- BLIP_DUOTONE
- BLIP_CLR_CHANGE
- BLIP_TILE_ALIGN
- BLIP_TILE_FLIP
Try it live
Reading the deck…