@office-kit/pptx 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,19 +1,121 @@
1
1
  # @office-kit/pptx
2
2
 
3
+ ## 0.24.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c8512fe: The emphasis effects' own Effect Options:
8
+
9
+ - **Spin** takes `spinDirection` (`'clockwise'` / `'counterclockwise'`) and `spinDegrees` (90, 180, 360, 720 or any positive angle); **Grow/Shrink** takes `scaleDirection` (`'both'` / `'horizontal'` / `'vertical'`) and `scalePercent`; **Transparency** takes `transparencyPercent`; and Fill, Font, Line, Brush and Object Color, Color Pulse and Grow With Color take `color` — a theme slot or `#RRGGBB`, optionally with colour transforms (`AnimationColor`). `setShapeAnimation` and `updateSlideAnimation` write them, and `getSlideAnimations` reads them back on `SlideAnimationStep`.
10
+ - A spin through any angle, either way, is now read as `spin` with its `spinDegrees` and `spinDirection`. Before, only a full clockwise turn was named. A scale that stretches the two axes by different amounts, or a colour effect with two different colours, is still listed with `effect: null`.
11
+ - **Changed:** `updateSlideAnimation` with a new `effect` now gives it that preset's default duration, as picking a preset from the reference desktop app's gallery does. Before, it kept the duration the old effect had. Pass `durationMs` in the same patch to keep a length of your own. Changing only an option or the text build still keeps the duration.
12
+
13
+ - 4410413: All 95 animation presets of the reference desktop app, written exactly as it writes them, and the Sequence (text build) option:
14
+
15
+ - **Every gallery preset.** `setShapeAnimation`, `updateSlideAnimation` and `getSlideAnimations` cover the 35 entrance, 24 emphasis and 36 exit presets in the galleries of the reference desktop app (Mac, 16). Each writes the preset id, subtype, behaviours, default duration and build entry the reference desktop app writes for the same gallery item; a test compares every one against XML saved by the reference desktop app. New `AnimationEffect` tokens include `expandIn`, `swivelIn`, `basicZoomIn`, `centerRevolveIn`, `floatIn`, `growTurnIn`, `riseUpIn`, `spinnerIn`, `stretchIn`, `boomerangIn`, `bounceIn`, `creditsIn`, `curveUpIn`, `dropIn`, `flipIn`, `floatingIn`, `pinwheelIn`, `spiralIn`, `basicSwivelIn` and `whipIn`; the exits `contractOut`, `collapseOut`, `floatOut`, `shrinkTurnOut`, `sinkDownOut`, `stretchyOut`, `curveDownOut` and the counterparts of the entrances; and the emphasis effects `fillColor`, `fontColor`, `growShrink`, `lineColor`, `transparency`, `boldFlash`, `brushColor`, `complementaryColor`, `complementaryColor2`, `contrastingColor`, `darken`, `desaturate`, `lighten`, `objectColor`, `pulse`, `underline`, `colorPulse`, `growWithColor`, `shimmer`, `teeter`, `blink`, `boldReveal` and `wave`. An exhaustive `switch` over `AnimationEffect` needs the new cases.
16
+ - **Breaking: `build` replaces `byParagraph`.** `setShapeAnimation` and `updateSlideAnimation` take `build: 'asOneObject' | 'allAtOnce' | 'byParagraph'` (the reference desktop app's Effect Options ▸ Sequence) instead of `byParagraph: boolean`, and `SlideAnimationStep.build` (`AnimationTextBuild | 'custom'`) replaces `buildByParagraph`. Replace `byParagraph: true` with `build: 'byParagraph'`. `'allAtOnce'` is new: it gives every paragraph its own effect, all starting together. Fill Color and Line Color take no build and refuse one.
17
+ - **Breaking: `zoomIn` / `zoomOut` are now the reference desktop app's Zoom** (preset 53, a fade with a zoom). The plain scale they wrote before is the reference desktop app's Basic Zoom, now `basicZoomIn` / `basicZoomOut`.
18
+ - **Changed output to match the reference desktop app.** `fadeIn` / `fadeOut` write the reference desktop app's fade filter instead of an opacity animation; `spin` defaults to 2 s; exit behaviours carry no `fill`; a shape with no fill and no line writes no `animBg`. `durationMs` now rescales every behaviour of a multi-behaviour preset together, as the reference desktop app's Duration box does; Transparency and Bold Reveal hold until the end of the slide and refuse a duration.
19
+ - **Editor.** Every tile of the Entrance and Emphasis galleries and every Exit Effects item is enabled, in the reference desktop app's order and with its English and Japanese names. Each writes the preset's own default duration. Effect Options ▸ Sequence offers As One Object, All at Once and By Paragraph, and the animation pane lists every preset and has a Sequence choice. The slide show and Preview play an approximation of the new presets (a pose from scale, rotation, translation and opacity, or a colour filter for the emphasis colour effects).
20
+
21
+ - d8e455d: The reference desktop app's 74 built-in table styles are now fully supported.
22
+
23
+ - `setTableStyleId` accepts a built-in style's English name as well as a GUID (`setTableStyleId(table, 'Light Style 1 - Accent 2')`). Applying a built-in style writes the reference desktop app's definition of it into `ppt/tableStyles.xml` (creating the part when a deck has none), as the reference desktop app does, so Keynote, Google Slides and LibreOffice draw the same table. A deck's own definition of a GUID is kept. `addSlideTable` likewise writes the definition of its default style.
24
+ - New `BUILTIN_TABLE_STYLES` lists every built-in style (`id`, `name`, gallery `category`) in the order of the reference desktop app's Table Styles gallery.
25
+ - `getTableCellAppearanceEffective` now resolves every built-in style, not only Medium Style 2 - Accent 1 and No Style, Table Grid, and reports `fillOpacity` for translucent fills. New `getTableBackgroundEffective` resolves the table background (`a:tblPr` fill, else the style's `a:tblBg`).
26
+ - The preview draws all table style parts for built-in and custom styles, including translucent bands and the Themed Styles' background.
27
+ - The editor's Table Design ▸ Table Styles gallery offers all built-in styles, grouped as in the reference desktop app (Best Match for Document, Light, Medium, Dark), with swatches drawn by the preview renderer that follow the Table Style Options check boxes, the reference desktop app's English and Japanese names, and Clear Table.
28
+
29
+ - 550b55c: Gradient lines, sketched lines and more text paints:
30
+
31
+ - **Gradient lines.** `setShapeStroke(shape, { fill: { kind: 'gradient', ...gradient } })` writes `<a:ln><a:gradFill>` with the same gradient options as `setShapeGradientFill`, and a text outline takes the same `fill` (`setShapeTextFormat(shape, { outline: { fill } })`). `getShapeStrokeGradient(shape, pres?)` reads it back; `getShapeStroke` / `getShapeStrokeEffective` now report `{ kind: 'gradient' }` for such lines (previously `inherit`), so a `switch` over `ShapeStroke['kind']` needs a `gradient` case.
32
+ - **Sketched lines.** `setShapeStrokeSketch(shape, 'curved' | 'freehand' | 'scribble' | null)` / `getShapeStrokeSketch(shape)` write and read the reference desktop app's Sketched style (`ask:lineSketchStyleProps`). Other `<a:ln>` extensions are kept, and a sketch the reference desktop app saved (which replaces the geometry with the hand-drawn path) gets its original geometry back when the sketch is changed or removed.
33
+ - **Text fills.** `TextFormat.textFill` accepts `{ kind: 'none' }` (`<a:noFill/>`) and `{ kind: 'image', bytes }` (a PNG, JPEG, GIF, BMP, TIFF or WebP stretched over the text, as the reference desktop app writes it), on shapes, table cells and notes.
34
+ - **Keep text flat.** `setShapeTextFlat(shape, flat)` / `getShapeTextFlat(shape)` write `<a:bodyPr><a:flatTx/>`.
35
+ - **Preview** strokes gradient outlines on shapes, connectors and text, paints no-fill and picture-filled text, and draws a hand-drawn approximation of sketched outlines.
36
+ - **Editor**: Gradient line in Line and Text Outline (with the gradient type, direction, angle and stop controls of Gradient fill), the Sketched style menu (None, Curved, Freehand, Scribble), No fill and Picture or texture fill for text, and Keep text flat are now enabled. Text Effects ▸ Soft Edges stays disabled, as in the reference desktop app. The Text Fill gradient and pattern options no longer fail to apply.
37
+
38
+ - afe80eb: Slide, notes and handout masters can now be edited:
39
+
40
+ - Slide masters: `addSlideMaster`, `removeSlideMaster`, `getSlideMasterLayouts`, `getSlideMasterPlaceholders`, `getSlideMasterName` / `setSlideMasterName`, `isSlideMasterPreserved` / `setSlideMasterPreserved` and `setSlideMasterPlaceholderIncluded`. A new master gets the reference desktop app's default structure: eleven default layouts and its own copy of the theme.
41
+ - Layouts: `addSlideLayout`, `removeSlideLayout`, `addSlideLayoutPlaceholder` (content, text, picture, chart, table, SmartArt, media and online image, plus vertical content and text), `setSlideLayoutTitleIncluded`, `setSlideLayoutFootersIncluded` and `setSlideLayoutBackgroundGraphicsHidden`.
42
+ - Removing a master or layout that slides still use throws, as does removing the last one.
43
+ - Notes and handout masters: `getNotesMasterPlaceholders` / `setNotesMasterPlaceholderIncluded`, `getHandoutMasterPlaceholders` / `setHandoutMasterPlaceholderIncluded`, `getNotesPageSize` / `setNotesPageOrientation` and `getHandoutSlidesPerPage` / `setHandoutSlidesPerPage`. If the deck has no such master, the first edit creates the reference desktop app's default one.
44
+ - `@office-kit/pptx-preview` adds `renderSlideLayoutToSvg`, which draws a layout's or master's background and decorative shapes without its placeholders.
45
+ - In the editor, the Slide Master, Handout Master and Notes Master tabs no longer have disabled commands:
46
+ - Insert Slide Master, Insert Layout, Delete, Rename, Preserve, Master Layout and Insert Placeholder all work, as do the Title, Footers and Hide Background Graphics checkboxes.
47
+ - Orientation, the placeholder checkboxes and Slides Per Page also work.
48
+ - The master views draw the deck's decorative shapes and its real placeholder positions.
49
+
50
+ - 1d447f8: Add `getParagraphElementLanguages(target, paragraphIndex)`. It reads the `lang` of each run, field and line break in a shape or table-cell paragraph, in `getShapeParagraphElements` order.
51
+ - acb95fc: Picture Format: Compress Pictures, Reset Picture & Size and the Artistic Effects gallery.
52
+
53
+ - New `getShapeImageArtisticEffect` reads the Artistic Effect the reference desktop app applied to a picture or image fill (`a14:imgProps`, e.g. `'pencilSketch'`), or `null`. The embedded picture is already the effect's result, so the preview keeps drawing it as is; the effect, its JPEG XR original and the relationship to it survive edits, duplication and saving.
54
+ - Fix: setting a picture's transparency, brightness, contrast or recolor wrote the effect after the picture's `a:extLst`, which is schema-invalid; it now goes before it.
55
+ - The editor's Compress Pictures (Picture Format and File ▸ Compress Pictures...) offers the reference desktop app's Picture Quality choices (High Fidelity, HD 330, Print 220, On-screen 150, Email 96 ppi, Use Original Quality), Delete cropped areas of pictures and Apply to. It downsamples PNG and JPEG pictures in the browser to the chosen resolution of their frame and removes cropped-away pixels, as one undo step.
56
+ - Reset Picture ▸ Reset Picture & Size now works: it also removes the crop and restores the picture's natural size at its own resolution.
57
+ - Artistic Effects shows the reference desktop app's gallery (English and Japanese names) with the picture's current effect checked. Applying an effect stays unavailable: the reference desktop app stores its own rendering plus a JPEG XR original, which the editor cannot produce.
58
+
59
+ - 21d59f7: Picture Styles, and Compress Pictures that labels pictures the way the reference desktop app does.
60
+
61
+ - New `setShapePictureStyle(picture, 'Metal Oval')` applies one of the reference desktop app's 28 built-in picture styles. It writes exactly the `p:spPr` markup the reference desktop app (Mac, 16.113) saves for that style (geometry, fill, border, effects and 3-D, with literal colors) and keeps the picture, its crop and its position. `getShapePictureStyle` returns the style a picture carries exactly, or `null`. New `BUILTIN_PICTURE_STYLES` lists the style names in the order of the reference desktop app's gallery.
62
+ - New `setShapeImageCompressionState` / `getShapeImageCompressionState` write and read the picture's `a:blip/@cstate` (`'print'`, `'screen'`, `'email'`, …) together with the `a14:useLocalDpi` extension the reference desktop app writes beside it.
63
+ - Preview: pictures now draw their effects (outer and inner shadow, glow, soft edge, reflection), their own fill and an approximation of their 3-D: the camera rotation as a flat projection and a top bevel as edge lighting.
64
+ - Fix (preview): a reflection faded the wrong way, strongest at its far edge, and ignored its end position; it now starts at the shape's edge and fades out by `endPos`. A soft edge blurred the whole shape; it now only feathers the outline.
65
+ - The editor's Picture Format ▸ Picture Styles gallery works: the 28 styles in the reference desktop app's order, drawn by the preview renderer, with the reference desktop app's English and Japanese names as tooltips and the applied style checked.
66
+ - The editor's Compress Pictures writes `cstate` for Print, On-screen and Email, as the reference desktop app does, and only replaces a picture's pixels when cropped areas are removed or the resampled picture is smaller. Picture Quality now opens the reference desktop app's menu: Compress Pictures... and Upscale Picture (unavailable: it uses the vendor's cloud AI service).
67
+
68
+ - 2912bdc: Shapes can now carry every effect the reference desktop app's Format Shape pane edits, one at a time:
69
+
70
+ - New `setShapeInnerShadow`, `setShapeReflection` and `setShapeSoftEdge`. `setShapeShadow` and `setShapeGlow` also accept `null`, which removes only that effect (other effects stay; a shape whose style references a theme effect keeps an empty effect list so the theme effect does not come back).
71
+ - `ShadowOptions` gains `scaleX`, `scaleY`, `skewX` and `skewY` (`sx`, `sy`, `kx`, `ky`), used by the reference desktop app's shadow Size field and its perspective shadows. Shape and run shadows read them back.
72
+ - New `setShape3D` / `getShape3D` write and read a shape's own `<a:scene3d>` and `<a:sp3d>` (bevels, depth, contour, material, lighting, camera rotation, perspective, distance from ground). The shared 3-D vocabulary (`Text3D`, also exported as `Shape3D`) gains `bevelBottom`, `extrusionColor`, `contourWidthEmu`, `distanceFromGroundEmu`, `scene.cameraRotation` and `scene.fieldOfViewDeg`. Because these are now modelled, `setShapeText3D` replaces them like its other fields: a field left out is removed rather than kept from the deck, and `getShapeText3D` returns them.
73
+
74
+ - ec775df: `TextFormat.bold` and `TextFormat.spc` accept `null`, which removes the `b` / `spc` attribute so the run inherits its weight and character spacing again. `false` and `0` still write `b="0"` / `spc="0"`, which override an inherited bold or spacing.
75
+
76
+ The editor's Text Art Quick Styles now remove bold and character spacing that a preset does not set, as the reference desktop app does, instead of writing `b="0"` and `spc="0"`. Text whose list style or placeholder makes it bold or spaced keeps that look after applying such a preset.
77
+
78
+ - 24a6ae0: The 2010-and-later transitions and the filter animations of the reference desktop app:
79
+
80
+ - **Transitions.** `setSlideTransition` writes the 2010-and-later transition effects — `vortex`, `switch`, `flip`, `ripple`, `honeycomb`, `prism`, `doors`, `window`, `ferris`, `gallery`, `conveyor`, `pan`, `glitter`, `warp`, `flythrough`, `flash`, `shred`, `reveal` and `wheelReverse` — the twelve `prstTrans` presets (`{ effect: 'prstTrans', preset: 'curtains' }`, with `invertX` / `invertY`) and Morph (`{ effect: 'morph', morphOption: 'byObject' | 'byWord' | 'byChar' }`). They are written the way the reference desktop app writes them, inside `mc:AlternateContent` with a `<p:fade/>` fallback for readers that do not know them. New options: `pattern` (glitter, shred), `isContent`, `isInverted`, `hasBounce` and the directions each effect takes. `getSlideTransition` reads all of them back; an extension effect the library does not know is reported as `prefix:local` (for example `p99:sparkle`) and kept on the slide. `TransitionEffect` gained these tokens, so an exhaustive `switch` over it needs the new cases.
81
+ - **Animations.** `setShapeAnimation` writes the reference desktop app's filter entrance and exit effects with the preset ids, subtypes, filters and default durations the reference desktop app writes: `wipeIn` / `wipeOut`, `peekIn` / `peekOut`, `splitIn` / `splitOut`, `blindsIn` / `blindsOut`, `checkerboardIn` / `checkerboardOut`, `randomBarsIn` / `randomBarsOut`, `shapeIn` / `shapeOut`, `stripsIn` / `stripsOut`, `wheelIn` / `wheelOut`, `dissolveIn` / `dissolveOut` and `wedgeIn` / `wedgeOut`. New options `orientation`, `inOut`, `shape` and `spokes` (and `direction` for wipe, peek and strips) are accepted by `setShapeAnimation` and `updateSlideAnimation` and reported by `getSlideAnimations`. `flyIn` / `flyOut` take the four diagonal directions (`'topLeft'`, `'topRight'`, `'bottomLeft'`, `'bottomRight'`). `AnimationEffect` and `AnimationDirection` gained these tokens, so an exhaustive `switch` over them needs the new cases. An option given to an effect that does not take it throws, as `direction` always did. Without `durationMs`, shape, wedge and wheel run 2 s (the reference desktop app's default); everything else keeps 500 ms.
82
+ - **Editor.** All 49 transitions and every Effect Options item are enabled, each tile writing the reference desktop app's default option and duration; the slide show plays an approximation of the 2010+ effects. The Entrance gallery enables Blinds, Checkerboard, Dissolve In, Peek In, Random Bars, Shape, Split, Strips, Wedge, Wheel and Wipe; Exit Effects lists the reference desktop app's exit gallery with their counterparts enabled; Effect Options offers each effect's directions, shapes and spokes, including Fly's diagonals. Preview plays the filter effects as an animated clip. All at Once and the remaining motion and emphasis presets stay disabled with a reason.
83
+
84
+ ### Patch Changes
85
+
86
+ - 0d26527: Colors with a large `satMod` (or `satOff`) now resolve to the color the reference desktop app paints. `resolveDrawingColor` capped saturation at 100%, as ECMA-376 §20.1.2.3.27 describes, but the reference desktop app does not cap it. Because of that cap, the theme gradients that use `satMod` 300–350% came out too light and too gray in the preview. The Themed Style table backgrounds and the gradient fills of the built-in 2007-era themes are the visible cases: an orange accent was off by up to 70 levels per channel. They now match the reference desktop app's own exports within 2 levels.
87
+
88
+ `resolveDrawingColor` now also applies the `hue`, `sat`, `lum`, `red`/`green`/`blue` (with their `Mod`/`Off` forms), `gamma` and `invGamma` transforms, which it ignored before.
89
+
90
+ - 5e6bbc5: Built-in theme names are now neutral.
91
+
92
+ - `createPresentation()` writes its theme as "Default Theme", with color, font and format schemes named "Default". Decks created earlier keep the names they were saved with.
93
+ - The editor's Design tab names the first three themes Standard Theme, Classic Theme and Legacy Theme (標準テーマ, クラシック テーマ, レガシー テーマ), and the matching color sets and font pairs Standard, Classic and Legacy (標準, クラシック, レガシー). Picking one writes the new name into the deck. When an opened deck's color scheme uses the name another presentation app gives one of these sets, Theme Colors shows the editor's name for it.
94
+
95
+ - 3f4aefe: The READMEs and npm package descriptions describe compatibility in terms of presentation apps in general instead of naming a third-party product. The root README gains a Trademarks section. No code behaviour changes.
96
+ - 9d0754c: API documentation (the TSDoc shipped in the type declarations and in the editor's tool descriptions) no longer uses third-party product names. Behaviour that was checked against a specific desktop presentation app is now described as "the reference desktop app". The `@office-kit/pptx-dsl` package description and the `@office-kit/pptx-preview` npm keywords were reworded the same way. No API or output changes.
97
+ - af5b2b4: The chart API documentation (the TSDoc shipped in the type declarations and in the editor's tool descriptions) now says "spreadsheet" number formats and date system instead of naming a spreadsheet product. No API or output changes. The embedded chart workbook keeps its part name, `/ppt/embeddings/Microsoft_Excel_Worksheet{N}.xlsx`.
98
+ - 197b737: Transitions are saved the way the reference desktop app (Mac) saves them:
99
+
100
+ - **`setSlideTransition` with `durationMs`.** `spd` is now the fastest speed at least as long as the duration (≤ 0.5 s fast, ≤ 0.75 s medium, otherwise slow). `fast` is left out because it is the schema default. A duration equal to its speed's own (500, 750 or 1000 ms) is written as that speed alone, with no `p14:dur` and no `mc:AlternateContent` unless the effect needs one. It reads back as `speed` without `durationMs`. Any other duration is written as before.
101
+ - **Editor.** Each Transitions gallery tile now writes the element, attributes and duration the reference desktop app (Mac, 16) saves for it, and the ribbon Duration shows the reference desktop app's value. Twenty-three durations changed, for example Reveal 3.40, Curtains 6.00, Honeycomb 4.40, Shape 0.80 and Zoom 0.90. Default directions the reference desktop app does not write are no longer written, for example on Split, Reveal, Ripple, Shred, Cube and Fly Through, and Wind, Airplane and Origami no longer write `invX`. Ten Japanese gallery names now match the reference desktop app, for example 垂れ幕, 破砕, ハチの巣, 細分, 扉 and 窓.
102
+ - **Durations of transitions without `spd`.** The ribbon Duration, the Slide transition dialog's speed and the slide-show preview now use the schema default (fast, 0.5 s) for a transition without `spd`. They used medium (0.75 s) before.
103
+ - **Effect Options.** Choosing an option keeps a duration that is stored only as a speed. Before, the transition fell back to fast.
104
+
3
105
  ## 0.23.0
4
106
 
5
107
  ### Minor Changes
6
108
 
7
- - e860ae8: Preset shapes are now drawn from ECMA-376's own preset definitions instead of hand-written approximations. The preview, the editor canvas and its Shapes gallery icons showed many presets wrongly — hearts, lightning bolts, suns, moons, clouds, brackets and braces, bent and curved arrows, the equation shapes, stars with 7 to 32 points — and now match PowerPoint, including the lit and shaded faces of cubes, cans and curved arrows, adjust handles on every preset, and elliptical arcs in custom geometry (whose `arcTo` angles were read as parametric instead of visual angles). Text in a preset now wraps inside the rectangle the definition gives it, such as an ellipse's inscribed rectangle, as PowerPoint does.
109
+ - e860ae8: Preset shapes are now drawn from ECMA-376's own preset definitions instead of hand-written approximations. The preview, the editor canvas and its Shapes gallery icons showed many presets wrongly — hearts, lightning bolts, suns, moons, clouds, brackets and braces, bent and curved arrows, the equation shapes, stars with 7 to 32 points — and now match the reference desktop app, including the lit and shaded faces of cubes, cans and curved arrows, adjust handles on every preset, and elliptical arcs in custom geometry (whose `arcTo` angles were read as parametric instead of visual angles). Text in a preset now wraps inside the rectangle the definition gives it, such as an ellipse's inscribed rectangle, as the reference desktop app does.
8
110
 
9
111
  - `@office-kit/pptx`: new `getPresetGeometry(preset, size, adjustValues?)` evaluates any preset's paths and text rectangle in the same form as `getShapeCustomGeometry`.
10
112
  - `@office-kit/pptx-preview` (breaking): `shapeCustomTextRect(custom, extent)` is replaced by `shapeTextRect(shape)`, which reads custom and preset geometry alike, and `resolveTextBodyRect` now takes `(bounds, margins, region)` with the region from `shapeTextRect`.
11
113
 
12
- - 089140c: The preview now draws text bevels (`<a:bodyPr>` `<a:sp3d><a:bevelT>`, as PowerPoint's Soft Bevel and Sharp Bevel WordArt write them): beveled glyphs are shaded with a light and dark edge sized from the bevel's width and height and lit from the light rig's direction, in shape text, table cells and the editor while text is being edited. The 12 bevel presets get different edge profiles and shiny materials add a highlight; this is a 2-D approximation, so the camera, extrusion and contour are not drawn. Text without a bevel renders exactly as before. New `getTableCellText3D` reads a table cell's text 3-D, like `getShapeText3D` does for shapes.
114
+ - 089140c: The preview now draws text bevels (`<a:bodyPr>` `<a:sp3d><a:bevelT>`, as the reference desktop app's Soft Bevel and Sharp Bevel text styles write them): beveled glyphs are shaded with a light and dark edge sized from the bevel's width and height and lit from the light rig's direction, in shape text, table cells and the editor while text is being edited. The 12 bevel presets get different edge profiles and shiny materials add a highlight; this is a 2-D approximation, so the camera, extrusion and contour are not drawn. Text without a bevel renders exactly as before. New `getTableCellText3D` reads a table cell's text 3-D, like `getShapeText3D` does for shapes.
13
115
 
14
116
  ### Patch Changes
15
117
 
16
- - 8db2360: `setShapeText`, `setTableCellText` and `setSlideNotes` with a `range` no longer leave a separate `<a:r>` for every insertion: text inserted next to a run with the same formatting extends that run, and deleting the text between two halves of a run joins them again, as PowerPoint does. Typing in the editor previously saved one run per keystroke.
118
+ - 8db2360: `setShapeText`, `setTableCellText` and `setSlideNotes` with a `range` no longer leave a separate `<a:r>` for every insertion: text inserted next to a run with the same formatting extends that run, and deleting the text between two halves of a run joins them again, as the reference desktop app does. Typing in the editor previously saved one run per keystroke.
17
119
 
18
120
  ## 0.22.0
19
121
 
@@ -50,9 +152,9 @@
50
152
 
51
153
  Fixes: an exit fade hid its shape the moment it started instead of fading it
52
154
  out. The `<p:set>` that takes the shape off the slide now trails the motion the
53
- way PowerPoint writes it, and moves when the effect's duration changes.
155
+ way the reference desktop app writes it, and moves when the effect's duration changes.
54
156
 
55
- - e18d19d: `setShapeAnimation` accepts `byParagraph`, which reveals a shape's text one paragraph at a time instead of animating the shape as a whole — PowerPoint's and Google Slides' "By paragraph". Each paragraph gets its own effect with the `start` you asked for, so the default advances a paragraph per click, and they share the one `<p:bldP build="p">` that makes PowerPoint treat them as a single build. `getSlideAnimations` reports each paragraph as its own step, targeting a paragraph range. A shape with no text is refused rather than silently animated as a whole, and a call that cannot be completed leaves the slide's existing timing exactly as it was.
157
+ - e18d19d: `setShapeAnimation` accepts `byParagraph`, which reveals a shape's text one paragraph at a time instead of animating the shape as a whole — the reference desktop app's and Google Slides' "By paragraph". Each paragraph gets its own effect with the `start` you asked for, so the default advances a paragraph per click, and they share the one `<p:bldP build="p">` that makes the reference desktop app treat them as a single build. `getSlideAnimations` reports each paragraph as its own step, targeting a paragraph range. A shape with no text is refused rather than silently animated as a whole, and a call that cannot be completed leaves the slide's existing timing exactly as it was.
56
158
  - e18d19d: `setShapeAnimation` accepts `start` and `delayMs`. `'withPrevious'` runs an effect alongside the one before it and `'afterPrevious'` once that one has finished, both off the click that started their predecessor, so several shapes can animate from a single click. As a slide's first effect neither has a predecessor to follow, so both run as the slide appears.
57
159
 
58
160
  `'afterPrevious'` needs to know when the effect before it ends. On a slide whose timing states that in a form this library does not model — an effect that runs indefinitely or states no duration, one that repeats or is rescaled, or one that starts from another node rather than at a fixed offset — the call throws and leaves the slide's timing untouched rather than placing the effect at a guessed moment. `'click'` and `'withPrevious'` need no such measurement and still work there.
@@ -60,8 +162,8 @@
60
162
  Existing calls are unaffected: the defaults still write the click-triggered, zero-delay tree they wrote before, byte for byte.
61
163
 
62
164
  - e18d19d: Apply the active slide's background to the whole presentation with `applySlideBackgroundToAll` or the editor's Apply to All button. Backgrounds move to slide masters and individual slide/layout overrides are cleared, preserving theme colors and image references. The editor supports undoing the whole operation together.
63
- - e18d19d: Add `setSlideMasterBackgroundStyle` to select PowerPoint's twelve theme background styles. The selected slide's master receives the theme fill reference and light or dark text/background mapping, preserving accent colors and existing slide overrides.
64
- - e18d19d: Read and edit PowerPoint’s Rewind After Playing setting for audio and video, preserving it when saving and reopening presentations.
165
+ - e18d19d: Add `setSlideMasterBackgroundStyle` to select the reference desktop app's twelve theme background styles. The selected slide's master receives the theme fill reference and light or dark text/background mapping, preserving accent colors and existing slide overrides.
166
+ - e18d19d: Read and edit the reference desktop app’s Rewind After Playing setting for audio and video, preserving it when saving and reopening presentations.
65
167
  - e18d19d: Preview background images with their stretch offsets, tile scale, alignment, offsets, and alternating reflections, including inherited backgrounds. Expose natural background image dimensions using embedded resolution and fill DPI, so tiling matches the image size instead of stretching it across the slide.
66
168
  - e18d19d: Read and change slide background image placement with `getSlideBackgroundImageFillLayout` and `setSlideBackgroundImageFillLayout`. Stretch offsets and tiled scale, position, alignment, and mirroring preserve the image data. Editing inherited images creates a slide override without changing other slides.
67
169
  - e18d19d: Render background picture cropping for stretched and tiled images, including inherited backgrounds. Add `getSlideBackgroundImageCrop` to read the effective source rectangle without changing the deck.
@@ -89,11 +191,11 @@
89
191
 
90
192
  - e18d19d: Support `TextFormat.underlineColor` for independently colored underlines. Set it to `null` to follow the text color. Preserve the color when reading, editing, copying, and saving text, and expose underline color and Automatic in the editor's Font dialog.
91
193
  - e18d19d: Support reading and changing transparency on image-filled shapes as well as pictures, including preview rendering. Invalid opacity values now leave the existing transparency unchanged.
92
- - e18d19d: Support PowerPoint's Top, Middle and Bottom Centered text anchors through the existing `setShapeTextAnchor` API's `centered` option. Resolve inherited centering through `getShapeBodyPrEffective`, preserve paragraph alignment, and expose all six anchor choices in the editor with preview and text-editing support.
194
+ - e18d19d: Support the reference desktop app's Top, Middle and Bottom Centered text anchors through the existing `setShapeTextAnchor` API's `centered` option. Resolve inherited centering through `getShapeBodyPrEffective`, preserve paragraph alignment, and expose all six anchor choices in the editor with preview and text-editing support.
93
195
 
94
196
  Preview integrations can use `shapeTextAnchorOffset` to position editable text consistently with the rendered text block.
95
197
 
96
- - e18d19d: Text can now carry its own outline, shadow and glow — the WordArt half of a
198
+ - e18d19d: Text can now carry its own outline, shadow and glow — the decorative half of a
97
199
  character format.
98
200
 
99
201
  `TextFormat` gained `outline`, `shadow` and `glow`, so every writer that takes
@@ -116,14 +218,14 @@
116
218
 
117
219
  The existing `setShapeTextFormat` and `setTableCellTextFormat` APIs now accept `{ reset: true }` to restore inherited run appearance before applying a new format, optionally limited to a character range.
118
220
 
119
- - e18d19d: Add comment replies through `addSlideComment({ replyTo })` and `getCommentParent`, preserving PowerPoint p15 threading extensions through save and reload. Removing a comment also removes its descendant replies.
221
+ - e18d19d: Add comment replies through `addSlideComment({ replyTo })` and `getCommentParent`, preserving the reference desktop app's p15 threading extensions through save and reload. Removing a comment also removes its descendant replies.
120
222
 
121
223
  The preview comments dialog supports creating and editing replies in English and Japanese, shows each reply's parent, and deletes threads with undo/redo support.
122
224
 
123
225
  - e18d19d: `setShapeShadow` and `setShapeGlow` no longer erase each other. Each now
124
226
  replaces only the effect of its own kind and leaves the rest of the shape's
125
227
  `<a:effectLst>` in place, written in the order `CT_EffectList` states — so a
126
- shape can carry a shadow and a glow at once, as PowerPoint routinely writes
228
+ shape can carry a shadow and a glow at once, as the reference desktop app routinely writes
127
229
  them. Setting the same effect twice still replaces it, because the schema
128
230
  allows each one only once. `clearShapeEffects` remains the way to empty the
129
231
  list.
@@ -131,7 +233,7 @@
131
233
  `getShapePatternFill` now reports `preset` as the `PatternPreset` union rather
132
234
  than a bare `string`, so what it reads can be handed straight back to
133
235
  `setShapePatternFill`. An unrecognised `prst` in the file reads as `'pct50'`,
134
- which is what PowerPoint paints when the attribute is absent.
236
+ which is what the reference desktop app paints when the attribute is absent.
135
237
 
136
238
  - e18d19d: Concatenate text from multiple shapes with `setShapeParagraphs(target, { sources })`, retaining paragraph formatting and hyperlinks. In Outline View, demote a slide title into the previous slide's body with Tab or the context menu, with Undo support. Slides with additional objects or no destination body placeholder report an error before changing their content.
137
239
  - e18d19d: Copy existing formatted text into a shape with `setShapeParagraphs(shape, { source, range })`. The optional UTF-16 range retains paragraph properties, fields, run formatting and link relationships while keeping the destination text body's settings.
@@ -169,23 +271,23 @@
169
271
 
170
272
  Fix Increase/Decrease Font Size leaving empty paragraphs unchanged when formatting an entire text box or table cell.
171
273
 
172
- - e18d19d: Read and write PowerPoint's Equalize character height setting with `TextFormat.normalizeHeight`, preserving explicit enabled and disabled values through editing and saving.
274
+ - e18d19d: Read and write the reference desktop app's Equalize character height setting with `TextFormat.normalizeHeight`, preserving explicit enabled and disabled values through editing and saving.
173
275
  - e18d19d: Add an optional proportional content fit when changing slide size, with English and Japanese page setup controls. Scale object coordinates, explicit text formatting, table dimensions and outlines, and center the original page on the new canvas. Invalid scaled dimensions leave the presentation unchanged.
174
276
  - e18d19d: Read and update slide show mode, slide range, looping, narration, animation, and timing settings while preserving other presentation properties.
175
- - e18d19d: Preserve gradient stop transparency when reading shapes and expose theme-resolved stop colors. Shape previews now render the brightness and transparency saved by PowerPoint for linear and radial gradient stops.
277
+ - e18d19d: Preserve gradient stop transparency when reading shapes and expose theme-resolved stop colors. Shape previews now render the brightness and transparency saved by the reference desktop app for linear and radial gradient stops.
176
278
  - e18d19d: Allow gradient stops to specify brightness and opacity, and gradients to preserve scaling and rotation settings. Reject invalid stop edits without discarding the shape's existing fill.
177
279
 
178
280
  Edit gradient stop color, position, brightness and transparency in the Format Shape pane, with add/remove controls and Undo support. Drag stops directly, commit each drag as one undoable edit, and cancel an in-progress drag with Escape.
179
281
 
180
- - e18d19d: Expose gradient tile bounds through `GradientFillOptions.tileRect` and gradient readers. Preserve PowerPoint's corner-gradient tile bounds when changing stops or rotation and saving the presentation.
282
+ - e18d19d: Expose gradient tile bounds through `GradientFillOptions.tileRect` and gradient readers. Preserve the reference desktop app's corner-gradient tile bounds when changing stops or rotation and saving the presentation.
181
283
  - e18d19d: Add image-fill placement readers and setters for tile alignment, scale, offsets, mirroring, stretch offsets and rotation with the shape. Placement changes preserve the embedded image, crop and effects. Preview now renders stretch offsets and clips the image to the shape.
182
284
  - e18d19d: Add `isSlideBackgroundGraphicsHidden`, `setSlideBackgroundGraphicsHidden`, and `isSlideLayoutBackgroundGraphicsHidden` to inspect and control inherited decoration without deleting template content. Apply to All also copies the graphics visibility setting to slides and layouts. The preview honors both levels, and the editor's Format Background pane supports changing selected slides with undo and save/reload.
183
285
  - e18d19d: Fix horizontal text overrides on placeholders inheriting vertical text from a layout or master. Explicit `horz` values now stop the inheritance cascade. Behavior change: `setShapeTextDirection(shape, 'horz')` writes an explicit override; use `null` to clear the override and restore inheritance.
184
- - e18d19d: Add `setShapeImageRecolor` for PowerPoint-compatible grayscale, duotone, threshold, and washout image effects.
286
+ - e18d19d: Add `setShapeImageRecolor` for desktop-app-compatible grayscale, duotone, threshold, and washout image effects.
185
287
  - e18d19d: Allow effective run formatting to resolve layout and master inheritance from an original shape while reading a detached editing preview. Show inherited character styles during inline shape editing, including pending text and paragraph changes, without baking those styles into saved text or clipboard data.
186
288
  - e18d19d: Resolve inherited text autofit and columns through `getShapeBodyPrEffective`, and use them consistently in previews and editing controls. Allow `setShapeTextColumns` to author one column explicitly, overriding inherited columns; invalid column settings leave the previous values intact.
187
289
  - e18d19d: Allow effective paragraph properties to retain original placeholder and slide inheritance when reading a detached shape preview. Display paragraph alignment, line spacing, spacing before and after, indentation and text direction during inline editing, with canvas zoom applied to absolute dimensions.
188
- - e18d19d: Add character-level inner shadow formatting to the text API, including PowerPoint OOXML read, write, inheritance, and independent removal.
290
+ - e18d19d: Add character-level inner shadow formatting to the text API, including the reference desktop app's OOXML read, write, inheritance, and independent removal.
189
291
  - e18d19d: Edit a slide layout, not just apply one: `setSlideLayoutName`,
190
292
  `setSlideLayoutBackground`, `clearSlideLayoutBackground` and
191
293
  `setSlideLayoutPlaceholderBounds`.
@@ -203,18 +305,18 @@
203
305
  Design ▸ Layout ribbon group, in English and Japanese.
204
306
 
205
307
  - e18d19d: Resolve line-break formatting with `{ breakIndex }` in getShapeRunFormatEffective and getTableCellRunFormatEffective. Preserve inherited font, size, and emphasis when selecting, editing, or copying line breaks.
206
- - e18d19d: Add PowerPoint link destinations for the last slide viewed and ending the slide show.
207
- - e18d19d: `SlideShowProperties` gains an optional `showMediaControls` (PowerPoint's Show Media Controls, stored as `p14:showMediaCtrls`); `getSlideShowProperties` always reports it. The editor's Slide Show tab adds Rehearse Timings (time each slide while presenting, then keep the times as slide timings), Record, and the Use Timings, Play Narrations and Show Media Controls options; the Microsoft 365-only commands are shown disabled.
308
+ - e18d19d: Add the reference desktop app's link destinations for the last slide viewed and ending the slide show.
309
+ - e18d19d: `SlideShowProperties` gains an optional `showMediaControls` (the reference desktop app's Show Media Controls, stored as `p14:showMediaCtrls`); `getSlideShowProperties` always reports it. The editor's Slide Show tab adds Rehearse Timings (time each slide while presenting, then keep the times as slide timings), Record, and the Use Timings, Play Narrations and Show Media Controls options; the commands that need the vendor's cloud service are shown disabled.
208
310
  - e18d19d: Add read and write support for named bookmarks in embedded media playback.
209
311
  - e18d19d: Say how a clip plays: `getShapeMediaPlayback` and `setShapeMediaPlayback`.
210
312
 
211
313
  A deck could embed a video or a sound but not state anything about playing it,
212
- so every clip waited for a click at PowerPoint's default volume. The new pair
314
+ so every clip waited for a click at the reference desktop app's default volume. The new pair
213
315
  reads and writes autoplay, loop, volume, mute, hide-when-stopped and (video
214
316
  only) full screen, from the clip's media time node. Omitted properties keep
215
317
  their current value.
216
318
 
217
- Trimming a clip is still not supported: PowerPoint stores it in a 2010
319
+ Trimming a clip is still not supported: the reference desktop app stores it in a 2010
218
320
  extension rather than in the core schema.
219
321
 
220
322
  The editor exposes the settings through its properties panel and command
@@ -222,7 +324,7 @@
222
324
 
223
325
  - e18d19d: Read and edit the OOXML `numSld` setting for audio and video playback across slides.
224
326
  - e18d19d: Preserve automatic media start delays through `MediaPlayback.delayMs`. Presentation preview now waits for the saved delay before playing audio or video and cancels pending playback when leaving a slide or starting media manually.
225
- - e18d19d: Comments written by PowerPoint 2021 and Microsoft 365 are now read and edited,
327
+ - e18d19d: Comments written by the reference desktop app (2021 and the subscription edition) are now read and edited,
226
328
  not merely carried along. Those decks keep their comments in a different format
227
329
  from the one ECMA-376 defines ([MS-PPTX] §2.16.1): a thread owns its replies
228
330
  instead of the replies pointing back at a parent, the text is a DrawingML body
@@ -255,12 +357,12 @@
255
357
 
256
358
  The four existing stacking APIs also accept an array of sibling shapes. Selections from different parent containers are rejected before any shape is moved.
257
359
 
258
- - e18d19d: Preserve shadow alignment and rotation when reading and editing PowerPoint text. Shadow formatting now accepts `alignment` and `rotateWithShape`, including native WordArt anchors.
259
- - e18d19d: Add character-level reflection formatting to `TextFormat`, including native PowerPoint read, write, merge, removal, and round-trip support.
360
+ - e18d19d: Preserve shadow alignment and rotation when reading and editing text from the reference desktop app. Shadow formatting now accepts `alignment` and `rotateWithShape`, including native text-art anchors.
361
+ - e18d19d: Add character-level reflection formatting to `TextFormat`, including the reference desktop app's read, write, merge, removal, and round-trip support.
260
362
  - e18d19d: Group sibling shapes and ungroup groups inside an existing group without removing the outer group or changing its transform. Grouping preserves the members' stacking order regardless of selection order. Preview group commands support nested selections with Undo/Redo and reject selections spanning different parents.
261
363
  - e18d19d: Format selected speaker-note text from the Home ribbon, preserving mixed formatting when editing and saving notes. Add APIs to read and update notes character formatting and change letter case.
262
364
  - e18d19d: Read and update paragraph levels across a UTF-16 text selection with `getParagraphLevel` and `setParagraphLevel`. Relative updates preserve differences between levels and keep text, formatting and links intact. Indenting a long outline selection now updates its text body once instead of once per paragraph.
263
- - e18d19d: Persist outline collapse with `getCollapsedOutlineSlides` and `setSlideOutlineCollapsed`, preserving PowerPoint's per-slide view state. Deleting a slide removes its outline reference.
365
+ - e18d19d: Persist outline collapse with `getCollapsedOutlineSlides` and `setSlideOutlineCollapsed`, preserving the reference desktop app's per-slide view state. Deleting a slide removes its outline reference.
264
366
 
265
367
  In the editor, double-click a slide icon in Outline View to collapse or expand its body. The right-click menu also collapses or expands the selected slides or the whole outline. Each change supports Undo and survives saving and reopening.
266
368
 
@@ -280,7 +382,7 @@
280
382
  - e18d19d: Add `setParagraphTabs` to edit custom tab positions, left/center/right/decimal alignment, and automatic tab spacing in text boxes and table cells. Effective paragraph properties now include inherited tab settings. Empty tab lists clear custom stops, while null removes a local override.
281
383
  - e18d19d: Read and update paragraph Asian line breaking, Latin word wrapping, hanging punctuation, and font alignment with `setParagraphTypography`, including inherited settings and removal of local overrides.
282
384
 
283
- Add the Paragraph dialog's Line Breaks and Alignment tab. Apply changes to selected paragraphs or table cells together, preserve mixed values, and support undo and redo. These settings are saved in exported PowerPoint files; preview rendering does not yet reproduce all typography rules.
385
+ Add the Paragraph dialog's Line Breaks and Alignment tab. Apply changes to selected paragraphs or table cells together, preserve mixed values, and support undo and redo. These settings are saved in exported presentation files; preview rendering does not yet reproduce all typography rules.
284
386
 
285
387
  - e18d19d: Choose pattern foreground and background colors from theme and standard palettes. Base theme colors stay linked when switching fill types and after saving.
286
388
 
@@ -302,7 +404,7 @@
302
404
 
303
405
  Add an optional UTF-16 `range` to `setShapeText` and `setTableCellText` to replace an exact selection while retaining unaffected formatting, including when adjacent characters are identical. Invalid boundaries and split surrogate pairs are rejected.
304
406
 
305
- - e18d19d: Add a canonical `setShapeStyle` API for applying native PowerPoint shape style references while preserving shape geometry and text formatting.
407
+ - e18d19d: Add a canonical `setShapeStyle` API for applying native shape style references while preserving shape geometry and text formatting.
306
408
 
307
409
  Allow `setShapeHidden` to update multiple shapes in one call while preserving animation data.
308
410
 
@@ -353,7 +455,7 @@
353
455
  space — restoring it would either tear the shape out of the arrangement it was
354
456
  grouped into, or invent a rectangle the layout never described.
355
457
 
356
- - e18d19d: Add `resetShapeImageColorEffects` for clearing PowerPoint image recolor and brightness/contrast effects while preserving other image effects.
458
+ - e18d19d: Add `resetShapeImageColorEffects` for clearing the reference desktop app's image recolor and brightness/contrast effects while preserving other image effects.
357
459
  - e18d19d: Add resetSlidePlaceholderGeometry to restore top-level placeholder position, size, rotation and flips from the current layout or master while preserving content and formatting. The bilingual development editor exposes it for individual or selected slides with undo/redo.
358
460
  - e18d19d: Add `resetSlidePlaceholderTextFormatting` to restore inherited text, paragraph and text-body formatting on layout-bound placeholders while retaining content, hyperlinks, language and outline levels. Expose the operation in English and Japanese in the preview, with selected-slide support and undo/redo.
359
461
  - e18d19d: Add `resetSlideLayout` to restore missing placeholders, layout geometry and inherited shape/text formatting together while preserving content and image relationships. Expose Reset layout in the English and Japanese preview, with multi-slide selection and a single undo step.
@@ -363,9 +465,9 @@
363
465
  - e18d19d: Allow getShapeRunFormatEffective to resolve fields with a fieldIndex selector. Preserve inherited fonts, sizes, colors, and emphasis for shape fields when displaying, editing, inspecting, and copying their text.
364
466
  - e18d19d: Read and preview theme-referenced shape fills, including solid colors, transparency, and gradient stops, using each shape's slide master theme. Direct shape fills continue to override theme references. The fill opacity reader accepts an optional presentation argument to resolve theme transparency.
365
467
 
366
- Use a shape style's text color and theme font defaults when its existing text formatting does not supply them, so text in PowerPoint's colored shape styles keeps its intended color.
468
+ Use a shape style's text color and theme font defaults when its existing text formatting does not supply them, so text in the reference desktop app's colored shape styles keeps its intended color.
367
469
 
368
- - e18d19d: Add `isShapeLocked` and `setShapeLocked` for PowerPoint-compatible object geometry locks, preserving text editing and unrelated drawing constraints.
470
+ - e18d19d: Add `isShapeLocked` and `setShapeLocked` for desktop-app-compatible object geometry locks, preserving text editing and unrelated drawing constraints.
369
471
 
370
472
  Add individual and all-object locks in the editor Selection Pane. Locked objects cannot be moved, resized, rotated, aligned or grouped; their lock state survives saving and undo/redo.
371
473
 
@@ -378,7 +480,7 @@
378
480
  - e18d19d: Slide numbers, as live fields rather than typed text.
379
481
 
380
482
  `setShapeTextField(shape, type, { text })` writes an `<a:fld>` — the slide's
381
- number, a date, a footer — replacing the shape's text body the way PowerPoint
483
+ number, a date, a footer — replacing the shape's text body the way the reference desktop app
382
484
  writes one, and carrying the replaced text's formatting onto the field.
383
485
  `addSlidePlaceholder(slide, type)` restores a single slot the layout reserves
384
486
  (`sldNum`, `dt`, `ftr`, …), where `addMissingSlidePlaceholders` restores them
@@ -403,17 +505,17 @@ firstSlideNum>`.
403
505
 
404
506
  Keep Home ribbon controls accessible without horizontal scrolling at intermediate window widths.
405
507
 
406
- - e18d19d: Text formats can now carry PowerPoint's theme tints and WordArt bevels.
508
+ - e18d19d: Text formats can now carry the reference desktop app's theme tints and text-art bevels.
407
509
 
408
510
  - `TextFormat.colorTransforms`, and `colorTransforms` on `outline`, `shadow`, `innerShadow` and `glow`, write `<a:lumMod>`, `<a:lumOff>`, `<a:tint>`, ... on the run's colors — the same field gradient stops already take — so "Accent 2, Lighter 60%" stays a theme color instead of a fixed RGB. `getShapeRunFormat` reads them back beside the unresolved color and `toWritableTextFormat` carries them. The shared `ShadowOptions`, `InnerShadowOptions` and `GlowOptions` gain the field, so `setShapeShadow` and `setShapeGlow` accept it too.
409
- - New `setShapeText3D(shape, value | null)` / `getShapeText3D(shape)` write and read the text body's 3-D (`<a:scene3d>` camera and light rig, `<a:sp3d>` top bevel, extrusion height, material and contour color), which is where PowerPoint puts its WordArt bevels. Presets are typed by the schema's enums (`CameraPreset`, `LightRigType`, `LightRigDirection`, `BevelPreset`, `PresetMaterial`).
511
+ - New `setShapeText3D(shape, value | null)` / `getShapeText3D(shape)` write and read the text body's 3-D (`<a:scene3d>` camera and light rig, `<a:sp3d>` top bevel, extrusion height, material and contour color), which is where the reference desktop app puts its text-art bevels. Presets are typed by the schema's enums (`CameraPreset`, `LightRigType`, `LightRigDirection`, `BevelPreset`, `PresetMaterial`).
410
512
  - `setShapeTextAutoFit` now places its element ahead of any `<a:scene3d>` / `<a:sp3d>`, as the schema requires.
411
513
  - `getShapeRunFormat` reports a run effect's scheme color as its token (it returned an empty string without a theme), and a text gradient stop without alpha no longer reads back as `opacity: 1`, which wrote an `<a:alpha val="100000"/>` on the way back.
412
514
 
413
- - e18d19d: Support paragraph-internal line breaks when replacing shape or table-cell text with `newlines: 'break'`. The editor preserves these breaks for Shift+Enter and for Enter in title placeholders, matching Mac PowerPoint.
515
+ - e18d19d: Support paragraph-internal line breaks when replacing shape or table-cell text with `newlines: 'break'`. The editor preserves these breaks for Shift+Enter and for Enter in title placeholders, matching the reference desktop app (Mac).
414
516
  - e18d19d: Add `setShapeTextLanguage(shape, lang)` and `getShapeTextLanguage(shape)` for the proofing language of a shape's text (`lang` on every run and paragraph end). The editor's Review tab gains Check Accessibility, Language, comment Delete/Previous/Next, Show Comments and Hide Ink; commands the library cannot support yet are shown disabled with the reason.
415
517
  - e18d19d: Support gradient and pattern fills on formatted text runs through `textFill`,
416
- including theme color transforms and round-tripping native WordArt fills.
518
+ including theme color transforms and round-tripping native text-art fills.
417
519
  The existing `color` property remains the solid text color shorthand; passing
418
520
  both `color` and `textFill` is rejected.
419
521
  - e18d19d: Add slide-background shape fills through `setShapeSlideBackgroundFill` and the editor's Fill pane, including multiple selection, undo and saved reloads. Fill readers expose the new `background` kind. Preview paints the slide background through these shapes while keeping it aligned through shape and group transforms.
@@ -426,8 +528,8 @@ firstSlideNum>`.
426
528
 
427
529
  Resolve inherited shape and table text colors through the slide color map, including detached editing previews.
428
530
 
429
- - e18d19d: Transitions can now carry a duration and a sound. `setSlideTransition` accepts `durationMs`, written as PowerPoint 2010 writes it (`p14:dur` inside `mc:AlternateContent`, with the nearest `speed` as the fallback), and `getSlideTransition` reads it back, including from decks saved by PowerPoint. New `setSlideTransitionSound` / `getSlideTransitionSound` embed a WAV sound or stop earlier sounds; changing the effect keeps the sound. The editor's Transitions tab gains Preview, Duration and Sound, and the preview plays fast/medium/slow transitions at PowerPoint's 0.5/0.75/1 s.
430
- - e18d19d: Add typed media trim and fade playback controls with PowerPoint OOXML round-trip support.
531
+ - e18d19d: Transitions can now carry a duration and a sound. `setSlideTransition` accepts `durationMs`, written as the reference desktop app (2010) writes it (`p14:dur` inside `mc:AlternateContent`, with the nearest `speed` as the fallback), and `getSlideTransition` reads it back, including from decks saved by the reference desktop app. New `setSlideTransitionSound` / `getSlideTransitionSound` embed a WAV sound or stop earlier sounds; changing the effect keeps the sound. The editor's Transitions tab gains Preview, Duration and Sound, and the preview plays fast/medium/slow transitions at the reference desktop app's 0.5/0.75/1 s.
532
+ - e18d19d: Add typed media trim and fade playback controls with round-trip support for the reference desktop app's OOXML.
431
533
  - e18d19d: Add video formatting reset to the editor ribbon and the `resetShapeVideoFormatting` API. Reset removes color corrections, borders and effects and restores a rectangular shape while preserving the video, poster image, crop and dimensions.
432
534
  - e18d19d: Preserve and edit wheel transition spoke counts, with Japanese and English controls. Play clockwise wheel transitions in presentation mode, including default four spokes and a fade for zero spokes.
433
535
 
@@ -440,7 +542,7 @@ firstSlideNum>`.
440
542
  - e18d19d: Display the borders and transparent cells of the built-in No Style, Table Grid style when a presentation stores only its style ID.
441
543
  - e18d19d: Read percent-form bullet sizes at their intended scale instead of rendering the list marker a thousand times too small.
442
544
  - e18d19d: Add bilingual speaker-note and slide-transition dialogs to the development preview, including automatic advance and applying a transition to all slides in one undo step. Correct speaker-note reads and updates to use the body placeholder without overwriting footers, read soft breaks and field results, and retain automatic-advance settings when no transition effect is selected.
443
- - e18d19d: Fix changing font colors on text with gradient, pattern, or other fills so the previous fill is replaced instead of producing conflicting fills in saved PowerPoint files.
545
+ - e18d19d: Fix changing font colors on text with gradient, pattern, or other fills so the previous fill is replaced instead of producing conflicting fills in saved presentation files.
444
546
  - e18d19d: Fix reading and rendering of DrawingML preset colors such as `red`, including
445
547
  colors used by shape fills and text after a presentation is saved and reopened.
446
548
  - e18d19d: Scale table text with no authored font size when fitting slide content to a new page size. Preserve explicit font-size inheritance and retain scaled defaults for empty cells and saved presentations.
@@ -457,12 +559,12 @@ firstSlideNum>`.
457
559
  - e18d19d: Resolve internal slide link targets by package and part name so preview links retain the correct destination after reading, reordering, and saving a presentation.
458
560
  - e18d19d: Read imported percentage line spacing at the correct scale, including paragraph and inherited list styles. Percent-form spacing such as `150%` no longer collapses the lines together.
459
561
  - e18d19d: Keep event-triggered audio and video from being reported as automatic playback. Remove media timing nodes inside nested playback sequences when their shapes are deleted while preserving unrelated timing content.
460
- - e18d19d: Apply last-column formatting to horizontally merged table cells that reach the right edge, matching PowerPoint even when the cell starts in an earlier column.
461
- - e18d19d: Apply total-row formatting to vertically merged table cells that reach the last row, matching PowerPoint even when the cell starts in an earlier row.
462
- - e18d19d: Convert PowerPoint's native Play in Background timing tree when changing an audio clip between automatic and click playback, preserving the existing timing IDs and media settings.
562
+ - e18d19d: Apply last-column formatting to horizontally merged table cells that reach the right edge, matching the reference desktop app even when the cell starts in an earlier column.
563
+ - e18d19d: Apply total-row formatting to vertically merged table cells that reach the last row, matching the reference desktop app even when the cell starts in an earlier row.
564
+ - e18d19d: Convert the reference desktop app's native Play in Background timing tree when changing an audio clip between automatic and click playback, preserving the existing timing IDs and media settings.
463
565
  - e18d19d: Show and edit playback settings for audio and video nested inside animation timing groups. Preserve enclosing start conditions when changing volume, looping, or video display settings, and account for parent delays when reading and editing simple automatic playback. Reject unsupported start-condition edits before changing the document. Also reject non-finite volume values instead of writing invalid XML.
464
566
  - e18d19d: Fix existing text in shapes and table cells incorrectly adopting the font, size, or emphasis saved for newly inserted text at the end of a paragraph.
465
- - e18d19d: Read imported path-gradient focus rectangles correctly when PowerPoint omits zero insets. Preserve small integer percentage values and percentage-string values when editing and saving gradient fills.
567
+ - e18d19d: Read imported path-gradient focus rectangles correctly when the reference desktop app omits zero insets. Preserve small integer percentage values and percentage-string values when editing and saving gradient fills.
466
568
  - e18d19d: Read image crop offsets correctly when imported presentations store them as percentages. Include selected text and theme fonts in the editor's font picker, including custom font names.
467
569
  - e18d19d: Preserve charts, embedded workbooks, speaker notes, media, and relationship-linked extension parts when importing slides. Retain shared dependencies and cycles, allocate independent copies for repeated imports, and reject missing dependencies before modifying the destination package.
468
570
  - e18d19d: Keep nested audio and video playback settings when clearing a slide's animations, preserving their enclosing timing conditions.
@@ -470,13 +572,13 @@ firstSlideNum>`.
470
572
  - e18d19d: Preserve original run XML on the unchanged portions of a text range replacement in shapes and table cells. Partially edited fields still become literal text without retaining field-only paragraph properties.
471
573
  - e18d19d: Honor imported XML boolean spellings for through-black transitions and click advancement. Play cut-through-black transitions in presentation mode, respecting transition speed, reduced motion, and cleanup when interrupted or exited.
472
574
  - e18d19d: Read explicit XML `false` values for bold and italic correctly, preventing imported text from appearing bold or italic when those styles are disabled.
473
- - e18d19d: Preserve fonts, text colors, bold and italic formatting inherited from embedded table styles when displaying, editing and copying table text. Apply header, footer, banded row and column, and corner formatting in PowerPoint's precedence order while keeping explicitly formatted cell text unchanged.
575
+ - e18d19d: Preserve fonts, text colors, bold and italic formatting inherited from embedded table styles when displaying, editing and copying table text. Apply header, footer, banded row and column, and corner formatting in the reference desktop app's precedence order while keeping explicitly formatted cell text unchanged.
474
576
  - e18d19d: Read scRGB and HSL colors in imported fills, strokes, and gradient stops.
475
577
  - e18d19d: Resolve scRGB and HSL color elements used by shape shadows and glow effects when reading imported presentations.
476
578
 
477
579
  Preserve opacity modifiers and offsets on imported effects, including percent-form shadow opacity.
478
580
 
479
- - e18d19d: Recognize automatic playback for audio saved with PowerPoint's Play in Background command. Preserve its command timing when editing other playback settings, and reject unsupported start or delay changes instead of leaving conflicting playback instructions.
581
+ - e18d19d: Recognize automatic playback for audio saved with the reference desktop app's Play in Background command. Preserve its command timing when editing other playback settings, and reject unsupported start or delay changes instead of leaving conflicting playback instructions.
480
582
  - e18d19d: Slide background readers now resolve imported DrawingML preset and system colors instead of treating them as an empty solid fill.
481
583
  - e18d19d: Preserve the original outline after rejecting invalid width or opacity values, including when a later edit saves the shape.
482
584
  - e18d19d: Resolve DrawingML percentage RGB and HSL colors when reading imported presentations.
@@ -494,7 +596,7 @@ firstSlideNum>`.
494
596
  - e18d19d: fix: setShapeText / appendShapeText now add text to a shape that has no text body
495
597
 
496
598
  Previously, setting text on a shape authored without one (e.g. `addSlideShape`
497
- called without `text`) threw `shape "…" has no <p:txBody>`. PowerPoint always
599
+ called without `text`) threw `shape "…" has no <p:txBody>`. The reference desktop app always
498
600
  gives an autoshape a text body so you can click in and type, so these functions
499
601
  now create the body on demand and populate it, matching that behavior. Picture /
500
602
  table shapes still throw, since they are not text-bearing.
@@ -504,9 +606,9 @@ firstSlideNum>`.
504
606
  - e18d19d: Preserve slides with absolute or normalized relative relationship targets when moving or sorting a presentation. Speed up moving multiple editor slides by applying the final order once.
505
607
  - e18d19d: Preserve explicit cell-side borders in banded table styles, including interior cells, while retaining interior borders when a side is unspecified.
506
608
  - e18d19d: Read small and percent-suffixed text baseline offsets correctly so imported superscript and subscript positions retain their intended values.
507
- - e18d19d: Display theme-referenced background gradients instead of a solid color, including radial backgrounds selected with PowerPoint's Background Styles gallery. Resolve gradient colors through the owning slide master's theme and color map while preserving the original theme and background XML on save.
609
+ - e18d19d: Display theme-referenced background gradients instead of a solid color, including radial backgrounds selected with the reference desktop app's Background Styles gallery. Resolve gradient colors through the owning slide master's theme and color map while preserving the original theme and background XML on save.
508
610
  - e18d19d: Resolve shape style effect references against the owning slide master's theme, including placeholder colors and explicit empty effect lists in the layout-to-master cascade.
509
- - e18d19d: Preserve theme-based shape outlines in previews, including line colors and widths from PowerPoint Quick Styles. Direct line formatting now retains theme properties that it does not override.
611
+ - e18d19d: Preserve theme-based shape outlines in previews, including line colors and widths from the reference desktop app's Quick Styles. Direct line formatting now retains theme properties that it does not override.
510
612
  - e18d19d: Replacing a copied picture now changes only that picture, preserving other pictures that share its media or slide relationship. Repeated same-format replacements reuse the detached media part. Invalid image crop input now preserves the previous crop, including when a subsequent edit is saved.
511
613
  - e18d19d: Reject invalid slide dimensions before modifying the presentation. Page setup now enforces PPTX’s 1–56 inch range in both inches and centimeters, with matching Japanese and English validation messages.
512
614
 
@@ -562,7 +664,7 @@ firstSlideNum>`.
562
664
 
563
665
  ### Patch Changes
564
666
 
565
- - 73b763d: `removeSlide` now drops slide relationships in other slides that pointed at the removed slide, along with the `<a:hlinkClick>` / `<a:hlinkHover>` elements that carried them. A slide-jump click action stores its relationship on the _referring_ slide, so removing the target used to leave a dangling relationship: PowerPoint rejects the package and a later `duplicateSlide` of the referring slide throws `Cannot duplicate missing dependency`.
667
+ - 73b763d: `removeSlide` now drops slide relationships in other slides that pointed at the removed slide, along with the `<a:hlinkClick>` / `<a:hlinkHover>` elements that carried them. A slide-jump click action stores its relationship on the _referring_ slide, so removing the target used to leave a dangling relationship: the reference desktop app rejects the package and a later `duplicateSlide` of the referring slide throws `Cannot duplicate missing dependency`.
566
668
 
567
669
  ## 0.18.4
568
670
 
@@ -607,7 +709,7 @@ firstSlideNum>`.
607
709
  ### Minor Changes
608
710
 
609
711
  - 7e89e62: Validate enum inputs at authoring boundaries and throw a descriptive `RangeError`
610
- instead of writing invalid PowerPoint XML or silently selecting another mode.
712
+ instead of writing invalid the reference desktop app XML or silently selecting another mode.
611
713
 
612
714
  Affected APIs:
613
715
 
@@ -662,7 +764,7 @@ firstSlideNum>`.
662
764
  - Per series: `errorBars` / `xErrorBars` (fixed, percentage, standard deviation, standard error, custom), `fillOpacity`.
663
765
  - Per chart: `dataTable`, `upDownBars`, `categoryAxisDate` (date axis with time units), `categoryGroupLevels` (multi-level category labels), `categoryAxisScaling` (the x axis of scatter / bubble charts, or a date axis' range), `plotAreaLayout` / `titleLayout` / `legend.layout` (manual placement), `valueAxisLineHidden` / `categoryAxisLineHidden`, `valueAxis.displayUnitsLabel`.
664
766
  - Data labels gain `showBubbleSize`, `showLegendKey`, `fillColor`, and per-point `text` (a literal label, e.g. naming one scatter point).
665
- - A spec whose fields contradict each other (`view3D` on a scatter chart, error bars on a pie, a date axis with non-numeric categories, …) throws with a message naming the field, instead of writing a chart PowerPoint would repair.
767
+ - A spec whose fields contradict each other (`view3D` on a scatter chart, error bars on a pie, a date axis with non-numeric categories, …) throws with a message naming the field, instead of writing a chart the reference desktop app would repair.
666
768
 
667
769
  Behavior changes when reading existing decks:
668
770
 
@@ -678,12 +780,12 @@ firstSlideNum>`.
678
780
  - `addSlideMedia(slide, { kind: 'video' | 'audio', data, ... })` embeds a clip from bytes; `{ kind: 'online', url }` links an online video. YouTube watch / `youtu.be` / shorts URLs are rewritten to the embed URL; any other `http(s)` URL is stored as given, and anything else throws.
679
781
  - The container is detected from the bytes (mp4, m4v, mov, webm, avi, wmv, mp3, wav, m4a, ogg, wma); pass `format` to override. An undetectable clip, an unreadable `poster`, or a bad URL throws before anything is added to the package.
680
782
  - The new shape is a picture showing the poster frame: `setShapeImage` / `getShapeImageBytes` replace and read it. Without `poster`, a small built-in play-button image is used.
681
- - The slide gets the `<p:video>` / `<p:audio>` time node PowerPoint writes itself, which is what makes the play controls appear in the slide show. Identical clip bytes are stored once per deck.
682
- - `getShapeMedia(shape)` returns `{ kind: 'video' | 'audio', partName, contentType, bytes }` or `{ kind: 'online', url }`, also for media authored by PowerPoint, PptxGenJS or python-pptx. `findShapesWithMedia(slide)` lists a slide's clips.
783
+ - The slide gets the `<p:video>` / `<p:audio>` time node the reference desktop app writes itself, which is what makes the play controls appear in the slide show. Identical clip bytes are stored once per deck.
784
+ - `getShapeMedia(shape)` returns `{ kind: 'video' | 'audio', partName, contentType, bytes }` or `{ kind: 'online', url }`, also for media authored by the reference desktop app, PptxGenJS or python-pptx. `findShapesWithMedia(slide)` lists a slide's clips.
683
785
  - `@office-kit/pptx-dsl` gains a `Media` element with the same `kind` / `data` / `url` / `poster` props. It now requires `@office-kit/pptx` >= 0.17.0.
684
786
  - `copyShape` gives the copied clip its own time node, `removeShape` / `clearSlideShapes` remove it, and `importSlide` now carries video / audio parts (copied once per clip) and online-video links across decks — previously an imported slide with media was left with dangling relationships.
685
787
  - `setShapeAnimation` now works on a slide that holds a clip but no animation yet (it used to throw), and `clearSlideAnimations` keeps clips' time nodes instead of removing their play controls.
686
- - fix: `duplicateSlide` copied a slide's video / audio bytes for every duplicate, because the library's video / audio / media relationship-type constants did not match the URIs PowerPoint writes. Clips are now shared between the original and the duplicate, as documented.
788
+ - fix: `duplicateSlide` copied a slide's video / audio bytes for every duplicate, because the library's video / audio / media relationship-type constants did not match the URIs the reference desktop app writes. Clips are now shared between the original and the duplicate, as documented.
687
789
  - `validatePresentation` reports a video / audio relationship whose part is missing, and a media time node whose shape is no longer on the slide.
688
790
 
689
791
  ## 0.16.1
@@ -700,12 +802,12 @@ firstSlideNum>`.
700
802
 
701
803
  ### Minor Changes
702
804
 
703
- - 22f1f30: feat: author and read the complex-script typeface (`<a:cs>`), and align the blank deck's font scheme with Office's
805
+ - 22f1f30: feat: author and read the complex-script typeface (`<a:cs>`), and align the blank deck's font scheme with the reference desktop app's
704
806
 
705
807
  - `TextFormat.fontComplexScript` sets and reads `<a:cs typeface="…"/>`, the third typeface slot next to `font` (`<a:latin>`) and `fontEastAsian` (`<a:ea>`). It works everywhere the other two already did: `setShapeRunFormat` / `setShapeTextFormat`, `setShapeParagraphs` and `setTableCellParagraphs` (runs and `endFormat`), and it comes back from `getShapeRunFormat`, `getShapeRunFormatEffective` (including `+mj-cs` / `+mn-cs` and the theme's complex-script fallback), `getShapeParagraphElements`, `getParagraphEndFormat` and `getTableCellParagraphs`.
706
808
  - `ChartTextStyle.fontComplexScript` writes `<a:cs>` on a chart title / axis / data-label / legend style, and the chart reader returns it. `font` keeps filling the Latin and East Asian slots only, so a chart can name a complex-script face on the legend alone.
707
809
  - The three slots stay independent: setting one never changes the other two. Rewriting a slot writes its `typeface` attribute alone, so a `pitchFamily` / `charset` the source file carried on that element is dropped — as was already the case for `<a:latin>` and `<a:ea>`.
708
- - `createPresentation`'s blank deck now carries the standard per-script font list (`<a:font script="Thai" typeface="Cordia New"/>` and its 46 siblings) in both `majorFont` and `minorFont`, the same list Office's own default theme ships. It is what resolves a face for text in a script no run names one for. Every deck `createPresentation()` produces therefore has a larger `theme1.xml` than before — its bytes change — and text in a script with no explicit typeface now resolves through that list.
810
+ - `createPresentation`'s blank deck now carries the standard per-script font list (`<a:font script="Thai" typeface="Cordia New"/>` and its 46 siblings) in both `majorFont` and `minorFont`, the same list the reference desktop app's own default theme ships. It is what resolves a face for text in a script no run names one for. Every deck `createPresentation()` produces therefore has a larger `theme1.xml` than before — its bytes change — and text in a script with no explicit typeface now resolves through that list.
709
811
  - Chart titles and axis titles no longer carry a `lang="en-US"` language tag on their run. The chart-level tag is still `ChartSpec.language` (`<c:lang>`).
710
812
 
711
813
  ## 0.15.1
@@ -737,13 +839,13 @@ firstSlideNum>`.
737
839
  - `setShapeParagraphs(shape, paragraphs)` and `setTableCellParagraphs(cell, paragraphs)` replace a shape's or cell's text with paragraphs that each carry their own alignment and several differently formatted runs; run text is written verbatim. An empty paragraph list is rejected (use `[{ runs: [] }]` for an empty body).
738
840
  - `ChartSpec.valueAxisTickLabelPos` positions the primary value-axis tick labels (`none` / `low` / `high` / `nextTo`), mirroring `categoryAxisTickLabelPos`.
739
841
  - `ChartSeries.lineColor` sets the series outline / line color separately from its fill (a doughnut's slice borders, for example), and the reader returns the `<a:ln>` color of every series.
740
- - `ChartSeries.markerColor` / `markerLineColor` set the marker fill and outline colors of a line / scatter / radar series, and the reader returns both. The builder now always writes them (the fill defaults to the series color, the outline to the fill), because PowerPoint paints a marker without `<c:spPr>` in the theme's automatic color rather than the series color.
842
+ - `ChartSeries.markerColor` / `markerLineColor` set the marker fill and outline colors of a line / scatter / radar series, and the reader returns both. The builder now always writes them (the fill defaults to the series color, the outline to the fill), because the reference desktop app paints a marker without `<c:spPr>` in the theme's automatic color rather than the series color.
741
843
  - `@office-kit/pptx-preview` paints chart markers (data points and legend swatches) in `markerColor` / `markerLineColor` and strokes line / scatter / radar series in `lineColor`, instead of always using the series color.
742
- - Axis lines and gridlines carry a width next to their color: `valueAxisLineWidthEmu` / `categoryAxisLineWidthEmu`, `valueAxisMajorGridlineWidthEmu` / `valueAxisMinorGridlineWidthEmu`, `categoryAxisMajorGridlineWidthEmu` / `categoryAxisMinorGridlineWidthEmu`, and `secondaryValueAxis.lineWidthEmu` / `majorGridlineWidthEmu` (EMU, 12700 = 1 pt). The reader returns them, and a width of 0 — valid in the schema — now reads back on these and on a series' `lineWidthEmu` instead of turning into `undefined`. Without a width PowerPoint draws these lines at 0.75 pt, so a 1 pt line from another writer used to come back thinner.
844
+ - Axis lines and gridlines carry a width next to their color: `valueAxisLineWidthEmu` / `categoryAxisLineWidthEmu`, `valueAxisMajorGridlineWidthEmu` / `valueAxisMinorGridlineWidthEmu`, `categoryAxisMajorGridlineWidthEmu` / `categoryAxisMinorGridlineWidthEmu`, and `secondaryValueAxis.lineWidthEmu` / `majorGridlineWidthEmu` (EMU, 12700 = 1 pt). The reader returns them, and a width of 0 — valid in the schema — now reads back on these and on a series' `lineWidthEmu` instead of turning into `undefined`. Without a width the reference desktop app draws these lines at 0.75 pt, so a 1 pt line from another writer used to come back thinner.
743
845
  - `ChartDataLabels.showLeaderLines` writes and reads `<c:showLeaderLines>` on series- and chart-level labels (per-point overrides have no such setting).
744
- - Chart, axis and secondary-axis titles no longer force a 14 pt default size or a horizontal layout: without `sizePt` the application default applies, and a title without a rotation writes neither `rot` nor `vert="horz"` (PowerPoint reads a lone `vert="horz"` as "not rotated"), so a value-axis title takes PowerPoint's default (vertical) — pass `0` to keep it horizontal. The reader merges a title's paragraph defaults under its run style.
846
+ - Chart, axis and secondary-axis titles no longer force a 14 pt default size or a horizontal layout: without `sizePt` the application default applies, and a title without a rotation writes neither `rot` nor `vert="horz"` (the reference desktop app reads a lone `vert="horz"` as "not rotated"), so a value-axis title takes the reference desktop app's default (vertical) — pass `0` to keep it horizontal. The reader merges a title's paragraph defaults under its run style.
745
847
  - Combo series are shaped by their own `chartKind`: a line series in a column chart keeps its markers and `smooth`, and line / area plot groups write a schema-valid `<c:grouping>` (`standard` instead of the bar-only `clustered`).
746
- - Horizontal bar charts (`kind: 'bar'`) now put the category axis on the left and the value axis at the bottom, matching PowerPoint; the hidden companion category axis of a secondary axis follows the primary one.
848
+ - Horizontal bar charts (`kind: 'bar'`) now put the category axis on the left and the value axis at the bottom, matching the reference desktop app; the hidden companion category axis of a secondary axis follows the primary one.
747
849
  - The chart reader honors `<c:ptCount>` (including on multi-level category caches), so series with empty trailing points keep their full length on read-back; cache points past the authored count are dropped.
748
850
  - The chart reader identifies the secondary value axis by which plot groups reference it, not by its position, so a scatter chart's X axis at the top no longer reads as secondary and decks that list the secondary axis pair first read back correctly.
749
851
  - The XML parser applies XML 1.0 end-of-line handling: a raw CR LF or CR in a part reads as LF, while a `&#13;` character reference still yields a CR.
@@ -774,7 +876,7 @@ firstSlideNum>`.
774
876
  `ChartSeries` gains `chartKind` (`'bar' | 'column' | 'line' | 'area'`) to
775
877
  overlay e.g. a line series on a column chart, and `secondaryAxis: true` to
776
878
  plot a series against a right-hand secondary value axis — the standard
777
- PowerPoint combo layout for series with mixed units (counts vs. rates).
879
+ the reference desktop app's combo layout for series with mixed units (counts vs. rates).
778
880
  The builder splits series into plot groups (`<c:barChart>` + `<c:lineChart>`
779
881
  …) and emits the secondary `<c:valAx>`/`<c:catAx>` pair on demand;
780
882
  `getShapeChartSpec` round-trips both fields. The preview renderer paints
@@ -825,7 +927,7 @@ firstSlideNum>`.
825
927
 
826
928
  - eeb8659: Validate authoring inputs at the API boundary so out-of-range values throw a
827
929
  clear `RangeError` instead of silently emitting a schema-invalid `.pptx` that
828
- PowerPoint marks corrupt and "repairs".
930
+ the reference desktop app marks corrupt and "repairs".
829
931
 
830
932
  A generative schema-validation sweep surfaced a whole class of defects where a
831
933
  caller-supplied number/string was serialized straight into a constrained
@@ -919,7 +1021,7 @@ firstSlideNum>`.
919
1021
  example.
920
1022
 
921
1023
  - eeb8659: Close a final batch of correctness defects a generative schema sweep surfaced,
922
- where the writer emitted a `.pptx` PowerPoint marks corrupt:
1024
+ where the writer emitted a `.pptx` the reference desktop app marks corrupt:
923
1025
 
924
1026
  - **XML-illegal control characters** in any text field (shape text, table cells,
925
1027
  notes, chart titles/categories/series, hyperlink tooltip/URL, section names,
@@ -952,7 +1054,7 @@ firstSlideNum>`.
952
1054
  ### Patch Changes
953
1055
 
954
1056
  - e9eae5c: Fix `<a:tint>` / `<a:shade>` colour resolution to compute in linear-light RGB,
955
- matching PowerPoint and LibreOffice. A 75% tint of black now resolves to a mid
1057
+ matching the reference desktop app and LibreOffice. A 75% tint of black now resolves to a mid
956
1058
  grey (~#8B8B8B) instead of the too-dark #404040, so colours derived from theme
957
1059
  scheme transforms (subtitle placeholders, table banding, chart fills) render at
958
1060
  the right lightness.
@@ -970,9 +1072,9 @@ firstSlideNum>`.
970
1072
  `setShapeBullets('number')` / `setParagraphBullet(..., 'number')` emitted only
971
1073
  `<a:buAutoNum>`, with no `<a:buFont>` — so the auto-number glyph fell through to
972
1074
  whatever font happened to apply, instead of the theme's major font that
973
- PowerPoint and PptxGenJS use. Numbered lists now emit
1075
+ the reference desktop app and PptxGenJS use. Numbered lists now emit
974
1076
  `<a:buFont typeface="+mj-lt"/>` ahead of the number and write the default
975
- `startAt="1"` explicitly, matching PowerPoint-authored output.
1077
+ `startAt="1"` explicitly, matching desktop-app-authored output.
976
1078
 
977
1079
  ## 0.7.0
978
1080
 
@@ -984,14 +1086,14 @@ firstSlideNum>`.
984
1086
 
985
1087
  ### Patch Changes
986
1088
 
987
- - 099d77b: Emit PowerPoint's default cell insets on table cells
1089
+ - 099d77b: Emit the reference desktop app's default cell insets on table cells
988
1090
 
989
- `addSlideTable` cells now carry the explicit default insets PowerPoint and
1091
+ `addSlideTable` cells now carry the explicit default insets the reference desktop app and
990
1092
  PptxGenJS both write — `<a:tcPr marL="91440" marR="91440" marT="45720"
991
1093
  marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
992
1094
  suppresses any inherited list bullet on the cell paragraph. The table renders
993
- identically (these match the values PowerPoint applies when they're absent),
994
- but the cell is now self-describing, so the output matches a PowerPoint- or
1095
+ identically (these match the values the reference desktop app applies when they're absent),
1096
+ but the cell is now self-describing, so the output matches a desktop-app- or
995
1097
  PptxGenJS-authored table byte-for-byte at the cell level.
996
1098
 
997
1099
  Note: `getTableCellMargins` now returns the explicit `91440 / 45720` defaults
@@ -1007,11 +1109,11 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1007
1109
  `setParagraphBullet` added the bullet glyph but no hanging indent, so a bullet
1008
1110
  authored on a text box (which inherits the master's `otherStyle`, marL=0, not
1009
1111
  the body style) rendered with the glyph jammed against the text. They now
1010
- write PowerPoint's per-level default `marL` / `indent` (unless the caller set
1011
- their own), matching PowerPoint and PptxGenJS.
1112
+ write the reference desktop app's per-level default `marL` / `indent` (unless the caller set
1113
+ their own), matching the reference desktop app and PptxGenJS.
1012
1114
  - **Charts with multi-level category references now read back.** The chart
1013
1115
  reader handled `<c:strRef>` / `<c:strLit>` categories but not
1014
- `<c:multiLvlStrRef>`, which is what PowerPoint and PptxGenJS emit — so
1116
+ `<c:multiLvlStrRef>`, which is what the reference desktop app and PptxGenJS emit — so
1015
1117
  `getShapeChartCategories` (and the full `getShapeChartSpec`) returned an empty
1016
1118
  category list for those charts. It now reads the level's points.
1017
1119
 
@@ -1021,23 +1123,23 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1021
1123
 
1022
1124
  - 333b19f: fix: line-chart series colors now paint the line. The color was written only
1023
1125
  as a bare `<a:solidFill>`, which doesn't color a line series' stroke, so
1024
- PowerPoint ignored it and fell back to its automatic palette (a 4-series line
1126
+ the reference desktop app ignored it and fell back to its automatic palette (a 4-series line
1025
1127
  chart authored as accent1–4 rendered blue/red/green/purple instead of the
1026
1128
  requested colors). The color is now also emitted on `<a:ln>`.
1027
1129
  - 665d4c2: Fix unstyled, broken-looking tables from `addSlideTable`
1028
1130
 
1029
1131
  `addSlideTable` set the `firstRow` / `bandRow` flags but never wrote a
1030
1132
  `<a:tableStyleId>`, and `createPresentation` shipped no `tableStyles.xml` part.
1031
- With no style to resolve against, PowerPoint painted the table as a borderless,
1133
+ With no style to resolve against, the reference desktop app painted the table as a borderless,
1032
1134
  unstyled block — a "broken" grid with no rules.
1033
1135
 
1034
- - **Tables now reference PowerPoint's "No Style, Table Grid" built-in**
1136
+ - **Tables now reference the reference desktop app's "No Style, Table Grid" built-in**
1035
1137
  (`{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}`) via `<a:tableStyleId>`, the same
1036
- default PptxGenJS and PowerPoint itself emit, so a table resolves to a clean
1138
+ default PptxGenJS and the reference desktop app itself emit, so a table resolves to a clean
1037
1139
  ruled grid. Callers can override with the internal `styleId` option (or the
1038
1140
  existing `setTableStyleId`).
1039
1141
  - **`createPresentation` now ships `/ppt/tableStyles.xml`** (referenced from
1040
- `presentation.xml.rels`), matching every PowerPoint-authored deck, so the
1142
+ `presentation.xml.rels`), matching every desktop-app-authored deck, so the
1041
1143
  `tableStyleId` always has a backing part.
1042
1144
 
1043
1145
  ## 0.6.0
@@ -1046,7 +1148,7 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1046
1148
 
1047
1149
  - 0f7c538: Preview: take the default text color from the deck's body style, not the `tx1` token
1048
1150
 
1049
- The preview used `scheme:tx1` as the fallback color for runs without an authored color. On a template with an inverted color map (`tx1 → lt1`) that resolves to the light slot, so body text was painted white on the white background — the whole slide looked blank. PowerPoint instead takes the fallback from the master `bodyStyle` (e.g. `schemeClr bg1`). The preview now does the same via the newly exported `resolveDeckBodyTextColor(slide)`, so default-colored text and table-cell text resolve to the color PowerPoint actually paints.
1151
+ The preview used `scheme:tx1` as the fallback color for runs without an authored color. On a template with an inverted color map (`tx1 → lt1`) that resolves to the light slot, so body text was painted white on the white background — the whole slide looked blank. The reference desktop app instead takes the fallback from the master `bodyStyle` (e.g. `schemeClr bg1`). The preview now does the same via the newly exported `resolveDeckBodyTextColor(slide)`, so default-colored text and table-cell text resolve to the color the reference desktop app actually paints.
1050
1152
 
1051
1153
  - New export **`resolveDeckBodyTextColor(slide)`** — the deck's resolved body-text color (master `bodyStyle`, run through the effective color map + theme). This is the color `addSlideTable` / `addSlideChart` bake in, now reusable by renderers.
1052
1154
 
@@ -1054,8 +1156,8 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1054
1156
 
1055
1157
  - 0f7c538: Fix corrupt files from fractional EMU and sideways-spreading stacked bar charts
1056
1158
 
1057
- - **Whole-EMU coordinates.** `inches` / `cm` / `mm` / `pt` / `emu` now round to integer EMU, and every shape / table / text-box / connector / chart offset is rounded on serialization. Floating-point drift from unit math (e.g. `3090672.0000000005`) previously reached `<a:off>` / `<a:ext>`, which is invalid `ST_Coordinate` (xsd:long) — PowerPoint flagged the file as corrupt and "repaired" it by zeroing the offending offsets, collapsing shapes to the slide origin.
1058
- - **Stacked bar/column charts** now emit `<c:overlap val="100"/>` by default (and for `percentStacked`). Without it PowerPoint draws each series in its own sub-slot so the "stack" spreads sideways across the category. An explicit `overlapPct` still wins; clustered charts are unchanged.
1159
+ - **Whole-EMU coordinates.** `inches` / `cm` / `mm` / `pt` / `emu` now round to integer EMU, and every shape / table / text-box / connector / chart offset is rounded on serialization. Floating-point drift from unit math (e.g. `3090672.0000000005`) previously reached `<a:off>` / `<a:ext>`, which is invalid `ST_Coordinate` (xsd:long) — the reference desktop app flagged the file as corrupt and "repaired" it by zeroing the offending offsets, collapsing shapes to the slide origin.
1160
+ - **Stacked bar/column charts** now emit `<c:overlap val="100"/>` by default (and for `percentStacked`). Without it the reference desktop app draws each series in its own sub-slot so the "stack" spreads sideways across the category. An explicit `overlapPct` still wins; clustered charts are unchanged.
1059
1161
 
1060
1162
  ## 0.5.0
1061
1163
 
@@ -1063,12 +1165,12 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1063
1165
 
1064
1166
  - 4a2ede1: Resolve scheme colors through the slide's color map so inverted-map templates render correctly
1065
1167
 
1066
- Templates whose slide master inverts the color map (`<p:clrMap bg1="dk1" tx1="lt1">`, common in Google Slides / Canva exports) previously rendered with swapped light/dark colors: slide backgrounds came out black in the preview while PowerPoint paints them white, and generated tables and charts came out with invisible text (the default `tx1` token resolved to the same color as the background).
1168
+ Templates whose slide master inverts the color map (`<p:clrMap bg1="dk1" tx1="lt1">`, common in Google Slides / Canva exports) previously rendered with swapped light/dark colors: slide backgrounds came out black in the preview while the reference desktop app paints them white, and generated tables and charts came out with invisible text (the default `tx1` token resolved to the same color as the background).
1067
1169
 
1068
1170
  - **`getEffectiveColorMap(slide)`** — new export returning the slide's effective color map (the master's `<p:clrMap>` overlaid by a per-slide `<p:clrMapOvr>`). Color resolution and renderers apply it to `schemeClr` tokens before indexing the theme.
1069
1171
  - **`resolveDrawingColor(colorEl, theme, clrMap?)`** — accepts an optional color map; scheme tokens are remapped through it before the theme lookup. Omitting it preserves the previous behavior (correct for the standard map).
1070
1172
  - **`addSlideTable` / `addSlideChart`** now bake the deck's resolved body-text color onto table cells and chart text (axis labels, legend, data labels) so generated tables and charts stay readable regardless of the template's color map. Authored colors still win; override table cells afterwards with `setTableCellTextFormat`.
1071
- - **`pptx-kit-preview`** resolves `schemeClr` tokens through the effective color map, so previews of inverted-map decks match what PowerPoint paints.
1173
+ - **`pptx-kit-preview`** resolves `schemeClr` tokens through the effective color map, so previews of inverted-map decks match what the reference desktop app paints.
1072
1174
 
1073
1175
  ## 0.4.0
1074
1176
 
@@ -1080,7 +1182,7 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1080
1182
  legends, and data labels now accept a font face
1081
1183
  (`titleStyle: { font: 'Yu Gothic' }`). The builder writes both
1082
1184
  `<a:latin typeface>` and `<a:ea typeface>` so CJK families render
1083
- correctly in PowerPoint, and `getSlideCharts` / `getShapeChartSpec` read
1185
+ correctly in the reference desktop app, and `getSlideCharts` / `getShapeChartSpec` read
1084
1186
  the face back for round-trips. Works through both `addSlideChart` and
1085
1187
  `setChartSpec`. (The SVG preview keeps its fixed substitution font set —
1086
1188
  authored chart faces affect the emitted PPTX, not the preview raster.)
@@ -1112,7 +1214,7 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1112
1214
  impossible. From-scratch authoring (a headline feature in the README) did
1113
1215
  not actually work without loading a template file.
1114
1216
 
1115
- `createPresentation()` now ships a slide master, the Office theme, and three
1217
+ `createPresentation()` now ships a slide master, a default theme, and three
1116
1218
  layouts — `Blank`, `Title Slide`, and `Title and Content` — so you can go
1117
1219
  straight to `addSlide` / `addTitleSlide` / `addContentSlide` and `savePresentation`.
1118
1220
  Every emitted part is validated against the ECMA-376 XSDs in CI. The slide
@@ -1123,13 +1225,13 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1123
1225
  - `addSlideChart` now rejects a series `color` (and `pointColors` /
1124
1226
  `trendline.color` / plot- and chart-area fills / axis & gridline colors)
1125
1227
  that isn't an sRGB hex (`#RRGGBB` or `RRGGBB`) with a clear error, instead
1126
- of silently emitting an invalid `<a:srgbClr val="…"/>` that PowerPoint
1228
+ of silently emitting an invalid `<a:srgbClr val="…"/>` that the reference desktop app
1127
1229
  dropped or repaired. Bare `RRGGBB` (no `#`) is accepted and normalized;
1128
1230
  scheme tokens like `accent1` are correctly rejected, since charts emit
1129
1231
  `srgbClr`.
1130
1232
  - `addSlideTable` with empty `rows: []` (or a row with no cells) now throws
1131
1233
  an actionable `addSlideTable: …` error at the boundary rather than
1132
- producing a grid-less `<a:tbl>` that triggers PowerPoint's repair dialog.
1234
+ producing a grid-less `<a:tbl>` that triggers the reference desktop app's repair dialog.
1133
1235
  (The error message previously named the old internal `addTable` path.)
1134
1236
  - `findSlideLayout`'s case-sensitive, locale-dependent name matching is now
1135
1237
  documented in its JSDoc and the README, pointing readers to the
@@ -1149,7 +1251,7 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1149
1251
  hanging indent through the paragraph cascade (new `bullet` field on
1150
1252
  `ParagraphProperties` from `getParagraphPropertiesEffective`); charts no
1151
1253
  longer invent a legend when the XML authors no `<c:legend>`, and the value
1152
- axis gets Excel-style headroom above the data max with the tick step
1254
+ axis gets spreadsheet-style headroom above the data max with the tick step
1153
1255
  preserved; the chart builder writes `<c:smooth val="0"/>` explicitly on line
1154
1256
  series (the schema default for an absent element is smooth=1, which made
1155
1257
  LibreOffice draw unauthored lines as curves); and the pure-SVG text layer is
@@ -1174,7 +1276,7 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1174
1276
  `bulletStyle === 'number'` or `{ autoNum: '…' }` now emit the next
1175
1277
  number in sequence (1., 2., 3., …; A., B., C., …; i., ii., iii., …)
1176
1278
  rather than a generic dot. Counter resets on a non-numbered paragraph
1177
- or a level change, matching PowerPoint's behaviour.
1279
+ or a level change, matching the reference desktop app's behaviour.
1178
1280
 
1179
1281
  Covers the common `ST_TextAutoNumberScheme` tokens — arabicPeriod /
1180
1282
  ParenR / ParenBoth, romanUc / Lc with Period / ParenR / ParenBoth,
@@ -1190,7 +1292,7 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1190
1292
  and `categoryAxisMajorTickMark` carry `<c:majorTickMark val="in|out|
1191
1293
  cross|none"/>`. The playground value-axis renderer draws short stubs
1192
1294
  on the appropriate side of the plot edge (default `out` matches
1193
- PowerPoint's stock look); `none` suppresses them entirely.
1295
+ the reference desktop app's stock look); `none` suppresses them entirely.
1194
1296
  - 3a2b974: feat: chart axis titles honor authored `<a:rPr>` font / color.
1195
1297
  `ChartSpec.categoryAxisTitleStyle` and `valueAxisTitleStyle` carry the
1196
1298
  same `ChartTextStyle` shape as `titleStyle`. The playground renderer
@@ -1255,7 +1357,7 @@ cross|none"/>`. The playground value-axis renderer draws short stubs
1255
1357
  (converted from OOXML's 60000ths-of-a-degree to plain degrees). The
1256
1358
  playground renderer rotates each tick label around its anchor and
1257
1359
  shifts the text-anchor side based on the sign of the rotation so dense
1258
- charts with 45°/-45°/90° rotated labels render the way PowerPoint
1360
+ charts with 45°/-45°/90° rotated labels render the way the reference desktop app
1259
1361
  shows them. Rotated labels also get a longer truncation budget before
1260
1362
  ellipsization.
1261
1363
  - 4f5cc4c: feat: round out gridline color round-trip with 3 more fields —
@@ -1278,7 +1380,7 @@ cross|none"/>`. The playground value-axis renderer draws short stubs
1278
1380
  `ChartSpec.plotAreaStrokeColor` reads `<c:plotArea><c:spPr><a:ln>`.
1279
1381
  The playground renderer projects them onto the chart-area card
1280
1382
  border and the plot-area inner rect — branded charts with thick / no
1281
- / colored card borders finally render the way PowerPoint shows them.
1383
+ / colored card borders finally render the way the reference desktop app shows them.
1282
1384
  - eb4159e: feat(chart): `ChartSpec.valueAxisHidden` and `categoryAxisHidden`
1283
1385
  read `<c:valAx><c:delete val="1"/>` and `<c:catAx><c:delete val="1"/>`.
1284
1386
  Playground skips rendering the axis when hidden — common on KPI tile
@@ -1307,7 +1409,7 @@ cross|none"/>`. The playground value-axis renderer draws short stubs
1307
1409
  `ChartSpec.valueAxisTitleRotationDeg` — rotation in plain degrees
1308
1410
  (clockwise) on the per-axis title. Maps to
1309
1411
  `<c:catAx|valAx><c:title><c:tx><c:rich><a:bodyPr rot="N"/>` (60000ths
1310
- of a degree on the wire). PowerPoint often emits `-90` on the value-
1412
+ of a degree on the wire). The reference desktop app often emits `-90` on the value-
1311
1413
  axis title; the field now survives round-trip. Read by chart-reader
1312
1414
  via a new `readTitleRotationDeg` helper; written by chart-builder
1313
1415
  through an extended `titleElement(title, style?, rotationDeg?)`
@@ -1447,14 +1549,14 @@ cross|none"/>`. The playground value-axis renderer draws short stubs
1447
1549
  CT_CatAx schema order.
1448
1550
  - 21f58cb: feat: `ChartSpec.categoryAxisNoMultiLevelLabel` — toggle multi-level
1449
1551
  (hierarchical) category labels via `<c:catAx><c:noMultiLvlLbl val/>`.
1450
- PowerPoint defaults to `0` (multi-level labels stack); set to `true`
1552
+ The reference desktop app defaults to `0` (multi-level labels stack); set to `true`
1451
1553
  to flatten hierarchical categories into a single row. Read by
1452
1554
  chart-reader, written by chart-builder at the schema-required last
1453
1555
  position inside `<c:catAx>`.
1454
1556
  - c561df4: feat: `ChartSpec.categoryAxisNumberFormat` — number-format code for the
1455
1557
  category-axis tick labels (`<c:catAx><c:numFmt formatCode="…"/>`). Most
1456
1558
  useful on date-style categories (`"mm/dd/yyyy"`, `"mmm-yyyy"`) but
1457
- accepts any Excel format string. Independent of `valueAxis.numberFormat`.
1559
+ accepts any spreadsheet number-format string. Independent of `valueAxis.numberFormat`.
1458
1560
  Read by chart-reader, written by chart-builder in the correct CT_CatAx
1459
1561
  schema order (after `<c:title>`, before `<c:majorTickMark>`).
1460
1562
  - 3ecc11b: feat(chart): category-axis label-skip + position. `ChartSpec.categoryAxisTickLabelSkip`
@@ -1475,7 +1577,7 @@ cross|none"/>`. The playground value-axis renderer draws short stubs
1475
1577
  - 199031b: feat: chart data labels honor `<c:dLbls><c:numFmt formatCode="…"/>`.
1476
1578
  `ChartDataLabels.numberFormat` exposes the format code on both
1477
1579
  chart-level and per-series toggle groups, and the playground renderer
1478
- projects value labels through the same Excel-format subset the value
1580
+ projects value labels through the same spreadsheet number-format subset the value
1479
1581
  axis already supports (`"0%"`, `"$#,##0"`, `"0.00"`, etc). Per-series
1480
1582
  formats win over the chart-level default.
1481
1583
  - b77c0ed: feat(chart): `ChartSpec.dispBlanksAs` reads `<c:dispBlanksAs>`
@@ -1515,7 +1617,7 @@ cross|none"/>`. The playground value-axis renderer draws short stubs
1515
1617
  `<c:gapWidth>` and `<c:overlap>` on bar / column plots. Playground
1516
1618
  sizes bars per ECMA-376 §21.2.2.75 — `barW = groupW / (clusterUnits +
1517
1619
  gapWidth/100)` with `clusterUnits = 1 + (S - 1)(1 - overlap/100)` —
1518
- so authored bar spacing matches PowerPoint instead of the hard-coded
1620
+ so authored bar spacing matches the reference desktop app instead of the hard-coded
1519
1621
  0.8 / 0.7 ratios.
1520
1622
  - b88dbb8: feat(chart): `ChartSpec.valueAxisMajorGridlines` / `valueAxisMinorGridlines`
1521
1623
  read the presence of `<c:majorGridlines/>` / `<c:minorGridlines/>`
@@ -1526,12 +1628,12 @@ gapWidth/100)` with `clusterUnits = 1 + (S - 1)(1 - overlap/100)` —
1526
1628
  - 4caa5ad: feat(chart): `ChartSeries.invertIfNegative` reads `<c:ser>
1527
1629
  <c:invertIfNegative val="1"/>`. Playground's bar / column renderer
1528
1630
  paints negative bars in a darker shade of the series color when the
1529
- flag is set — matching PowerPoint's profit/loss visualization.
1631
+ flag is set — matching the reference desktop app's profit/loss visualization.
1530
1632
  - b603115: feat: `ChartSpec.language` (`<c:chartSpace><c:lang val=…/>`) and
1531
- `ChartSpec.date1904` (`<c:date1904 val=…/>`) — chartSpace-level Office
1532
- metadata round-tripped for parity. `language` is the Office UI
1633
+ `ChartSpec.date1904` (`<c:date1904 val=…/>`) — chartSpace-level
1634
+ metadata round-tripped for parity. `language` is the UI
1533
1635
  language code (e.g. `'en-US'`, `'ja-JP'`); `date1904` selects the
1534
- 1904 date epoch (default `false` = Excel 1900 epoch, surface only
1636
+ 1904 date epoch (default `false` = 1900 date epoch, surface only
1535
1637
  when explicitly true). pptx-kit's renderers don't act on either yet.
1536
1638
  - 028e3b7: feat: chart `<c:legend><c:legendEntry><c:delete val="1"/>` honored.
1537
1639
  `ChartSpec.legend.hiddenIndices` carries the series indices the
@@ -1556,15 +1658,15 @@ gapWidth/100)` with `clusterUnits = 1 + (S - 1)(1 - overlap/100)` —
1556
1658
  - 28d77ea: fix: chart categories accept `<c:cat><c:numRef>` (numeric / date
1557
1659
  categories). Previously the category-axis dropped to an empty
1558
1660
  labels array when the chart authored a numeric category channel
1559
- (common for date-axis line charts authored in Excel). Falls back
1661
+ (common for date-axis line charts authored in a spreadsheet app). Falls back
1560
1662
  to formatting each cached numeric value as a string so date /
1561
1663
  number cats appear on the axis instead of disappearing.
1562
- - 7b3ba0a: feat(chart): axis number formats now accept Excel's `"$"#,##0`
1563
- quoted-literal prefix / suffix syntax. PowerPoint typically emits
1664
+ - 7b3ba0a: feat(chart): axis number formats now accept the spreadsheet-style `"$"#,##0`
1665
+ quoted-literal prefix / suffix syntax. The reference desktop app typically emits
1564
1666
  currency as `"$"#,##0` (or `"\$"#,##0`) rather than the bare `$`
1565
1667
  form, so the previous detection missed it.
1566
1668
  - d2f86d2: feat(chart): `ChartAxisScaling.numberFormat` reads `<c:valAx><c:numFmt
1567
- formatCode="…"/>`. Playground projects the most common Excel format
1669
+ formatCode="…"/>`. Playground projects the most common spreadsheet number-format
1568
1670
  codes to axis labels — percent (`'0%'`, `'0.0%'`), thousand
1569
1671
  separator (`'#,##0'`, `'#,##0.0'`), and currency prefixes
1570
1672
  (`'$#,##0'`, `'¥#,##0'`). Other codes fall through to the generic
@@ -1575,20 +1677,20 @@ formatCode="…"/>`. Playground projects the most common Excel format
1575
1677
  horizontal strip. Playground sizes the plot area accordingly — gives
1576
1678
  the chart back the extra vertical real estate when overlay is set.
1577
1679
  - 4cde872: feat: `ChartSpec.plotVisibleCellsOnly` — toggle `<c:plotVisOnly val/>`.
1578
- PowerPoint's default is `true` (only plot visible cells); the field
1680
+ The reference desktop app's default is `true` (only plot visible cells); the field
1579
1681
  exists to let authors opt into `false` (plot hidden rows / columns too).
1580
1682
  The reader surfaces `false` only when the wire is explicitly `0` so
1581
1683
  round-tripping the common default doesn't drag a redundant explicit
1582
1684
  `true` into the spec.
1583
1685
  - 693ba3e: feat: `ChartSpec.roundedCorners` — round-trip the chartSpace-level
1584
- `<c:roundedCorners val>` toggle. PowerPoint's default is `false`; the
1686
+ `<c:roundedCorners val>` toggle. The reference desktop app's default is `false`; the
1585
1687
  reader surfaces `true` only when the wire is explicitly `1` and the
1586
1688
  builder emits the element only when authored, so common defaults stay
1587
1689
  clean. Schema position is BEFORE `<c:chart>` (per CT_ChartSpace).
1588
1690
  - 733120a: feat(chart): `ChartSeries.smooth` reads `<c:smooth val="1"/>`. Playground
1589
1691
  line / area renderer interpolates a cubic-Bézier curve through the
1590
1692
  data points (Catmull-Rom-to-Bezier with 0.5 tension) when `smooth` is
1591
- true, matching PowerPoint's "smooth line" preset visually.
1693
+ true, matching the reference desktop app's "smooth line" preset visually.
1592
1694
  - d581121: feat(site/playground): bar (horizontal), line, and area charts now
1593
1695
  honour `ChartSpec.grouping` for stacked / percentStacked layouts —
1594
1696
  matching the column-chart treatment added previously. Data labels
@@ -1604,9 +1706,9 @@ formatCode="…"/>`. Playground projects the most common Excel format
1604
1706
  Adds the `ChartGrouping` type to the public surface.
1605
1707
 
1606
1708
  - 53148e4: feat: `ChartSpec.chartStyle` — round-trip the chartSpace-level
1607
- `<c:style val="N"/>` PowerPoint chart-style preset (1..48). Encodes a
1709
+ `<c:style val="N"/>` the reference desktop app's chart-style preset (1..48). Encodes a
1608
1710
  curated combo of theme accent colors, gradients, effects, and font
1609
- sizes from the PowerPoint "Chart Styles" gallery. Read and written for
1711
+ sizes from the reference desktop app's "Chart Styles" gallery. Read and written for
1610
1712
  round-trip parity; pptx-kit's renderers don't interpret the preset
1611
1713
  yet, but the field survives save/reload.
1612
1714
  - b1cfda3: feat: `ChartSpec.categoryAxisTickMarkSkip` — the second half of the
@@ -1617,7 +1719,7 @@ formatCode="…"/>`. Playground projects the most common Excel format
1617
1719
  chart-builder.
1618
1720
  - 2599a46: feat: chart titles read `<c:tx><c:strRef>` workbook-cell references.
1619
1721
  Previously only literal `<c:rich>` titles surfaced; titles authored
1620
- via Excel's "Link to source cell" wizard (which emits `<c:strRef>`
1722
+ via a spreadsheet app's "Link to source cell" feature (which emits `<c:strRef>`
1621
1723
  with a `<c:strCache>` of the resolved text) now flow through to
1622
1724
  `ChartSpec.title` as the cached value. Affects the title shown above
1623
1725
  the chart and, transitively, axis-title rendering.
@@ -1635,7 +1737,7 @@ formatCode="…"/>`. Playground projects the most common Excel format
1635
1737
  chart-reader; written by chart-builder in the correct CT_Trendline
1636
1738
  schema order (after `<c:backward>`, before any `<c:trendlineLbl>`).
1637
1739
  - a978251: feat: `ChartTrendline.name` — round-trip a custom trendline label
1638
- (`<c:trendline><c:name>…`). PowerPoint auto-generates a label like
1740
+ (`<c:trendline><c:name>…`). The reference desktop app auto-generates a label like
1639
1741
  "Linear (X)" or "MA(5) (X)" when this element is omitted; authors who
1640
1742
  want a different label (or who imported one from another tool) now
1641
1743
  have the field. Read by chart-reader; written by chart-builder at the
@@ -1666,7 +1768,7 @@ formatCode="…"/>`. Playground projects the most common Excel format
1666
1768
  `ChartSpec.varyColors` carries the `<c:plottedKind><c:varyColors val="1"/>`
1667
1769
  flag. When set and the chart has exactly one series, the renderer
1668
1770
  assigns each data point a distinct accent color (mirroring
1669
- PowerPoint's "Vary colors by point" toggle for column / bar). Pies
1771
+ the reference desktop app's "Vary colors by point" toggle for column / bar). Pies
1670
1772
  already varied colors implicitly.
1671
1773
  - 69431a9: feat: `getSlideColorMapOverride(slide)` returns the slide's
1672
1774
  `<p:clrMapOvr><a:overrideClrMapping/>` token-remap, or `null` when the
@@ -1685,12 +1787,12 @@ formatCode="…"/>`. Playground projects the most common Excel format
1685
1787
  the supplied theme.
1686
1788
  - New `getShapeFillColorResolved(pres, shape)` and
1687
1789
  `getShapeStrokeColorResolved(pres, shape)` return the exact `#RRGGBB`
1688
- PowerPoint paints — useful for renderers / exporters where the legacy
1790
+ the reference desktop app paints — useful for renderers / exporters where the legacy
1689
1791
  `getShapeFillColor` / `getShapeStrokeColor` strings (`#RRGGBB` or
1690
1792
  `scheme:<token>`) miss both scheme resolution and color transforms.
1691
1793
  - `getShapeRunFormatEffective` now applies the same pipeline at every
1692
1794
  layer of the rPr cascade, so a run inheriting `accent1 lumMod=40000
1693
- lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1795
+ lumOff=60000` (the reference desktop app's "Accent 1, Lighter 60%") resolves to the
1694
1796
  concrete tinted hex instead of leaking the raw token through.
1695
1797
 
1696
1798
  - 263bf52: feat(site/playground): bent / curved connector routing.
@@ -1721,7 +1823,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1721
1823
  and per-series scope. The playground renderer projects `ctr`, `inEnd`,
1722
1824
  `outEnd`, `inBase` onto clustered column and bar labels — outside-end
1723
1825
  remains the default, but authored positions now move labels inside the
1724
- bar or to the base as PowerPoint shows them.
1826
+ bar or to the base as the reference desktop app shows them.
1725
1827
  - 3cfba8d: feat: chart data label separator. `ChartDataLabels.separator` carries
1726
1828
  the `<c:dLbls><c:separator>…</c:separator>` text used to join
1727
1829
  multiple label parts (value + percent + category etc.). The pie /
@@ -1757,7 +1859,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1757
1859
  `getShapeRunFormat` still returns the literal `<a:rPr>` only.
1758
1860
  - 25654cf: feat: `getShapeEffectsEffective(pres, shape)` walks the layout →
1759
1861
  master placeholder cascade for `<a:effectLst>`. Effect lists override
1760
- rather than compose (matching PowerPoint's behaviour), so the first
1862
+ rather than compose (matching the reference desktop app's behaviour), so the first
1761
1863
  layer that supplies any effects wins. Playground uses it so
1762
1864
  placeholder shadows / glows / soft edges inherited from the master
1763
1865
  finally render on slides that don't repeat the effect list.
@@ -1774,7 +1876,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1774
1876
  shape's `<a:effectLst>` (`outerShdw`, `innerShdw`, `glow`, `reflection`,
1775
1877
  `softEdge`, `blur`) in document order, with each effect's color
1776
1878
  (transform-resolved against the theme), opacity, blur radius, distance,
1777
- and angle. PowerPoint composes multiple effects in a single filter
1879
+ and angle. The reference desktop app composes multiple effects in a single filter
1778
1880
  stack — the existing `getShapeEffect` only surfaced the first one.
1779
1881
 
1780
1882
  The playground renderer now emits an SVG `<filter>` chain that
@@ -1840,7 +1942,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1840
1942
  slide whose `getShapeAnimation` is not `null`. Pair to
1841
1943
  `slideHasAnimations`. Useful for "which shapes on this slide actually
1842
1944
  animate?" audits before exporting to a video pipeline that doesn't
1843
- honor PowerPoint's timing tree.
1945
+ honor the reference desktop app's timing tree.
1844
1946
  - 87d7fbb: feat: `findShapesWithHyperlinks(slide)` — every shape on the slide
1845
1947
  that carries any hyperlink, regardless of target. Counterpart to
1846
1948
  `findShapesByHyperlink(slide, url)` (which requires a matching URL)
@@ -1854,7 +1956,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1854
1956
  `'/ppt/slideLayouts/slideLayout3.xml'`). Pair to the existing
1855
1957
  `findSlidesByLayoutName` / `findSlidesByLayoutType`. Keyed on the
1856
1958
  actual package path, so it's stable across template-name collisions
1857
- and PowerPoint UI locales.
1959
+ and the reference desktop app's UI locales.
1858
1960
  - 20613b5: feat: `findSlidesWithChartKind(pres, kind)` — kind-filtered variant of
1859
1961
  the existing `getSlidesWithCharts`. Returns every slide carrying at
1860
1962
  least one chart of the given `ChartKind` (`'bar'`, `'column'`,
@@ -1909,7 +2011,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1909
2011
  - b793c74: feat: `getSlideLayoutUsageCountsByType(pres)` — companion to
1910
2012
  `getSlideLayoutUsageCounts`, but keyed on the OOXML layout-type enum
1911
2013
  token (`title`, `obj`, `twoObj`, `blank`, …) instead of the user-
1912
- visible name. Stable across PowerPoint UI locales. Useful for "how
2014
+ visible name. Stable across the reference desktop app's UI locales. Useful for "how
1913
2015
  many content slides vs. dividers vs. title slides?" audits.
1914
2016
  - 3891fa2: feat: `getSlideLayoutUsageCounts(pres)` — layout name → number-of-slides
1915
2017
  histogram. Every layout enumerated by `getSlideLayouts` appears as a
@@ -1941,7 +2043,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1941
2043
 
1942
2044
  The playground renderer emits an SVG `<radialGradient>` for the
1943
2045
  non-linear paths, with reversed stop offsets so the first ECMA-376
1944
- stop sits at the focus center (matching PowerPoint's outward
2046
+ stop sits at the focus center (matching the reference desktop app's outward
1945
2047
  painting order).
1946
2048
 
1947
2049
  - 855076d: feat: chart value-axis major gridlines honor authored stroke color.
@@ -1953,17 +2055,17 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1953
2055
  - 74b227e: feat(site/playground): hyperlink tooltips. Shape and per-run
1954
2056
  hyperlinks now surface their `<a:hlinkClick tooltip="…"/>` text —
1955
2057
  shapes get an SVG `<title>` child on the `<a>` wrapper, runs get a
1956
- `title=` attribute on the HTML anchor. PowerPoint shows these on
2058
+ `title=` attribute on the HTML anchor. The reference desktop app shows these on
1957
2059
  hover during the slideshow; the playground now does too.
1958
2060
  - a610e82: feat: `getShapeHyperlinkTooltip(shape)` and
1959
2061
  `getShapeRunHyperlinkTooltip(shape, p, r)` return the
1960
- `<a:hlinkClick tooltip="…"/>` text. Tooltips show up in PowerPoint
2062
+ `<a:hlinkClick tooltip="…"/>` text. Tooltips show up in the reference desktop app
1961
2063
  when the user hovers a linked shape in slide-show mode — useful for
1962
2064
  accessibility and link-preview surfaces.
1963
2065
  - cbdda7c: feat(site/playground): render `<a:duotone>` image recolor. The filter
1964
2066
  pipeline desaturates the picture to luminance, then samples a
1965
2067
  two-color gradient (firstColor → secondColor) via a 16-step
1966
- `feComponentTransfer` table. Pictures with PowerPoint's Color >
2068
+ `feComponentTransfer` table. Pictures with the reference desktop app's Color >
1967
2069
  Recolor preset finally render in their authored two-color tint.
1968
2070
  - c4a89c1: feat: `getShapeImageDuotone(pres, shape)` reads the picture's
1969
2071
  `<a:blip><a:duotone>` two-color recolor effect — the typical
@@ -1991,7 +2093,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1991
2093
  threshold) when `<a:blip><a:biLevel thresh="…"/>` is set
1992
2094
 
1993
2095
  Pictures with Color > Grayscale or Color > Black and White now
1994
- render with the same visual treatment PowerPoint shows.
2096
+ render with the same visual treatment the reference desktop app shows.
1995
2097
 
1996
2098
  - 66edcbc: feat: add `isShapeTextBox(shape)` — `true` when a shape is a text box
1997
2099
  (`<p:cNvSpPr txBox="1">`) rather than an autoshape. The two have different
@@ -2031,7 +2133,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
2031
2133
  the data points. Bar / column / pie keep the square swatch.
2032
2134
  - b1073ff: feat(site/playground): right / left chart legend stack centers
2033
2135
  vertically. Previously the `r` and `l` legend positions both
2034
- stacked from a fixed `f.y + 12` top, the same as `tr`. PowerPoint
2136
+ stacked from a fixed `f.y + 12` top, the same as `tr`. The reference desktop app
2035
2137
  vertically-centers right / left legends inside the chart area; the
2036
2138
  renderer now matches by computing `yStart` from the legend's total
2037
2139
  height. `tr` keeps the top-anchored stack.
@@ -2123,7 +2225,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
2123
2225
  (`<a:lumOff>`), contrast (`<a:lumMod>`), and opacity (`<a:alphaModFix>`).
2124
2226
 
2125
2227
  Crops project to an enlarged `<image>` element clipped to the shape's
2126
- bounds (matching PowerPoint's "Crop" tool). Brightness + contrast
2228
+ bounds (matching the reference desktop app's "Crop" tool). Brightness + contrast
2127
2229
  compose into an SVG `<feComponentTransfer>` filter. Opacity drives
2128
2230
  the `opacity` attribute directly.
2129
2231
 
@@ -2137,7 +2239,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
2137
2239
  exposes the per-data-point pull-out percentage from `<c:dPt><c:explosion val="N"/>`,
2138
2240
  and the playground renderer offsets exploded slices (and their labels)
2139
2241
  outward along the slice mid-angle. Matches the "pulled-out" pie look
2140
- authors get from Excel's "Vary colors by point" toggle.
2242
+ authors get from the "Vary colors by point" toggle in spreadsheet apps.
2141
2243
  - 2e9776d: feat(site/playground): chart / media count badges on each slide.
2142
2244
  `getSlideCharts(slide)` and `getSlideMediaPartNames(pres, slide)`
2143
2245
  power two new badges (`N chart`, `N media`) showing how many chart
@@ -2146,7 +2248,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
2146
2248
  - 997d507: feat(site/playground): comment badge tooltip carries the comment
2147
2249
  texts. The `N cmt` badge's `title=` attribute now joins each
2148
2250
  comment's body text so hovering surfaces the review remarks
2149
- without opening PowerPoint.
2251
+ without opening the reference desktop app.
2150
2252
  - 3ede588: feat(site/playground): additional slide badges — `hidden` (when
2151
2253
  `show="0"`) and `N cmt` (count of authored review comments). Threads
2152
2254
  `isSlideHidden` and `getSlideComments` through the slide-snapshot
@@ -2161,7 +2263,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
2161
2263
  `twoObj`, `blank`, …) as a badge next to the slide title. Reads
2162
2264
  `<p:sldLayout type="…">` via `getSlideLayout` + `getSlideLayoutType`
2163
2265
  so deck audits can spot which layout each slide is bound to without
2164
- opening PowerPoint.
2266
+ opening the reference desktop app.
2165
2267
  - 5861d1e: feat(site/playground): include slide-master count in the
2166
2268
  "masters · layouts · sections" meta cell. `getPresentationSummary`
2167
2269
  already returned layout / section counts; the playground now also
@@ -2186,7 +2288,7 @@ href="#slide-N">` link, so users can right-click → "Copy link
2186
2288
  - ffec23d: feat(site/playground): show speaker notes under each slide. The
2187
2289
  playground now calls `getSlideNotes` for every slide and renders a
2188
2290
  collapsible `<details>` block when notes exist, so users can
2189
- inspect the deck author's notes without opening PowerPoint.
2291
+ inspect the deck author's notes without opening the reference desktop app.
2190
2292
  - b90f1bc: feat(site/playground): show `validatePresentation` results. The
2191
2293
  playground now runs the validator after parsing and surfaces any
2192
2294
  issues in a dedicated panel (with severity tint and the offending
@@ -2258,7 +2360,7 @@ href="#slide-N">` link, so users can right-click → "Copy link
2258
2360
  - a65c05c: feat: `setShapeTextColumns(shape, { count, gapEmu? } | null)` — multi-
2259
2361
  column writer pairing the existing `getShapeTextColumns` reader. Writes
2260
2362
  `<a:bodyPr numCol="N" [spcCol="EMU"]/>`. Passing `null` clears both
2261
- attributes so the text body falls back to PowerPoint's default single
2363
+ attributes so the text body falls back to the reference desktop app's default single
2262
2364
  column. `count` must be `>= 2` (single column is the default — pass
2263
2365
  `null` instead); the function throws otherwise.
2264
2366
  - fea7725: feat: `setShapeTextDirection(shape, direction | null)` — companion
@@ -2274,7 +2376,7 @@ href="#slide-N">` link, so users can right-click → "Copy link
2274
2376
  `top`/`center`/`bottom` to the schema's `t`/`ctr`/`b` values and clears
2275
2377
  the attribute on `null`. The margins setter writes per-side EMU on
2276
2378
  `marL`/`marR`/`marT`/`marB`; sides set to `null`/`undefined` are
2277
- stripped (PowerPoint falls back to its defaults); passing the whole
2379
+ stripped (the reference desktop app falls back to its defaults); passing the whole
2278
2380
  arg as `null` clears every side. Both create `<a:tcPr>` if absent.
2279
2381
  - 3921802: feat: `setTableCellBorders(cell, sides | null)` — partial-update writer
2280
2382
  for all 6 cell-border slots (`left`, `right`, `top`, `bottom` + the
@@ -2297,32 +2399,32 @@ href="#slide-N">` link, so users can right-click → "Copy link
2297
2399
  `firstCol`, `lastCol`, `bandRow`, `bandCol`). Pairs the existing
2298
2400
  `getTableStyleFlags` reader. Only the keys present in `flags` are
2299
2401
  touched — omitted keys keep their current state. A flag set to `false`
2300
- strips the attribute (matching how PowerPoint round-trips defaults).
2402
+ strips the attribute (matching how the reference desktop app round-trips defaults).
2301
2403
  Creates `<a:tblPr>` if absent. Throws when the shape isn't a table
2302
2404
  graphic frame.
2303
2405
  - 1ea509b: feat: `setTableStyleId(table, styleId | null)` — writer for
2304
2406
  `<a:tbl><a:tblPr><a:tableStyleId>`. Pairs the existing `getTableStyleId`
2305
2407
  reader. Pass the curly-braced GUID (e.g.
2306
- `'{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}'` for PowerPoint's "Medium
2408
+ `'{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}'` for the reference desktop app's "Medium
2307
2409
  Style 2 - Accent 1") or `null` to remove the reference so the table
2308
2410
  uses the slide's default style. Creates `<a:tblPr>` if absent. Throws
2309
2411
  when the shape isn't a table graphic frame.
2310
2412
  - 2438696: feat(site/playground): shape `aria-label` from authored alt text.
2311
2413
  Each rendered shape with a non-empty alt title (or, as fallback,
2312
2414
  alt description) now exposes `role="img" aria-label="…"` on the
2313
- root `<g>`. Screen readers announce decks the same way PowerPoint's
2415
+ root `<g>`. Screen readers announce decks the same way the reference desktop app's
2314
2416
  Accessibility Inspector reports them, without affecting visuals.
2315
2417
  - b8e24d6: feat(site/playground): each shape's authored name surfaces as a
2316
2418
  `data-pptx-shape-name` attribute on its root `<g>` element. Lets
2317
2419
  DevTools, a11y inspectors, or test selectors target shapes by their
2318
- PowerPoint name without parsing SVG geometry. Cheap to emit and has
2420
+ visible name without parsing SVG geometry. Cheap to emit and has
2319
2421
  no visual impact.
2320
2422
  - fdd4770: feat: `getShapeTextBodyRotationDeg(shape)` returns the shape's text-body
2321
2423
  rotation from `<a:bodyPr rot="N"/>` (where N is in 60000ths of a
2322
2424
  degree). Distinct from the shape's geometry rotation (`<p:xfrm rot>`):
2323
2425
  this rotates the text body _inside_ the shape without rotating the
2324
2426
  geometry. The playground renderer pivots the text body around the
2325
- inset midpoint when the angle is non-zero, matching PowerPoint's
2427
+ inset midpoint when the angle is non-zero, matching the reference desktop app's
2326
2428
  behaviour for vertical-label callouts and rotated text frames.
2327
2429
  - 263bf52: feat: `getSlideBackgroundGradientFill(slide)` returns the gradient
2328
2430
  stops + path for slides with a `<p:bgPr><a:gradFill>` background.
@@ -2345,7 +2447,7 @@ href="#slide-N">` link, so users can right-click → "Copy link
2345
2447
  `getPresentationSummary().hasAnimations`. The site playground uses
2346
2448
  it (plus `getSlideTransition`) to show small `anim` / `trans`
2347
2449
  badges next to each slide title so deck audits don't need to open
2348
- PowerPoint.
2450
+ the reference desktop app.
2349
2451
  - c0e0dc2: feat(site/playground): shapes with slide-jump click actions
2350
2452
  (`<a:hlinkClick action="ppaction://hlinksldjump"/>`) render as
2351
2453
  in-page hash anchors. The renderer resolves the target via
@@ -2370,7 +2472,7 @@ href="#slide-N">` link, so users can right-click → "Copy link
2370
2472
  caps, miter vs bevel joins, and per-end arrow heads.
2371
2473
 
2372
2474
  The playground composes `stroke-dasharray` from the preset dash
2373
- patterns (cadence multiplied by stroke width as PowerPoint does),
2475
+ patterns (cadence multiplied by stroke width as the reference desktop app does),
2374
2476
  emits SVG `<marker>` defs for triangle / stealth / diamond / oval
2375
2477
  arrowheads on connectors and shapes, and maps cap / join through.
2376
2478
 
@@ -2388,11 +2490,11 @@ href="#slide-N">` link, so users can right-click → "Copy link
2388
2490
  marL/marR/marT/marB>` insets. The renderer previously hard-coded a
2389
2491
  4-pixel pad on every side; it now converts each EMU-valued margin to
2390
2492
  px (falling back to 4px only when the side isn't authored) so cells
2391
- with custom inner padding line up the way PowerPoint shows them.
2493
+ with custom inner padding line up the way the reference desktop app shows them.
2392
2494
  - 42cf575: feat: `getTableCellMargins(cell)` returns the cell's `<a:tcPr marL
2393
2495
  marR marT marB>` inset margins in EMU. Each side is `null` when the
2394
2496
  cell doesn't author it, so renderers know to fall back to
2395
- PowerPoint's defaults (91440 EMU / 0.1 in horizontal, 45720 EMU /
2497
+ the reference desktop app's defaults (91440 EMU / 0.1 in horizontal, 45720 EMU /
2396
2498
  0.05 in vertical).
2397
2499
  - ba94f5e: feat: `getTableCellParagraphs(cell)` returns a table cell's text as structured
2398
2500
  paragraphs — each carrying its alignment and per-run format (`size`, `bold`,
@@ -2422,9 +2524,9 @@ marR marT marB>` inset margins in EMU. Each side is `null` when the
2422
2524
  (accent1 for header / footer rows, 92%-white-mixed accent for bands)
2423
2525
  when the cell doesn't supply an explicit fill of its own. Header text
2424
2526
  rendered on the accent gets white text instead of the default body
2425
- color, matching PowerPoint's built-in table styles.
2527
+ color, matching the reference desktop app's built-in table styles.
2426
2528
  - 243e731: feat: `getTableStyleId(table)` returns the GUID string inside
2427
- `<a:tbl><a:tblPr><a:tableStyleId>`. PowerPoint references built-in
2529
+ `<a:tbl><a:tblPr><a:tableStyleId>`. The reference desktop app references built-in
2428
2530
  table styles (`{5C22544A-…}` = Medium Style 2 - Accent 1, etc.) and
2429
2531
  theme-local styles by GUID. Returns `null` when the table doesn't
2430
2532
  author one.
@@ -2468,7 +2570,7 @@ layout)` — the non-placeholder decorative shapes (corner bars, divider lines,
2468
2570
  `writing-mode` / `text-orientation` declaration so Asian and
2469
2571
  Mongolian-style vertical text renders without manual transforms.
2470
2572
  - Playground wraps shapes carrying a `<a:hlinkClick>` in an SVG `<a>`
2471
- element so the preview is clickable — matches PowerPoint's
2573
+ element so the preview is clickable — matches the reference desktop app's
2472
2574
  slide-show behaviour for shape-level hyperlinks.
2473
2575
  - Group shape rendering now applies the group's own `<a:xfrm rot
2474
2576
  flipH flipV>` to the whole subtree before the scale + translate
@@ -2479,7 +2581,7 @@ flipH flipV>` to the whole subtree before the scale + translate
2479
2581
  extrapolation past the last / before the first data point. The
2480
2582
  playground renderer projects the linear fit further along the x-axis
2481
2583
  by `N * step` so projected-future trendlines render the way
2482
- PowerPoint shows them. Moving-average / log / poly trendlines keep
2584
+ the reference desktop app shows them. Moving-average / log / poly trendlines keep
2483
2585
  their data-range output since extrapolation isn't meaningful for
2484
2586
  them.
2485
2587
  - 57117a7: feat: chart value-axis tick labels honor `<c:valAx><c:txPr><a:bodyPr
@@ -2490,7 +2592,7 @@ rot="N"/>`. `ChartSpec.valueAxisLabelRotationDeg` returns the rotation
2490
2592
  `categoryAxisLabelRotationDeg` we already projected.
2491
2593
  - 3e1c8a1: feat: chart value-axis exposes `<c:scaling><c:logBase val="N"/>`.
2492
2594
  `ChartAxisScaling.logBase` carries the authored log base (commonly
2493
- `2`, `10`, or `Math.E`). The reader clamps to PowerPoint's `[2, 1000]`
2595
+ `2`, `10`, or `Math.E`). The reader clamps to the reference desktop app's `[2, 1000]`
2494
2596
  range. Callers that round-trip charts now preserve the log-scale
2495
2597
  flag; the playground renderer still draws linear (log-scale
2496
2598
  projection is a follow-up — exposing the field unblocks it).
@@ -2518,7 +2620,7 @@ rot="N"/>`. `ChartSpec.valueAxisLabelRotationDeg` returns the rotation
2518
2620
  size (consumers apply the ~18pt text-box default) instead of wrongly picking up
2519
2621
  the master body size (often much larger). Real placeholders — including ones
2520
2622
  whose `<p:ph>` omits a `type` — still inherit as before. This makes effective
2521
- text formatting match what PowerPoint and LibreOffice render for text boxes.
2623
+ text formatting match what the reference desktop app and LibreOffice render for text boxes.
2522
2624
  - cfe8b69: fix: placeholder inheritance now applies the OOXML `ctrTitle`↔`title` and
2523
2625
  `subTitle`→`body` type equivalence. A `ctrTitle` (centered title) now inherits
2524
2626
  its layout/master `title` placeholder's `bodyPr` (e.g. `anchor="ctr"`),
@@ -2528,7 +2630,7 @@ rot="N"/>`. `ChartSpec.valueAxisLabelRotationDeg` returns the rotation
2528
2630
  centered titles and subtitles.
2529
2631
  - 610ecac: fix(validator): `validatePresentation` now flags duplicate
2530
2632
  `<p:cNvPr id="N">` values inside a single slide's `<p:spTree>` as
2531
- errors. PowerPoint requires every shape's non-visual ID to be unique
2633
+ errors. The reference desktop app requires every shape's non-visual ID to be unique
2532
2634
  within its slide; duplicates often appear after pasting shapes from
2533
2635
  another slide without re-allocating IDs. The walk recurses into
2534
2636
  `<p:grpSp>` so duplicates nested in groups are also caught.
@@ -2541,8 +2643,8 @@ rot="N"/>`. `ChartSpec.valueAxisLabelRotationDeg` returns the rotation
2541
2643
 
2542
2644
  **What works at 1.0:**
2543
2645
 
2544
- - **Read** any `.pptx` produced by PowerPoint, Keynote, Google Slides, or
2545
- LibreOffice Impress, and save it back without corruption. Unknown
2646
+ - **Read** any `.pptx` produced by Keynote, Google Slides, LibreOffice Impress or
2647
+ other common presentation apps, and save it back without corruption. Unknown
2546
2648
  extensions are preserved verbatim on round-trip.
2547
2649
  - **Template editing**: token / text replace across slides and speaker
2548
2650
  notes, image swap with geometry preserved, slide CRUD with placeholder