Skip to content

v4.0.0

Choose a tag to compare

@shbernal shbernal released this 21 Sep 07:41
· 324 commits to main since this release

[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.bytes is renamed Part.originalBytes. To read what a part holds now, call
    part.serialize(). Keep originalBytes only where you mean the bytes as loaded.
  • Every read value that carries a colour carries one ColorRef, under colorRef.
  • The read model's text, table and diagram proxies take the context they are read in.
  • PptxSlideElement.id is typed number. It was string | number.
  • A NaN option is refused, an infinite length clamps, and a coordinate outside the DrawingML
    range throws.
    NaN throws coord/non-finite or percent/non-finite; the range bounds are
    exported as MIN_COORDINATE_EMU and MAX_COORDINATE_EMU.
  • A zero extent is kept on every object and reported, and a NaN one is refused. w: 0 is
    now a stated extent that warns frame/zero-extent, not a silent default.
  • chartColorsOpacity: 0 paints a fully transparent series, and NaN throws. 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,
    slide or action.
  • 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

  • createPresentation composes 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.
  • pptxToScript keeps 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.appProperties reads docProps/app.xml, including the company the write API
    has always been able to set.
  • StrokeProps gives 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