@office-kit/pptx 0.22.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,5 +1,122 @@
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
+
105
+ ## 0.23.0
106
+
107
+ ### Minor Changes
108
+
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.
110
+
111
+ - `@office-kit/pptx`: new `getPresetGeometry(preset, size, adjustValues?)` evaluates any preset's paths and text rectangle in the same form as `getShapeCustomGeometry`.
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`.
113
+
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.
115
+
116
+ ### Patch Changes
117
+
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.
119
+
3
120
  ## 0.22.0
4
121
 
5
122
  ### Minor Changes
@@ -35,9 +152,9 @@
35
152
 
36
153
  Fixes: an exit fade hid its shape the moment it started instead of fading it
37
154
  out. The `<p:set>` that takes the shape off the slide now trails the motion the
38
- 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.
39
156
 
40
- - 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.
41
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.
42
159
 
43
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.
@@ -45,8 +162,8 @@
45
162
  Existing calls are unaffected: the defaults still write the click-triggered, zero-delay tree they wrote before, byte for byte.
46
163
 
47
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.
48
- - 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.
49
- - 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.
50
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.
51
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.
52
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.
@@ -74,11 +191,11 @@
74
191
 
75
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.
76
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.
77
- - 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.
78
195
 
79
196
  Preview integrations can use `shapeTextAnchorOffset` to position editable text consistently with the rendered text block.
80
197
 
81
- - 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
82
199
  character format.
83
200
 
84
201
  `TextFormat` gained `outline`, `shadow` and `glow`, so every writer that takes
@@ -101,14 +218,14 @@
101
218
 
102
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.
103
220
 
104
- - 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.
105
222
 
106
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.
107
224
 
108
225
  - e18d19d: `setShapeShadow` and `setShapeGlow` no longer erase each other. Each now
109
226
  replaces only the effect of its own kind and leaves the rest of the shape's
110
227
  `<a:effectLst>` in place, written in the order `CT_EffectList` states — so a
111
- 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
112
229
  them. Setting the same effect twice still replaces it, because the schema
113
230
  allows each one only once. `clearShapeEffects` remains the way to empty the
114
231
  list.
@@ -116,7 +233,7 @@
116
233
  `getShapePatternFill` now reports `preset` as the `PatternPreset` union rather
117
234
  than a bare `string`, so what it reads can be handed straight back to
118
235
  `setShapePatternFill`. An unrecognised `prst` in the file reads as `'pct50'`,
119
- which is what PowerPoint paints when the attribute is absent.
236
+ which is what the reference desktop app paints when the attribute is absent.
120
237
 
121
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.
122
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.
@@ -154,23 +271,23 @@
154
271
 
155
272
  Fix Increase/Decrease Font Size leaving empty paragraphs unchanged when formatting an entire text box or table cell.
156
273
 
157
- - 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.
158
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.
159
276
  - e18d19d: Read and update slide show mode, slide range, looping, narration, animation, and timing settings while preserving other presentation properties.
160
- - 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.
161
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.
162
279
 
163
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.
164
281
 
165
- - 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.
166
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.
167
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.
168
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.
169
- - 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.
170
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.
171
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.
172
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.
173
- - 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.
174
291
  - e18d19d: Edit a slide layout, not just apply one: `setSlideLayoutName`,
175
292
  `setSlideLayoutBackground`, `clearSlideLayoutBackground` and
176
293
  `setSlideLayoutPlaceholderBounds`.
@@ -188,18 +305,18 @@
188
305
  Design ▸ Layout ribbon group, in English and Japanese.
189
306
 
190
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.
191
- - e18d19d: Add PowerPoint link destinations for the last slide viewed and ending the slide show.
192
- - 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.
193
310
  - e18d19d: Add read and write support for named bookmarks in embedded media playback.
194
311
  - e18d19d: Say how a clip plays: `getShapeMediaPlayback` and `setShapeMediaPlayback`.
195
312
 
196
313
  A deck could embed a video or a sound but not state anything about playing it,
197
- 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
198
315
  reads and writes autoplay, loop, volume, mute, hide-when-stopped and (video
199
316
  only) full screen, from the clip's media time node. Omitted properties keep
200
317
  their current value.
201
318
 
202
- 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
203
320
  extension rather than in the core schema.
204
321
 
205
322
  The editor exposes the settings through its properties panel and command
@@ -207,7 +324,7 @@
207
324
 
208
325
  - e18d19d: Read and edit the OOXML `numSld` setting for audio and video playback across slides.
209
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.
210
- - 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,
211
328
  not merely carried along. Those decks keep their comments in a different format
212
329
  from the one ECMA-376 defines ([MS-PPTX] §2.16.1): a thread owns its replies
213
330
  instead of the replies pointing back at a parent, the text is a DrawingML body
@@ -240,12 +357,12 @@
240
357
 
241
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.
242
359
 
243
- - e18d19d: Preserve shadow alignment and rotation when reading and editing PowerPoint text. Shadow formatting now accepts `alignment` and `rotateWithShape`, including native WordArt anchors.
244
- - 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.
245
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.
246
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.
247
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.
248
- - 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.
249
366
 
250
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.
251
368
 
@@ -265,7 +382,7 @@
265
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.
266
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.
267
384
 
268
- 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.
269
386
 
270
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.
271
388
 
@@ -287,7 +404,7 @@
287
404
 
288
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.
289
406
 
290
- - 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.
291
408
 
292
409
  Allow `setShapeHidden` to update multiple shapes in one call while preserving animation data.
293
410
 
@@ -338,7 +455,7 @@
338
455
  space — restoring it would either tear the shape out of the arrangement it was
339
456
  grouped into, or invent a rectangle the layout never described.
340
457
 
341
- - 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.
342
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.
343
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.
344
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.
@@ -348,9 +465,9 @@
348
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.
349
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.
350
467
 
351
- 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.
352
469
 
353
- - 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.
354
471
 
355
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.
356
473
 
@@ -363,7 +480,7 @@
363
480
  - e18d19d: Slide numbers, as live fields rather than typed text.
364
481
 
365
482
  `setShapeTextField(shape, type, { text })` writes an `<a:fld>` — the slide's
366
- 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
367
484
  writes one, and carrying the replaced text's formatting onto the field.
368
485
  `addSlidePlaceholder(slide, type)` restores a single slot the layout reserves
369
486
  (`sldNum`, `dt`, `ftr`, …), where `addMissingSlidePlaceholders` restores them
@@ -388,17 +505,17 @@ firstSlideNum>`.
388
505
 
389
506
  Keep Home ribbon controls accessible without horizontal scrolling at intermediate window widths.
390
507
 
391
- - 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.
392
509
 
393
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.
394
- - 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`).
395
512
  - `setShapeTextAutoFit` now places its element ahead of any `<a:scene3d>` / `<a:sp3d>`, as the schema requires.
396
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.
397
514
 
398
- - 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).
399
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.
400
517
  - e18d19d: Support gradient and pattern fills on formatted text runs through `textFill`,
401
- including theme color transforms and round-tripping native WordArt fills.
518
+ including theme color transforms and round-tripping native text-art fills.
402
519
  The existing `color` property remains the solid text color shorthand; passing
403
520
  both `color` and `textFill` is rejected.
404
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.
@@ -411,8 +528,8 @@ firstSlideNum>`.
411
528
 
412
529
  Resolve inherited shape and table text colors through the slide color map, including detached editing previews.
413
530
 
414
- - 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.
415
- - 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.
416
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.
417
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.
418
535
 
@@ -425,7 +542,7 @@ firstSlideNum>`.
425
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.
426
543
  - e18d19d: Read percent-form bullet sizes at their intended scale instead of rendering the list marker a thousand times too small.
427
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.
428
- - 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.
429
546
  - e18d19d: Fix reading and rendering of DrawingML preset colors such as `red`, including
430
547
  colors used by shape fills and text after a presentation is saved and reopened.
431
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.
@@ -442,12 +559,12 @@ firstSlideNum>`.
442
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.
443
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.
444
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.
445
- - 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.
446
- - 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.
447
- - 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.
448
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.
449
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.
450
- - 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.
451
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.
452
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.
453
570
  - e18d19d: Keep nested audio and video playback settings when clearing a slide's animations, preserving their enclosing timing conditions.
@@ -455,13 +572,13 @@ firstSlideNum>`.
455
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.
456
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.
457
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.
458
- - 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.
459
576
  - e18d19d: Read scRGB and HSL colors in imported fills, strokes, and gradient stops.
460
577
  - e18d19d: Resolve scRGB and HSL color elements used by shape shadows and glow effects when reading imported presentations.
461
578
 
462
579
  Preserve opacity modifiers and offsets on imported effects, including percent-form shadow opacity.
463
580
 
464
- - 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.
465
582
  - e18d19d: Slide background readers now resolve imported DrawingML preset and system colors instead of treating them as an empty solid fill.
466
583
  - e18d19d: Preserve the original outline after rejecting invalid width or opacity values, including when a later edit saves the shape.
467
584
  - e18d19d: Resolve DrawingML percentage RGB and HSL colors when reading imported presentations.
@@ -479,7 +596,7 @@ firstSlideNum>`.
479
596
  - e18d19d: fix: setShapeText / appendShapeText now add text to a shape that has no text body
480
597
 
481
598
  Previously, setting text on a shape authored without one (e.g. `addSlideShape`
482
- 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
483
600
  gives an autoshape a text body so you can click in and type, so these functions
484
601
  now create the body on demand and populate it, matching that behavior. Picture /
485
602
  table shapes still throw, since they are not text-bearing.
@@ -489,9 +606,9 @@ firstSlideNum>`.
489
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.
490
607
  - e18d19d: Preserve explicit cell-side borders in banded table styles, including interior cells, while retaining interior borders when a side is unspecified.
491
608
  - e18d19d: Read small and percent-suffixed text baseline offsets correctly so imported superscript and subscript positions retain their intended values.
492
- - 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.
493
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.
494
- - 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.
495
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.
496
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.
497
614
 
@@ -547,7 +664,7 @@ firstSlideNum>`.
547
664
 
548
665
  ### Patch Changes
549
666
 
550
- - 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`.
551
668
 
552
669
  ## 0.18.4
553
670
 
@@ -592,7 +709,7 @@ firstSlideNum>`.
592
709
  ### Minor Changes
593
710
 
594
711
  - 7e89e62: Validate enum inputs at authoring boundaries and throw a descriptive `RangeError`
595
- 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.
596
713
 
597
714
  Affected APIs:
598
715
 
@@ -647,7 +764,7 @@ firstSlideNum>`.
647
764
  - Per series: `errorBars` / `xErrorBars` (fixed, percentage, standard deviation, standard error, custom), `fillOpacity`.
648
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`.
649
766
  - Data labels gain `showBubbleSize`, `showLegendKey`, `fillColor`, and per-point `text` (a literal label, e.g. naming one scatter point).
650
- - 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.
651
768
 
652
769
  Behavior changes when reading existing decks:
653
770
 
@@ -663,12 +780,12 @@ firstSlideNum>`.
663
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.
664
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.
665
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.
666
- - 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.
667
- - `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.
668
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.
669
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.
670
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.
671
- - 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.
672
789
  - `validatePresentation` reports a video / audio relationship whose part is missing, and a media time node whose shape is no longer on the slide.
673
790
 
674
791
  ## 0.16.1
@@ -685,12 +802,12 @@ firstSlideNum>`.
685
802
 
686
803
  ### Minor Changes
687
804
 
688
- - 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
689
806
 
690
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`.
691
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.
692
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>`.
693
- - `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.
694
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>`).
695
812
 
696
813
  ## 0.15.1
@@ -722,13 +839,13 @@ firstSlideNum>`.
722
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).
723
840
  - `ChartSpec.valueAxisTickLabelPos` positions the primary value-axis tick labels (`none` / `low` / `high` / `nextTo`), mirroring `categoryAxisTickLabelPos`.
724
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.
725
- - `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.
726
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.
727
- - 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.
728
845
  - `ChartDataLabels.showLeaderLines` writes and reads `<c:showLeaderLines>` on series- and chart-level labels (per-point overrides have no such setting).
729
- - 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.
730
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`).
731
- - 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.
732
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.
733
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.
734
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.
@@ -759,7 +876,7 @@ firstSlideNum>`.
759
876
  `ChartSeries` gains `chartKind` (`'bar' | 'column' | 'line' | 'area'`) to
760
877
  overlay e.g. a line series on a column chart, and `secondaryAxis: true` to
761
878
  plot a series against a right-hand secondary value axis — the standard
762
- 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).
763
880
  The builder splits series into plot groups (`<c:barChart>` + `<c:lineChart>`
764
881
  …) and emits the secondary `<c:valAx>`/`<c:catAx>` pair on demand;
765
882
  `getShapeChartSpec` round-trips both fields. The preview renderer paints
@@ -810,7 +927,7 @@ firstSlideNum>`.
810
927
 
811
928
  - eeb8659: Validate authoring inputs at the API boundary so out-of-range values throw a
812
929
  clear `RangeError` instead of silently emitting a schema-invalid `.pptx` that
813
- PowerPoint marks corrupt and "repairs".
930
+ the reference desktop app marks corrupt and "repairs".
814
931
 
815
932
  A generative schema-validation sweep surfaced a whole class of defects where a
816
933
  caller-supplied number/string was serialized straight into a constrained
@@ -904,7 +1021,7 @@ firstSlideNum>`.
904
1021
  example.
905
1022
 
906
1023
  - eeb8659: Close a final batch of correctness defects a generative schema sweep surfaced,
907
- where the writer emitted a `.pptx` PowerPoint marks corrupt:
1024
+ where the writer emitted a `.pptx` the reference desktop app marks corrupt:
908
1025
 
909
1026
  - **XML-illegal control characters** in any text field (shape text, table cells,
910
1027
  notes, chart titles/categories/series, hyperlink tooltip/URL, section names,
@@ -937,7 +1054,7 @@ firstSlideNum>`.
937
1054
  ### Patch Changes
938
1055
 
939
1056
  - e9eae5c: Fix `<a:tint>` / `<a:shade>` colour resolution to compute in linear-light RGB,
940
- 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
941
1058
  grey (~#8B8B8B) instead of the too-dark #404040, so colours derived from theme
942
1059
  scheme transforms (subtitle placeholders, table banding, chart fills) render at
943
1060
  the right lightness.
@@ -955,9 +1072,9 @@ firstSlideNum>`.
955
1072
  `setShapeBullets('number')` / `setParagraphBullet(..., 'number')` emitted only
956
1073
  `<a:buAutoNum>`, with no `<a:buFont>` — so the auto-number glyph fell through to
957
1074
  whatever font happened to apply, instead of the theme's major font that
958
- PowerPoint and PptxGenJS use. Numbered lists now emit
1075
+ the reference desktop app and PptxGenJS use. Numbered lists now emit
959
1076
  `<a:buFont typeface="+mj-lt"/>` ahead of the number and write the default
960
- `startAt="1"` explicitly, matching PowerPoint-authored output.
1077
+ `startAt="1"` explicitly, matching desktop-app-authored output.
961
1078
 
962
1079
  ## 0.7.0
963
1080
 
@@ -969,14 +1086,14 @@ firstSlideNum>`.
969
1086
 
970
1087
  ### Patch Changes
971
1088
 
972
- - 099d77b: Emit PowerPoint's default cell insets on table cells
1089
+ - 099d77b: Emit the reference desktop app's default cell insets on table cells
973
1090
 
974
- `addSlideTable` cells now carry the explicit default insets PowerPoint and
1091
+ `addSlideTable` cells now carry the explicit default insets the reference desktop app and
975
1092
  PptxGenJS both write — `<a:tcPr marL="91440" marR="91440" marT="45720"
976
1093
  marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
977
1094
  suppresses any inherited list bullet on the cell paragraph. The table renders
978
- identically (these match the values PowerPoint applies when they're absent),
979
- 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
980
1097
  PptxGenJS-authored table byte-for-byte at the cell level.
981
1098
 
982
1099
  Note: `getTableCellMargins` now returns the explicit `91440 / 45720` defaults
@@ -992,11 +1109,11 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
992
1109
  `setParagraphBullet` added the bullet glyph but no hanging indent, so a bullet
993
1110
  authored on a text box (which inherits the master's `otherStyle`, marL=0, not
994
1111
  the body style) rendered with the glyph jammed against the text. They now
995
- write PowerPoint's per-level default `marL` / `indent` (unless the caller set
996
- 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.
997
1114
  - **Charts with multi-level category references now read back.** The chart
998
1115
  reader handled `<c:strRef>` / `<c:strLit>` categories but not
999
- `<c:multiLvlStrRef>`, which is what PowerPoint and PptxGenJS emit — so
1116
+ `<c:multiLvlStrRef>`, which is what the reference desktop app and PptxGenJS emit — so
1000
1117
  `getShapeChartCategories` (and the full `getShapeChartSpec`) returned an empty
1001
1118
  category list for those charts. It now reads the level's points.
1002
1119
 
@@ -1006,23 +1123,23 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1006
1123
 
1007
1124
  - 333b19f: fix: line-chart series colors now paint the line. The color was written only
1008
1125
  as a bare `<a:solidFill>`, which doesn't color a line series' stroke, so
1009
- 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
1010
1127
  chart authored as accent1–4 rendered blue/red/green/purple instead of the
1011
1128
  requested colors). The color is now also emitted on `<a:ln>`.
1012
1129
  - 665d4c2: Fix unstyled, broken-looking tables from `addSlideTable`
1013
1130
 
1014
1131
  `addSlideTable` set the `firstRow` / `bandRow` flags but never wrote a
1015
1132
  `<a:tableStyleId>`, and `createPresentation` shipped no `tableStyles.xml` part.
1016
- 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,
1017
1134
  unstyled block — a "broken" grid with no rules.
1018
1135
 
1019
- - **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**
1020
1137
  (`{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}`) via `<a:tableStyleId>`, the same
1021
- 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
1022
1139
  ruled grid. Callers can override with the internal `styleId` option (or the
1023
1140
  existing `setTableStyleId`).
1024
1141
  - **`createPresentation` now ships `/ppt/tableStyles.xml`** (referenced from
1025
- `presentation.xml.rels`), matching every PowerPoint-authored deck, so the
1142
+ `presentation.xml.rels`), matching every desktop-app-authored deck, so the
1026
1143
  `tableStyleId` always has a backing part.
1027
1144
 
1028
1145
  ## 0.6.0
@@ -1031,7 +1148,7 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1031
1148
 
1032
1149
  - 0f7c538: Preview: take the default text color from the deck's body style, not the `tx1` token
1033
1150
 
1034
- 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.
1035
1152
 
1036
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.
1037
1154
 
@@ -1039,8 +1156,8 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1039
1156
 
1040
1157
  - 0f7c538: Fix corrupt files from fractional EMU and sideways-spreading stacked bar charts
1041
1158
 
1042
- - **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.
1043
- - **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.
1044
1161
 
1045
1162
  ## 0.5.0
1046
1163
 
@@ -1048,12 +1165,12 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1048
1165
 
1049
1166
  - 4a2ede1: Resolve scheme colors through the slide's color map so inverted-map templates render correctly
1050
1167
 
1051
- 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).
1052
1169
 
1053
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.
1054
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).
1055
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`.
1056
- - **`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.
1057
1174
 
1058
1175
  ## 0.4.0
1059
1176
 
@@ -1065,7 +1182,7 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1065
1182
  legends, and data labels now accept a font face
1066
1183
  (`titleStyle: { font: 'Yu Gothic' }`). The builder writes both
1067
1184
  `<a:latin typeface>` and `<a:ea typeface>` so CJK families render
1068
- correctly in PowerPoint, and `getSlideCharts` / `getShapeChartSpec` read
1185
+ correctly in the reference desktop app, and `getSlideCharts` / `getShapeChartSpec` read
1069
1186
  the face back for round-trips. Works through both `addSlideChart` and
1070
1187
  `setChartSpec`. (The SVG preview keeps its fixed substitution font set —
1071
1188
  authored chart faces affect the emitted PPTX, not the preview raster.)
@@ -1097,7 +1214,7 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1097
1214
  impossible. From-scratch authoring (a headline feature in the README) did
1098
1215
  not actually work without loading a template file.
1099
1216
 
1100
- `createPresentation()` now ships a slide master, the Office theme, and three
1217
+ `createPresentation()` now ships a slide master, a default theme, and three
1101
1218
  layouts — `Blank`, `Title Slide`, and `Title and Content` — so you can go
1102
1219
  straight to `addSlide` / `addTitleSlide` / `addContentSlide` and `savePresentation`.
1103
1220
  Every emitted part is validated against the ECMA-376 XSDs in CI. The slide
@@ -1108,13 +1225,13 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1108
1225
  - `addSlideChart` now rejects a series `color` (and `pointColors` /
1109
1226
  `trendline.color` / plot- and chart-area fills / axis & gridline colors)
1110
1227
  that isn't an sRGB hex (`#RRGGBB` or `RRGGBB`) with a clear error, instead
1111
- of silently emitting an invalid `<a:srgbClr val="…"/>` that PowerPoint
1228
+ of silently emitting an invalid `<a:srgbClr val="…"/>` that the reference desktop app
1112
1229
  dropped or repaired. Bare `RRGGBB` (no `#`) is accepted and normalized;
1113
1230
  scheme tokens like `accent1` are correctly rejected, since charts emit
1114
1231
  `srgbClr`.
1115
1232
  - `addSlideTable` with empty `rows: []` (or a row with no cells) now throws
1116
1233
  an actionable `addSlideTable: …` error at the boundary rather than
1117
- 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.
1118
1235
  (The error message previously named the old internal `addTable` path.)
1119
1236
  - `findSlideLayout`'s case-sensitive, locale-dependent name matching is now
1120
1237
  documented in its JSDoc and the README, pointing readers to the
@@ -1134,7 +1251,7 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1134
1251
  hanging indent through the paragraph cascade (new `bullet` field on
1135
1252
  `ParagraphProperties` from `getParagraphPropertiesEffective`); charts no
1136
1253
  longer invent a legend when the XML authors no `<c:legend>`, and the value
1137
- 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
1138
1255
  preserved; the chart builder writes `<c:smooth val="0"/>` explicitly on line
1139
1256
  series (the schema default for an absent element is smooth=1, which made
1140
1257
  LibreOffice draw unauthored lines as curves); and the pure-SVG text layer is
@@ -1159,7 +1276,7 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1159
1276
  `bulletStyle === 'number'` or `{ autoNum: '…' }` now emit the next
1160
1277
  number in sequence (1., 2., 3., …; A., B., C., …; i., ii., iii., …)
1161
1278
  rather than a generic dot. Counter resets on a non-numbered paragraph
1162
- or a level change, matching PowerPoint's behaviour.
1279
+ or a level change, matching the reference desktop app's behaviour.
1163
1280
 
1164
1281
  Covers the common `ST_TextAutoNumberScheme` tokens — arabicPeriod /
1165
1282
  ParenR / ParenBoth, romanUc / Lc with Period / ParenR / ParenBoth,
@@ -1175,7 +1292,7 @@ marB="45720">` — plus a `<a:pPr marL="0" indent="0"><a:buNone/></a:pPr>` that
1175
1292
  and `categoryAxisMajorTickMark` carry `<c:majorTickMark val="in|out|
1176
1293
  cross|none"/>`. The playground value-axis renderer draws short stubs
1177
1294
  on the appropriate side of the plot edge (default `out` matches
1178
- PowerPoint's stock look); `none` suppresses them entirely.
1295
+ the reference desktop app's stock look); `none` suppresses them entirely.
1179
1296
  - 3a2b974: feat: chart axis titles honor authored `<a:rPr>` font / color.
1180
1297
  `ChartSpec.categoryAxisTitleStyle` and `valueAxisTitleStyle` carry the
1181
1298
  same `ChartTextStyle` shape as `titleStyle`. The playground renderer
@@ -1240,7 +1357,7 @@ cross|none"/>`. The playground value-axis renderer draws short stubs
1240
1357
  (converted from OOXML's 60000ths-of-a-degree to plain degrees). The
1241
1358
  playground renderer rotates each tick label around its anchor and
1242
1359
  shifts the text-anchor side based on the sign of the rotation so dense
1243
- 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
1244
1361
  shows them. Rotated labels also get a longer truncation budget before
1245
1362
  ellipsization.
1246
1363
  - 4f5cc4c: feat: round out gridline color round-trip with 3 more fields —
@@ -1263,7 +1380,7 @@ cross|none"/>`. The playground value-axis renderer draws short stubs
1263
1380
  `ChartSpec.plotAreaStrokeColor` reads `<c:plotArea><c:spPr><a:ln>`.
1264
1381
  The playground renderer projects them onto the chart-area card
1265
1382
  border and the plot-area inner rect — branded charts with thick / no
1266
- / colored card borders finally render the way PowerPoint shows them.
1383
+ / colored card borders finally render the way the reference desktop app shows them.
1267
1384
  - eb4159e: feat(chart): `ChartSpec.valueAxisHidden` and `categoryAxisHidden`
1268
1385
  read `<c:valAx><c:delete val="1"/>` and `<c:catAx><c:delete val="1"/>`.
1269
1386
  Playground skips rendering the axis when hidden — common on KPI tile
@@ -1292,7 +1409,7 @@ cross|none"/>`. The playground value-axis renderer draws short stubs
1292
1409
  `ChartSpec.valueAxisTitleRotationDeg` — rotation in plain degrees
1293
1410
  (clockwise) on the per-axis title. Maps to
1294
1411
  `<c:catAx|valAx><c:title><c:tx><c:rich><a:bodyPr rot="N"/>` (60000ths
1295
- 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-
1296
1413
  axis title; the field now survives round-trip. Read by chart-reader
1297
1414
  via a new `readTitleRotationDeg` helper; written by chart-builder
1298
1415
  through an extended `titleElement(title, style?, rotationDeg?)`
@@ -1432,14 +1549,14 @@ cross|none"/>`. The playground value-axis renderer draws short stubs
1432
1549
  CT_CatAx schema order.
1433
1550
  - 21f58cb: feat: `ChartSpec.categoryAxisNoMultiLevelLabel` — toggle multi-level
1434
1551
  (hierarchical) category labels via `<c:catAx><c:noMultiLvlLbl val/>`.
1435
- 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`
1436
1553
  to flatten hierarchical categories into a single row. Read by
1437
1554
  chart-reader, written by chart-builder at the schema-required last
1438
1555
  position inside `<c:catAx>`.
1439
1556
  - c561df4: feat: `ChartSpec.categoryAxisNumberFormat` — number-format code for the
1440
1557
  category-axis tick labels (`<c:catAx><c:numFmt formatCode="…"/>`). Most
1441
1558
  useful on date-style categories (`"mm/dd/yyyy"`, `"mmm-yyyy"`) but
1442
- accepts any Excel format string. Independent of `valueAxis.numberFormat`.
1559
+ accepts any spreadsheet number-format string. Independent of `valueAxis.numberFormat`.
1443
1560
  Read by chart-reader, written by chart-builder in the correct CT_CatAx
1444
1561
  schema order (after `<c:title>`, before `<c:majorTickMark>`).
1445
1562
  - 3ecc11b: feat(chart): category-axis label-skip + position. `ChartSpec.categoryAxisTickLabelSkip`
@@ -1460,7 +1577,7 @@ cross|none"/>`. The playground value-axis renderer draws short stubs
1460
1577
  - 199031b: feat: chart data labels honor `<c:dLbls><c:numFmt formatCode="…"/>`.
1461
1578
  `ChartDataLabels.numberFormat` exposes the format code on both
1462
1579
  chart-level and per-series toggle groups, and the playground renderer
1463
- projects value labels through the same Excel-format subset the value
1580
+ projects value labels through the same spreadsheet number-format subset the value
1464
1581
  axis already supports (`"0%"`, `"$#,##0"`, `"0.00"`, etc). Per-series
1465
1582
  formats win over the chart-level default.
1466
1583
  - b77c0ed: feat(chart): `ChartSpec.dispBlanksAs` reads `<c:dispBlanksAs>`
@@ -1500,7 +1617,7 @@ cross|none"/>`. The playground value-axis renderer draws short stubs
1500
1617
  `<c:gapWidth>` and `<c:overlap>` on bar / column plots. Playground
1501
1618
  sizes bars per ECMA-376 §21.2.2.75 — `barW = groupW / (clusterUnits +
1502
1619
  gapWidth/100)` with `clusterUnits = 1 + (S - 1)(1 - overlap/100)` —
1503
- 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
1504
1621
  0.8 / 0.7 ratios.
1505
1622
  - b88dbb8: feat(chart): `ChartSpec.valueAxisMajorGridlines` / `valueAxisMinorGridlines`
1506
1623
  read the presence of `<c:majorGridlines/>` / `<c:minorGridlines/>`
@@ -1511,12 +1628,12 @@ gapWidth/100)` with `clusterUnits = 1 + (S - 1)(1 - overlap/100)` —
1511
1628
  - 4caa5ad: feat(chart): `ChartSeries.invertIfNegative` reads `<c:ser>
1512
1629
  <c:invertIfNegative val="1"/>`. Playground's bar / column renderer
1513
1630
  paints negative bars in a darker shade of the series color when the
1514
- flag is set — matching PowerPoint's profit/loss visualization.
1631
+ flag is set — matching the reference desktop app's profit/loss visualization.
1515
1632
  - b603115: feat: `ChartSpec.language` (`<c:chartSpace><c:lang val=…/>`) and
1516
- `ChartSpec.date1904` (`<c:date1904 val=…/>`) — chartSpace-level Office
1517
- 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
1518
1635
  language code (e.g. `'en-US'`, `'ja-JP'`); `date1904` selects the
1519
- 1904 date epoch (default `false` = Excel 1900 epoch, surface only
1636
+ 1904 date epoch (default `false` = 1900 date epoch, surface only
1520
1637
  when explicitly true). pptx-kit's renderers don't act on either yet.
1521
1638
  - 028e3b7: feat: chart `<c:legend><c:legendEntry><c:delete val="1"/>` honored.
1522
1639
  `ChartSpec.legend.hiddenIndices` carries the series indices the
@@ -1541,15 +1658,15 @@ gapWidth/100)` with `clusterUnits = 1 + (S - 1)(1 - overlap/100)` —
1541
1658
  - 28d77ea: fix: chart categories accept `<c:cat><c:numRef>` (numeric / date
1542
1659
  categories). Previously the category-axis dropped to an empty
1543
1660
  labels array when the chart authored a numeric category channel
1544
- (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
1545
1662
  to formatting each cached numeric value as a string so date /
1546
1663
  number cats appear on the axis instead of disappearing.
1547
- - 7b3ba0a: feat(chart): axis number formats now accept Excel's `"$"#,##0`
1548
- 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
1549
1666
  currency as `"$"#,##0` (or `"\$"#,##0`) rather than the bare `$`
1550
1667
  form, so the previous detection missed it.
1551
1668
  - d2f86d2: feat(chart): `ChartAxisScaling.numberFormat` reads `<c:valAx><c:numFmt
1552
- formatCode="…"/>`. Playground projects the most common Excel format
1669
+ formatCode="…"/>`. Playground projects the most common spreadsheet number-format
1553
1670
  codes to axis labels — percent (`'0%'`, `'0.0%'`), thousand
1554
1671
  separator (`'#,##0'`, `'#,##0.0'`), and currency prefixes
1555
1672
  (`'$#,##0'`, `'¥#,##0'`). Other codes fall through to the generic
@@ -1560,20 +1677,20 @@ formatCode="…"/>`. Playground projects the most common Excel format
1560
1677
  horizontal strip. Playground sizes the plot area accordingly — gives
1561
1678
  the chart back the extra vertical real estate when overlay is set.
1562
1679
  - 4cde872: feat: `ChartSpec.plotVisibleCellsOnly` — toggle `<c:plotVisOnly val/>`.
1563
- 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
1564
1681
  exists to let authors opt into `false` (plot hidden rows / columns too).
1565
1682
  The reader surfaces `false` only when the wire is explicitly `0` so
1566
1683
  round-tripping the common default doesn't drag a redundant explicit
1567
1684
  `true` into the spec.
1568
1685
  - 693ba3e: feat: `ChartSpec.roundedCorners` — round-trip the chartSpace-level
1569
- `<c:roundedCorners val>` toggle. PowerPoint's default is `false`; the
1686
+ `<c:roundedCorners val>` toggle. The reference desktop app's default is `false`; the
1570
1687
  reader surfaces `true` only when the wire is explicitly `1` and the
1571
1688
  builder emits the element only when authored, so common defaults stay
1572
1689
  clean. Schema position is BEFORE `<c:chart>` (per CT_ChartSpace).
1573
1690
  - 733120a: feat(chart): `ChartSeries.smooth` reads `<c:smooth val="1"/>`. Playground
1574
1691
  line / area renderer interpolates a cubic-Bézier curve through the
1575
1692
  data points (Catmull-Rom-to-Bezier with 0.5 tension) when `smooth` is
1576
- true, matching PowerPoint's "smooth line" preset visually.
1693
+ true, matching the reference desktop app's "smooth line" preset visually.
1577
1694
  - d581121: feat(site/playground): bar (horizontal), line, and area charts now
1578
1695
  honour `ChartSpec.grouping` for stacked / percentStacked layouts —
1579
1696
  matching the column-chart treatment added previously. Data labels
@@ -1589,9 +1706,9 @@ formatCode="…"/>`. Playground projects the most common Excel format
1589
1706
  Adds the `ChartGrouping` type to the public surface.
1590
1707
 
1591
1708
  - 53148e4: feat: `ChartSpec.chartStyle` — round-trip the chartSpace-level
1592
- `<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
1593
1710
  curated combo of theme accent colors, gradients, effects, and font
1594
- 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
1595
1712
  round-trip parity; pptx-kit's renderers don't interpret the preset
1596
1713
  yet, but the field survives save/reload.
1597
1714
  - b1cfda3: feat: `ChartSpec.categoryAxisTickMarkSkip` — the second half of the
@@ -1602,7 +1719,7 @@ formatCode="…"/>`. Playground projects the most common Excel format
1602
1719
  chart-builder.
1603
1720
  - 2599a46: feat: chart titles read `<c:tx><c:strRef>` workbook-cell references.
1604
1721
  Previously only literal `<c:rich>` titles surfaced; titles authored
1605
- 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>`
1606
1723
  with a `<c:strCache>` of the resolved text) now flow through to
1607
1724
  `ChartSpec.title` as the cached value. Affects the title shown above
1608
1725
  the chart and, transitively, axis-title rendering.
@@ -1620,7 +1737,7 @@ formatCode="…"/>`. Playground projects the most common Excel format
1620
1737
  chart-reader; written by chart-builder in the correct CT_Trendline
1621
1738
  schema order (after `<c:backward>`, before any `<c:trendlineLbl>`).
1622
1739
  - a978251: feat: `ChartTrendline.name` — round-trip a custom trendline label
1623
- (`<c:trendline><c:name>…`). PowerPoint auto-generates a label like
1740
+ (`<c:trendline><c:name>…`). The reference desktop app auto-generates a label like
1624
1741
  "Linear (X)" or "MA(5) (X)" when this element is omitted; authors who
1625
1742
  want a different label (or who imported one from another tool) now
1626
1743
  have the field. Read by chart-reader; written by chart-builder at the
@@ -1651,7 +1768,7 @@ formatCode="…"/>`. Playground projects the most common Excel format
1651
1768
  `ChartSpec.varyColors` carries the `<c:plottedKind><c:varyColors val="1"/>`
1652
1769
  flag. When set and the chart has exactly one series, the renderer
1653
1770
  assigns each data point a distinct accent color (mirroring
1654
- 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
1655
1772
  already varied colors implicitly.
1656
1773
  - 69431a9: feat: `getSlideColorMapOverride(slide)` returns the slide's
1657
1774
  `<p:clrMapOvr><a:overrideClrMapping/>` token-remap, or `null` when the
@@ -1670,12 +1787,12 @@ formatCode="…"/>`. Playground projects the most common Excel format
1670
1787
  the supplied theme.
1671
1788
  - New `getShapeFillColorResolved(pres, shape)` and
1672
1789
  `getShapeStrokeColorResolved(pres, shape)` return the exact `#RRGGBB`
1673
- PowerPoint paints — useful for renderers / exporters where the legacy
1790
+ the reference desktop app paints — useful for renderers / exporters where the legacy
1674
1791
  `getShapeFillColor` / `getShapeStrokeColor` strings (`#RRGGBB` or
1675
1792
  `scheme:<token>`) miss both scheme resolution and color transforms.
1676
1793
  - `getShapeRunFormatEffective` now applies the same pipeline at every
1677
1794
  layer of the rPr cascade, so a run inheriting `accent1 lumMod=40000
1678
- 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
1679
1796
  concrete tinted hex instead of leaking the raw token through.
1680
1797
 
1681
1798
  - 263bf52: feat(site/playground): bent / curved connector routing.
@@ -1706,7 +1823,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1706
1823
  and per-series scope. The playground renderer projects `ctr`, `inEnd`,
1707
1824
  `outEnd`, `inBase` onto clustered column and bar labels — outside-end
1708
1825
  remains the default, but authored positions now move labels inside the
1709
- bar or to the base as PowerPoint shows them.
1826
+ bar or to the base as the reference desktop app shows them.
1710
1827
  - 3cfba8d: feat: chart data label separator. `ChartDataLabels.separator` carries
1711
1828
  the `<c:dLbls><c:separator>…</c:separator>` text used to join
1712
1829
  multiple label parts (value + percent + category etc.). The pie /
@@ -1742,7 +1859,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1742
1859
  `getShapeRunFormat` still returns the literal `<a:rPr>` only.
1743
1860
  - 25654cf: feat: `getShapeEffectsEffective(pres, shape)` walks the layout →
1744
1861
  master placeholder cascade for `<a:effectLst>`. Effect lists override
1745
- rather than compose (matching PowerPoint's behaviour), so the first
1862
+ rather than compose (matching the reference desktop app's behaviour), so the first
1746
1863
  layer that supplies any effects wins. Playground uses it so
1747
1864
  placeholder shadows / glows / soft edges inherited from the master
1748
1865
  finally render on slides that don't repeat the effect list.
@@ -1759,7 +1876,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1759
1876
  shape's `<a:effectLst>` (`outerShdw`, `innerShdw`, `glow`, `reflection`,
1760
1877
  `softEdge`, `blur`) in document order, with each effect's color
1761
1878
  (transform-resolved against the theme), opacity, blur radius, distance,
1762
- and angle. PowerPoint composes multiple effects in a single filter
1879
+ and angle. The reference desktop app composes multiple effects in a single filter
1763
1880
  stack — the existing `getShapeEffect` only surfaced the first one.
1764
1881
 
1765
1882
  The playground renderer now emits an SVG `<filter>` chain that
@@ -1825,7 +1942,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1825
1942
  slide whose `getShapeAnimation` is not `null`. Pair to
1826
1943
  `slideHasAnimations`. Useful for "which shapes on this slide actually
1827
1944
  animate?" audits before exporting to a video pipeline that doesn't
1828
- honor PowerPoint's timing tree.
1945
+ honor the reference desktop app's timing tree.
1829
1946
  - 87d7fbb: feat: `findShapesWithHyperlinks(slide)` — every shape on the slide
1830
1947
  that carries any hyperlink, regardless of target. Counterpart to
1831
1948
  `findShapesByHyperlink(slide, url)` (which requires a matching URL)
@@ -1839,7 +1956,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1839
1956
  `'/ppt/slideLayouts/slideLayout3.xml'`). Pair to the existing
1840
1957
  `findSlidesByLayoutName` / `findSlidesByLayoutType`. Keyed on the
1841
1958
  actual package path, so it's stable across template-name collisions
1842
- and PowerPoint UI locales.
1959
+ and the reference desktop app's UI locales.
1843
1960
  - 20613b5: feat: `findSlidesWithChartKind(pres, kind)` — kind-filtered variant of
1844
1961
  the existing `getSlidesWithCharts`. Returns every slide carrying at
1845
1962
  least one chart of the given `ChartKind` (`'bar'`, `'column'`,
@@ -1894,7 +2011,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1894
2011
  - b793c74: feat: `getSlideLayoutUsageCountsByType(pres)` — companion to
1895
2012
  `getSlideLayoutUsageCounts`, but keyed on the OOXML layout-type enum
1896
2013
  token (`title`, `obj`, `twoObj`, `blank`, …) instead of the user-
1897
- 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
1898
2015
  many content slides vs. dividers vs. title slides?" audits.
1899
2016
  - 3891fa2: feat: `getSlideLayoutUsageCounts(pres)` — layout name → number-of-slides
1900
2017
  histogram. Every layout enumerated by `getSlideLayouts` appears as a
@@ -1926,7 +2043,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1926
2043
 
1927
2044
  The playground renderer emits an SVG `<radialGradient>` for the
1928
2045
  non-linear paths, with reversed stop offsets so the first ECMA-376
1929
- stop sits at the focus center (matching PowerPoint's outward
2046
+ stop sits at the focus center (matching the reference desktop app's outward
1930
2047
  painting order).
1931
2048
 
1932
2049
  - 855076d: feat: chart value-axis major gridlines honor authored stroke color.
@@ -1938,17 +2055,17 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1938
2055
  - 74b227e: feat(site/playground): hyperlink tooltips. Shape and per-run
1939
2056
  hyperlinks now surface their `<a:hlinkClick tooltip="…"/>` text —
1940
2057
  shapes get an SVG `<title>` child on the `<a>` wrapper, runs get a
1941
- `title=` attribute on the HTML anchor. PowerPoint shows these on
2058
+ `title=` attribute on the HTML anchor. The reference desktop app shows these on
1942
2059
  hover during the slideshow; the playground now does too.
1943
2060
  - a610e82: feat: `getShapeHyperlinkTooltip(shape)` and
1944
2061
  `getShapeRunHyperlinkTooltip(shape, p, r)` return the
1945
- `<a:hlinkClick tooltip="…"/>` text. Tooltips show up in PowerPoint
2062
+ `<a:hlinkClick tooltip="…"/>` text. Tooltips show up in the reference desktop app
1946
2063
  when the user hovers a linked shape in slide-show mode — useful for
1947
2064
  accessibility and link-preview surfaces.
1948
2065
  - cbdda7c: feat(site/playground): render `<a:duotone>` image recolor. The filter
1949
2066
  pipeline desaturates the picture to luminance, then samples a
1950
2067
  two-color gradient (firstColor → secondColor) via a 16-step
1951
- `feComponentTransfer` table. Pictures with PowerPoint's Color >
2068
+ `feComponentTransfer` table. Pictures with the reference desktop app's Color >
1952
2069
  Recolor preset finally render in their authored two-color tint.
1953
2070
  - c4a89c1: feat: `getShapeImageDuotone(pres, shape)` reads the picture's
1954
2071
  `<a:blip><a:duotone>` two-color recolor effect — the typical
@@ -1976,7 +2093,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
1976
2093
  threshold) when `<a:blip><a:biLevel thresh="…"/>` is set
1977
2094
 
1978
2095
  Pictures with Color > Grayscale or Color > Black and White now
1979
- render with the same visual treatment PowerPoint shows.
2096
+ render with the same visual treatment the reference desktop app shows.
1980
2097
 
1981
2098
  - 66edcbc: feat: add `isShapeTextBox(shape)` — `true` when a shape is a text box
1982
2099
  (`<p:cNvSpPr txBox="1">`) rather than an autoshape. The two have different
@@ -2016,7 +2133,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
2016
2133
  the data points. Bar / column / pie keep the square swatch.
2017
2134
  - b1073ff: feat(site/playground): right / left chart legend stack centers
2018
2135
  vertically. Previously the `r` and `l` legend positions both
2019
- 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
2020
2137
  vertically-centers right / left legends inside the chart area; the
2021
2138
  renderer now matches by computing `yStart` from the legend's total
2022
2139
  height. `tr` keeps the top-anchored stack.
@@ -2108,7 +2225,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
2108
2225
  (`<a:lumOff>`), contrast (`<a:lumMod>`), and opacity (`<a:alphaModFix>`).
2109
2226
 
2110
2227
  Crops project to an enlarged `<image>` element clipped to the shape's
2111
- bounds (matching PowerPoint's "Crop" tool). Brightness + contrast
2228
+ bounds (matching the reference desktop app's "Crop" tool). Brightness + contrast
2112
2229
  compose into an SVG `<feComponentTransfer>` filter. Opacity drives
2113
2230
  the `opacity` attribute directly.
2114
2231
 
@@ -2122,7 +2239,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
2122
2239
  exposes the per-data-point pull-out percentage from `<c:dPt><c:explosion val="N"/>`,
2123
2240
  and the playground renderer offsets exploded slices (and their labels)
2124
2241
  outward along the slice mid-angle. Matches the "pulled-out" pie look
2125
- authors get from Excel's "Vary colors by point" toggle.
2242
+ authors get from the "Vary colors by point" toggle in spreadsheet apps.
2126
2243
  - 2e9776d: feat(site/playground): chart / media count badges on each slide.
2127
2244
  `getSlideCharts(slide)` and `getSlideMediaPartNames(pres, slide)`
2128
2245
  power two new badges (`N chart`, `N media`) showing how many chart
@@ -2131,7 +2248,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
2131
2248
  - 997d507: feat(site/playground): comment badge tooltip carries the comment
2132
2249
  texts. The `N cmt` badge's `title=` attribute now joins each
2133
2250
  comment's body text so hovering surfaces the review remarks
2134
- without opening PowerPoint.
2251
+ without opening the reference desktop app.
2135
2252
  - 3ede588: feat(site/playground): additional slide badges — `hidden` (when
2136
2253
  `show="0"`) and `N cmt` (count of authored review comments). Threads
2137
2254
  `isSlideHidden` and `getSlideComments` through the slide-snapshot
@@ -2146,7 +2263,7 @@ lumOff=60000` (PowerPoint's "Accent 1, Lighter 60%") resolves to the
2146
2263
  `twoObj`, `blank`, …) as a badge next to the slide title. Reads
2147
2264
  `<p:sldLayout type="…">` via `getSlideLayout` + `getSlideLayoutType`
2148
2265
  so deck audits can spot which layout each slide is bound to without
2149
- opening PowerPoint.
2266
+ opening the reference desktop app.
2150
2267
  - 5861d1e: feat(site/playground): include slide-master count in the
2151
2268
  "masters · layouts · sections" meta cell. `getPresentationSummary`
2152
2269
  already returned layout / section counts; the playground now also
@@ -2171,7 +2288,7 @@ href="#slide-N">` link, so users can right-click → "Copy link
2171
2288
  - ffec23d: feat(site/playground): show speaker notes under each slide. The
2172
2289
  playground now calls `getSlideNotes` for every slide and renders a
2173
2290
  collapsible `<details>` block when notes exist, so users can
2174
- inspect the deck author's notes without opening PowerPoint.
2291
+ inspect the deck author's notes without opening the reference desktop app.
2175
2292
  - b90f1bc: feat(site/playground): show `validatePresentation` results. The
2176
2293
  playground now runs the validator after parsing and surfaces any
2177
2294
  issues in a dedicated panel (with severity tint and the offending
@@ -2243,7 +2360,7 @@ href="#slide-N">` link, so users can right-click → "Copy link
2243
2360
  - a65c05c: feat: `setShapeTextColumns(shape, { count, gapEmu? } | null)` — multi-
2244
2361
  column writer pairing the existing `getShapeTextColumns` reader. Writes
2245
2362
  `<a:bodyPr numCol="N" [spcCol="EMU"]/>`. Passing `null` clears both
2246
- 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
2247
2364
  column. `count` must be `>= 2` (single column is the default — pass
2248
2365
  `null` instead); the function throws otherwise.
2249
2366
  - fea7725: feat: `setShapeTextDirection(shape, direction | null)` — companion
@@ -2259,7 +2376,7 @@ href="#slide-N">` link, so users can right-click → "Copy link
2259
2376
  `top`/`center`/`bottom` to the schema's `t`/`ctr`/`b` values and clears
2260
2377
  the attribute on `null`. The margins setter writes per-side EMU on
2261
2378
  `marL`/`marR`/`marT`/`marB`; sides set to `null`/`undefined` are
2262
- stripped (PowerPoint falls back to its defaults); passing the whole
2379
+ stripped (the reference desktop app falls back to its defaults); passing the whole
2263
2380
  arg as `null` clears every side. Both create `<a:tcPr>` if absent.
2264
2381
  - 3921802: feat: `setTableCellBorders(cell, sides | null)` — partial-update writer
2265
2382
  for all 6 cell-border slots (`left`, `right`, `top`, `bottom` + the
@@ -2282,32 +2399,32 @@ href="#slide-N">` link, so users can right-click → "Copy link
2282
2399
  `firstCol`, `lastCol`, `bandRow`, `bandCol`). Pairs the existing
2283
2400
  `getTableStyleFlags` reader. Only the keys present in `flags` are
2284
2401
  touched — omitted keys keep their current state. A flag set to `false`
2285
- strips the attribute (matching how PowerPoint round-trips defaults).
2402
+ strips the attribute (matching how the reference desktop app round-trips defaults).
2286
2403
  Creates `<a:tblPr>` if absent. Throws when the shape isn't a table
2287
2404
  graphic frame.
2288
2405
  - 1ea509b: feat: `setTableStyleId(table, styleId | null)` — writer for
2289
2406
  `<a:tbl><a:tblPr><a:tableStyleId>`. Pairs the existing `getTableStyleId`
2290
2407
  reader. Pass the curly-braced GUID (e.g.
2291
- `'{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}'` for PowerPoint's "Medium
2408
+ `'{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}'` for the reference desktop app's "Medium
2292
2409
  Style 2 - Accent 1") or `null` to remove the reference so the table
2293
2410
  uses the slide's default style. Creates `<a:tblPr>` if absent. Throws
2294
2411
  when the shape isn't a table graphic frame.
2295
2412
  - 2438696: feat(site/playground): shape `aria-label` from authored alt text.
2296
2413
  Each rendered shape with a non-empty alt title (or, as fallback,
2297
2414
  alt description) now exposes `role="img" aria-label="…"` on the
2298
- 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
2299
2416
  Accessibility Inspector reports them, without affecting visuals.
2300
2417
  - b8e24d6: feat(site/playground): each shape's authored name surfaces as a
2301
2418
  `data-pptx-shape-name` attribute on its root `<g>` element. Lets
2302
2419
  DevTools, a11y inspectors, or test selectors target shapes by their
2303
- PowerPoint name without parsing SVG geometry. Cheap to emit and has
2420
+ visible name without parsing SVG geometry. Cheap to emit and has
2304
2421
  no visual impact.
2305
2422
  - fdd4770: feat: `getShapeTextBodyRotationDeg(shape)` returns the shape's text-body
2306
2423
  rotation from `<a:bodyPr rot="N"/>` (where N is in 60000ths of a
2307
2424
  degree). Distinct from the shape's geometry rotation (`<p:xfrm rot>`):
2308
2425
  this rotates the text body _inside_ the shape without rotating the
2309
2426
  geometry. The playground renderer pivots the text body around the
2310
- 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
2311
2428
  behaviour for vertical-label callouts and rotated text frames.
2312
2429
  - 263bf52: feat: `getSlideBackgroundGradientFill(slide)` returns the gradient
2313
2430
  stops + path for slides with a `<p:bgPr><a:gradFill>` background.
@@ -2330,7 +2447,7 @@ href="#slide-N">` link, so users can right-click → "Copy link
2330
2447
  `getPresentationSummary().hasAnimations`. The site playground uses
2331
2448
  it (plus `getSlideTransition`) to show small `anim` / `trans`
2332
2449
  badges next to each slide title so deck audits don't need to open
2333
- PowerPoint.
2450
+ the reference desktop app.
2334
2451
  - c0e0dc2: feat(site/playground): shapes with slide-jump click actions
2335
2452
  (`<a:hlinkClick action="ppaction://hlinksldjump"/>`) render as
2336
2453
  in-page hash anchors. The renderer resolves the target via
@@ -2355,7 +2472,7 @@ href="#slide-N">` link, so users can right-click → "Copy link
2355
2472
  caps, miter vs bevel joins, and per-end arrow heads.
2356
2473
 
2357
2474
  The playground composes `stroke-dasharray` from the preset dash
2358
- patterns (cadence multiplied by stroke width as PowerPoint does),
2475
+ patterns (cadence multiplied by stroke width as the reference desktop app does),
2359
2476
  emits SVG `<marker>` defs for triangle / stealth / diamond / oval
2360
2477
  arrowheads on connectors and shapes, and maps cap / join through.
2361
2478
 
@@ -2373,11 +2490,11 @@ href="#slide-N">` link, so users can right-click → "Copy link
2373
2490
  marL/marR/marT/marB>` insets. The renderer previously hard-coded a
2374
2491
  4-pixel pad on every side; it now converts each EMU-valued margin to
2375
2492
  px (falling back to 4px only when the side isn't authored) so cells
2376
- 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.
2377
2494
  - 42cf575: feat: `getTableCellMargins(cell)` returns the cell's `<a:tcPr marL
2378
2495
  marR marT marB>` inset margins in EMU. Each side is `null` when the
2379
2496
  cell doesn't author it, so renderers know to fall back to
2380
- 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 /
2381
2498
  0.05 in vertical).
2382
2499
  - ba94f5e: feat: `getTableCellParagraphs(cell)` returns a table cell's text as structured
2383
2500
  paragraphs — each carrying its alignment and per-run format (`size`, `bold`,
@@ -2407,9 +2524,9 @@ marR marT marB>` inset margins in EMU. Each side is `null` when the
2407
2524
  (accent1 for header / footer rows, 92%-white-mixed accent for bands)
2408
2525
  when the cell doesn't supply an explicit fill of its own. Header text
2409
2526
  rendered on the accent gets white text instead of the default body
2410
- color, matching PowerPoint's built-in table styles.
2527
+ color, matching the reference desktop app's built-in table styles.
2411
2528
  - 243e731: feat: `getTableStyleId(table)` returns the GUID string inside
2412
- `<a:tbl><a:tblPr><a:tableStyleId>`. PowerPoint references built-in
2529
+ `<a:tbl><a:tblPr><a:tableStyleId>`. The reference desktop app references built-in
2413
2530
  table styles (`{5C22544A-…}` = Medium Style 2 - Accent 1, etc.) and
2414
2531
  theme-local styles by GUID. Returns `null` when the table doesn't
2415
2532
  author one.
@@ -2453,7 +2570,7 @@ layout)` — the non-placeholder decorative shapes (corner bars, divider lines,
2453
2570
  `writing-mode` / `text-orientation` declaration so Asian and
2454
2571
  Mongolian-style vertical text renders without manual transforms.
2455
2572
  - Playground wraps shapes carrying a `<a:hlinkClick>` in an SVG `<a>`
2456
- element so the preview is clickable — matches PowerPoint's
2573
+ element so the preview is clickable — matches the reference desktop app's
2457
2574
  slide-show behaviour for shape-level hyperlinks.
2458
2575
  - Group shape rendering now applies the group's own `<a:xfrm rot
2459
2576
  flipH flipV>` to the whole subtree before the scale + translate
@@ -2464,7 +2581,7 @@ flipH flipV>` to the whole subtree before the scale + translate
2464
2581
  extrapolation past the last / before the first data point. The
2465
2582
  playground renderer projects the linear fit further along the x-axis
2466
2583
  by `N * step` so projected-future trendlines render the way
2467
- PowerPoint shows them. Moving-average / log / poly trendlines keep
2584
+ the reference desktop app shows them. Moving-average / log / poly trendlines keep
2468
2585
  their data-range output since extrapolation isn't meaningful for
2469
2586
  them.
2470
2587
  - 57117a7: feat: chart value-axis tick labels honor `<c:valAx><c:txPr><a:bodyPr
@@ -2475,7 +2592,7 @@ rot="N"/>`. `ChartSpec.valueAxisLabelRotationDeg` returns the rotation
2475
2592
  `categoryAxisLabelRotationDeg` we already projected.
2476
2593
  - 3e1c8a1: feat: chart value-axis exposes `<c:scaling><c:logBase val="N"/>`.
2477
2594
  `ChartAxisScaling.logBase` carries the authored log base (commonly
2478
- `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]`
2479
2596
  range. Callers that round-trip charts now preserve the log-scale
2480
2597
  flag; the playground renderer still draws linear (log-scale
2481
2598
  projection is a follow-up — exposing the field unblocks it).
@@ -2503,7 +2620,7 @@ rot="N"/>`. `ChartSpec.valueAxisLabelRotationDeg` returns the rotation
2503
2620
  size (consumers apply the ~18pt text-box default) instead of wrongly picking up
2504
2621
  the master body size (often much larger). Real placeholders — including ones
2505
2622
  whose `<p:ph>` omits a `type` — still inherit as before. This makes effective
2506
- 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.
2507
2624
  - cfe8b69: fix: placeholder inheritance now applies the OOXML `ctrTitle`↔`title` and
2508
2625
  `subTitle`→`body` type equivalence. A `ctrTitle` (centered title) now inherits
2509
2626
  its layout/master `title` placeholder's `bodyPr` (e.g. `anchor="ctr"`),
@@ -2513,7 +2630,7 @@ rot="N"/>`. `ChartSpec.valueAxisLabelRotationDeg` returns the rotation
2513
2630
  centered titles and subtitles.
2514
2631
  - 610ecac: fix(validator): `validatePresentation` now flags duplicate
2515
2632
  `<p:cNvPr id="N">` values inside a single slide's `<p:spTree>` as
2516
- 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
2517
2634
  within its slide; duplicates often appear after pasting shapes from
2518
2635
  another slide without re-allocating IDs. The walk recurses into
2519
2636
  `<p:grpSp>` so duplicates nested in groups are also caught.
@@ -2526,8 +2643,8 @@ rot="N"/>`. `ChartSpec.valueAxisLabelRotationDeg` returns the rotation
2526
2643
 
2527
2644
  **What works at 1.0:**
2528
2645
 
2529
- - **Read** any `.pptx` produced by PowerPoint, Keynote, Google Slides, or
2530
- 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
2531
2648
  extensions are preserved verbatim on round-trip.
2532
2649
  - **Template editing**: token / text replace across slides and speaker
2533
2650
  notes, image swap with geometry preserved, slide CRUD with placeholder