Repository navigation
v4.0.0
[4.0.0] - 2026-09-21
405 commits and 280 changelog entries since 3.7.0, which is too much to paste here. The full
section is linked at the bottom; this is what a reader upgrading needs to know.
The theme of the release is that the library stopped answering quietly wrong. A NaN option was
falsy, so it was dropped or replaced by a default without a word; a 0 extent meant one thing to
addShape and another to addChart; a coordinate past the DrawingML range was written into the
part as scientific notation. All three now warn or throw, which is the rule
docs/contributing/development.md states under "Warn or throw?" and which the option surface now
actually follows. The second theme is the read model: a colour reaching it arrives as one
ColorRef wherever it is read, the text, table and diagram proxies carry the context they were
read in, and Part.bytes is renamed Part.originalBytes because the old name hid the fact that
every copy and import in the library was reading the bytes a part was loaded with and dropping
the session's edits.
Nine entries are breaking, and each carries its migration in the changelog.
Breaking changes
Part.bytesis renamedPart.originalBytes. To read what a part holds now, call
part.serialize(). KeeporiginalBytesonly where you mean the bytes as loaded.- Every read value that carries a colour carries one
ColorRef, undercolorRef. - The read model's text, table and diagram proxies take the context they are read in.
PptxSlideElement.idis typednumber. It wasstring | number.- A
NaNoption is refused, an infinite length clamps, and a coordinate outside the DrawingML
range throws.NaNthrowscoord/non-finiteorpercent/non-finite; the range bounds are
exported asMIN_COORDINATE_EMUandMAX_COORDINATE_EMU. - A zero extent is kept on every object and reported, and a
NaNone is refused.w: 0is
now a stated extent that warnsframe/zero-extent, not a silent default. chartColorsOpacity: 0paints a fully transparent series, andNaNthrows. Leave the
option out for an opaque series.- A hyperlink is validated the same way wherever it is authored. Give each link one of
url,
slideoraction. - Chart axis, error-bar and legend-layout options are checked before they reach the writer.
Removed surface, all of it either dead or superseded: masterSlide, CONNECTOR_PRESETS,
ChartPropsBase.axisPos, ChartOpts's OptsChartGridLine base, the five series-axis unit
options, the three *AxisLineShow defaults, image on ShapeLineProps, TableCellProps.autoPageLineWeight,
TableToSlidesProps's colW / autoPage / autoPageHeaderRows, PresLayout._sizeW / ._sizeH,
TableCell._tableCells and SlideMasterChartProps.opts.
Highlights
createPresentationcomposes a deck from the construct families it needs, so a program that
writes text boxes no longer links the chart, table and diagram emitters.- A measured comparison with pptxgenjs, with a gate that fails the build when the published
page drifts from the snapshot it was rendered from. pptxToScriptkeeps far more of what it reads: a shape's click hyperlink, a picture's
border, all six Table Style Options, a pattern fill's theme tokens, a solid background's theme
token, and the freeform a picture is clipped to.- The chart read model reads scatter, bubble and multi-level data, and the labels a series
declares. Presentation.appPropertiesreadsdocProps/app.xml, including thecompanythe write API
has always been able to set.StrokePropsgives a stroke one vocabulary across every surface that draws one.- Three measured speedups, none of which moves a byte: six memoized read-model answers, the
table auto-pager's covered-column count, and package assembly decoding a shared media part once.
Full changelog: https://github.com/shbernal/ts-pptx/blob/v4.0.0/CHANGELOG.md