@office-kit/pptx 0.21.0 → 0.22.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/README.md CHANGED
@@ -321,7 +321,11 @@ and a next-actions table. Use labelled sample data where needed.
321
321
 
322
322
  The [skill](skill/SKILL.md) creates a TSX project, starts the interactive preview,
323
323
  checks the source and exports an editable PPTX. Ask for changes in the same
324
- conversation; the preview updates as the agent edits TSX. You need Node.js 22.18+
324
+ conversation; the preview updates as the agent edits TSX. It plans the storyline for
325
+ either a talk or a deck people read and decide from, and checks the headlines and
326
+ Japanese wording before delivery ([talk](skill/references/story-talk.md),
327
+ [document](skill/references/story-document.md), [review](skill/references/review.md)).
328
+ You need Node.js 22.18+
325
329
  and Git alongside Claude Code. See the
326
330
  [authoring guide](https://office-kit.github.io/pptx/docs/authoring) for template
327
331
  editing and manual setup. The bundled [core reference](skill/references/core-api.md)
@@ -601,57 +605,151 @@ for (const i of issues) console.error(i.severity, i.message);
601
605
  // Catches missing rels, dangling slide ids, layouts without masters, etc.
602
606
  ```
603
607
 
608
+ ### Copy formatted text between shapes
609
+
610
+ `setShapeParagraphs` accepts either paragraph specifications or an existing text
611
+ shape. Copying from a shape retains paragraph properties, run formatting, complete
612
+ fields and hyperlink relationships, including across presentations:
613
+
614
+ ```ts
615
+ import { setShapeParagraphs } from '@office-kit/pptx';
616
+
617
+ setShapeParagraphs(destination, { source });
618
+ setShapeParagraphs(destination, { source, range: { start: 6, end: 12 } });
619
+ // Append whole paragraphs without flattening formatting, fields or hyperlinks.
620
+ setShapeParagraphs(destination, { sources: [destination, source] });
621
+ // Reorder ranges into one text body, retaining their paragraph formatting.
622
+ setShapeParagraphs(destination, {
623
+ source,
624
+ ranges: [
625
+ { start: 6, end: 12 },
626
+ { start: 0, end: 5 },
627
+ ],
628
+ });
629
+ setShapeParagraphs([first, second], {
630
+ source,
631
+ ranges: [
632
+ { start: 0, end: 5 },
633
+ { start: 6, end: 12 },
634
+ ],
635
+ });
636
+ ```
637
+
638
+ Ranges use UTF-16 offsets with an exclusive end, including one character per
639
+ paragraph separator. A partially selected field becomes literal text. The
640
+ source stays unchanged unless it is also a destination; each destination retains
641
+ its text-body settings and list styles. All batch ranges are read before any
642
+ destination text changes. `getShapeParagraphElements(shape)` reads all paragraphs
643
+ in one pass; passing an index reads one paragraph.
644
+
645
+ To create several destination slides, use `addSlideAt(pres, index, [{ layout },
646
+ { layout }])`. It returns the new slides in insertion order, with existing slide
647
+ handles preserved. Every layout must belong to the presentation.
648
+
604
649
  ### API surface (current state)
605
650
 
606
651
  Each row lists the free-function entry points. Read/write pairs are
607
652
  shown together.
608
653
 
609
- | Capability | API |
610
- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
611
- | Load / save | `loadPresentation(input)`, `savePresentation(pres)`, `loadPresentationFile(path)` (node), `savePresentationToFile(pres, path)` (node) |
612
- | Create | `createPresentation({ size?: '16:9' \| '4:3' })` — blank deck with master + theme + `Blank` / `Title Slide` / `Title and Content` layouts |
613
- | Slide CRUD | `getSlides`, `getSlideAt`, `getSlideIndex`, `addSlide`, `removeSlide`, `moveSlide`, `duplicateSlide`, `clearSlideShapes` |
614
- | Slide layout | `getSlideLayouts`, `findSlideLayout` (by name — case-sensitive, exact; pass a `RegExp` for case-insensitive), `findSlideLayoutByType` (by locale-stable `type` token — preferred), `getSlideLayout(slide)`, `setSlideLayout(slide, layout)`, `getSlideLayoutName`, `getSlideLayoutType` |
615
- | Slide metadata | `getSlideTitle` / `setSlideTitle`, `getSlideSize` / `setSlideSize`, `isSlideHidden` / `setSlideHidden`, `getSlideText` |
616
- | Slide sections | `getSlideSections`, `setSlideSections` (p14 sectionLst) |
617
- | Placeholders | `findSlidePlaceholder(slide, 'title' \| 'body' \| ...)` |
618
- | Token / text replace | `replaceTokensInPresentation`, `replaceTokensInSlide`, `replaceTextInPresentation`, `replaceTextInSlide` |
619
- | Background | `getSlideBackground` / `setSlideBackground` / `clearSlideBackground` |
620
- | Notes | `getSlideNotes` / `setSlideNotes` |
621
- | Transitions | `getSlideTransition` / `setSlideTransition` / `clearSlideTransition` |
622
- | Animations | `getShapeAnimation` / `setShapeAnimation` (`fadeIn` / `fadeOut` / `appear` / `disappear`), `clearSlideAnimations` |
623
- | Comments | `addSlideComment`, `getSlideComments`, `removeSlideComment`, `getCommentAuthors`, `getCommentText` / `getCommentAuthor` / `getCommentPosition` |
624
- | Shape authoring | `addSlideTextBox`, `addSlideShape`, `addSlideLine`, `addSlideTable`, `addSlideImage`, `addSlideMedia`, `addSlideChart` |
625
- | Shape lookup | `findShapeByName`, `findShapesByName`, `findShapesByKind`, `findShapeInPresentation`, `getAllShapes`, `getSlideShapes` |
626
- | Shape text | `setShapeText`, `setShapeParagraphs`, `setShapeBulletStyle`, `setShapeAlignment`, `setShapeTextFormat`, `setShapeHyperlink` / `getShapeHyperlink` |
627
- | Per-paragraph | `setParagraphAlignment` / `getParagraphAlignment`, `setParagraphLevel` / `getParagraphLevel`, `setParagraphBullet` / `getParagraphBullet`, `setParagraphSpacing` / `getParagraphSpacing`, `setParagraphLineSpacing` / `getParagraphLineSpacing`, `getParagraphEndFormat` |
628
- | Per-run text | `setShapeRunText` / `getShapeRunText`, `setShapeRunFormat` / `getShapeRunFormat`, `getShapeParagraphCount`, `getShapeRunCount` |
629
- | Text frame | `setShapeTextAnchor` / `getShapeTextAnchor`, `setShapeTextMargins` / `getShapeTextMargins` |
630
- | Fill | `setShapeFill` / `getShapeFill`, `setShapeGradientFill`, `setShapePatternFill`, `setShapeImageFill`, `setShapeNoFill`, `clearShapeFill` |
631
- | Stroke | `setShapeStroke` / `getShapeStroke`, `setShapeStrokeDash` / `getShapeStrokeDash`, `setShapeStrokeArrow` / `getShapeStrokeArrow`, `…NoStroke` |
632
- | Effects | `setShapeShadow` / `setShapeGlow` / `getShapeEffect`, `clearShapeEffects` |
633
- | Geometry | `setShapePosition`, `setShapeSize`, `setShapeRotation`, `setShapeFlip`, `setShapeBounds` / `getShapeBounds` |
634
- | Pictures | `setShapeImage`, `setShapeImageCrop` / `getShapeImageCrop`, `setShapeImageOpacity` / `getShapeImageOpacity`, `setShapeImageBrightness`, `…Contrast` |
635
- | Z-order | `bringShapeToFront`, `sendShapeToBack`, `bringShapeForward`, `sendShapeBackward` |
636
- | Click actions | `setShapeClickAction` / `getShapeClickAction` (`url` / `slide` / `nextSlide` / `prevSlide` / `firstSlide` / `lastSlide`) |
637
- | Shape removal | `removeShape` |
638
- | Tables | `getTableCell` / `getTableCells`, `setTableCellText` / `getTableCellText`, `setTableCellParagraphs` / `getTableCellParagraphs`, `setTableCellFill` / `clearTableCellFill`, `setTableCellAlignment`, `setTableCellTextFormat`, `insertTableRow` / `removeTableRow`, `insertTableColumn` / `removeTableColumn`, `mergeTableCells` / `getTableCellSpan` |
639
- | Charts | `addSlideChart`, `getSlideCharts`, `setChartSpec` — kinds: `bar`, `column`, `line`, `pie`, `doughnut`, `area`; axis tick labels via `categoryAxisTickLabelPos` / `valueAxisTickLabelPos` / `secondaryValueAxis.tickLabelPos`; axis line / gridline widths via `valueAxisLineWidthEmu`, `valueAxisMajorGridlineWidthEmu` and their category / secondary-axis mirrors; series `lineColor` / `markerColor` / `markerLineColor`; `dataLabels.showLeaderLines` |
640
- | Theme | `getPresentationTheme` / `setPresentationTheme` — color scheme (`accent1`..`accent6`, `dark1`, `light1`, `hyperlink`, ...); `getPresentationFonts` / `setPresentationFonts` — major / minor Latin, East Asian, and complex-script faces |
641
- | Groups | `groupShapes`, `ungroupShapes`, `getGroupChildren`, `getGroupTransform` |
642
- | Text autofit | `setShapeTextAutoFit` / `getShapeTextAutoFit`, `getShapeTextAutoFitParams` |
643
- | Preset adjustments | `setShapeAdjustValues`; `getShapeCustomGeometry` (custom geometry is read-only) |
644
- | Document properties | `getCoreProperties` / `setCoreProperties`, `touchModified`, `getThumbnail` / `setThumbnail` / `removeThumbnail` |
645
- | Package inspection | `listPackageParts`, `readPackagePart`, `getMediaParts`, `getOrphanMediaPartNames`, `getPackageSize`, `compactPackage` |
646
- | Validation | `validatePresentation(pres)` — invariant checks, returns `ValidationIssue[]` |
647
- | Units | `inches(n)`, `cm(n)`, `mm(n)`, `pt(n)`, `emu(n)` — return branded `Emu` numbers |
654
+ | Capability | API |
655
+ | --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
656
+ | Load / save | `loadPresentation(input)`, `savePresentation(pres)`, `loadPresentationFile(path)` (node), `savePresentationToFile(pres, path)` (node) |
657
+ | Create | `createPresentation({ size?: '16:9' \| '4:3' })` — blank deck with master + theme + `Blank` / `Title Slide` / `Title and Content` layouts |
658
+ | Slide CRUD | `getSlides`, `getSlideAt`, `getSlideIndex`, `addSlide`, `removeSlide`, `moveSlide`, `duplicateSlide`, `clearSlideShapes` |
659
+ | Slide layout | `getSlideLayouts`, `findSlideLayout` (by name — case-sensitive, exact; pass a `RegExp` for case-insensitive), `findSlideLayoutByType` (by locale-stable `type` token — preferred), `getSlideLayout(slide)`, `setSlideLayout(slide, layout)`, `getSlideLayoutName`, `getSlideLayoutType` |
660
+ | Slide metadata | `getSlideTitle` / `setSlideTitle`, `getSlideSize` / `setSlideSize`, `isSlideHidden` / `setSlideHidden`, `getSlideText` |
661
+ | Slide sections | `getSlideSections`, `setSlideSections` (p14 sectionLst) |
662
+ | Placeholders | `findSlidePlaceholder(slide, 'title' \| 'body' \| ...)` |
663
+ | `addSlidePlaceholder(slide, type, { source?: 'layout' \| 'master' })` | Restore one missing layout placeholder, or explicitly inherit from the master without changing layouts. |
664
+ | Token / text replace | `replaceTokensInPresentation`, `replaceTokensInSlide`, `replaceTextInPresentation`, `replaceTextInSlide` |
665
+ | Background | `getSlideBackground` / `setSlideBackground` / `clearSlideBackground` |
666
+ | Notes | `getSlideNotes` / `setSlideNotes` |
667
+ | Transitions | `getSlideTransition` / `setSlideTransition` / `clearSlideTransition` |
668
+ | Animations | `getShapeAnimation` / `setShapeAnimation` (`fadeIn` / `fadeOut` / `appear` / `disappear`), `clearSlideAnimations` |
669
+ | Comments | `addSlideComment`, `getSlideComments`, `removeSlideComment`, `getCommentAuthors`, `getCommentText` / `getCommentAuthor` / `getCommentPosition` |
670
+ | Shape authoring | `addSlideTextBox`, `addSlideShape`, `addSlideLine`, `addSlideTable`, `addSlideImage`, `addSlideMedia`, `addSlideChart` |
671
+ | Shape lookup | `findShapeByName`, `findShapesByName`, `findShapesByKind`, `findShapeInPresentation`, `getAllShapes`, `getSlideShapes` |
672
+ | Shape text | `setShapeText`, `setShapeParagraphs`, `setShapeBulletStyle`, `setShapeAlignment`, `setShapeTextFormat`, `setShapeHyperlink` / `getShapeHyperlink` |
673
+ | Per-paragraph | `setParagraphAlignment` / `getParagraphAlignment`, `setParagraphLevel` / `getParagraphLevel`, `setParagraphBullet` / `getParagraphBullet`, `setParagraphSpacing` / `getParagraphSpacing`, `setParagraphLineSpacing` / `getParagraphLineSpacing`, `getParagraphEndFormat` |
674
+ | Per-run text | `setShapeRunText` / `getShapeRunText`, `setShapeRunFormat` / `getShapeRunFormat`, `getShapeParagraphCount`, `getShapeRunCount` |
675
+ | Text frame | `setShapeTextAnchor` / `getShapeTextAnchor`, `setShapeTextMargins` / `getShapeTextMargins` |
676
+ | Fill | `setShapeFill` / `getShapeFill`, `setShapeGradientFill`, `setShapePatternFill`, `setShapeImageFill`, `setShapeNoFill`, `clearShapeFill` |
677
+ | Stroke | `setShapeStroke` / `getShapeStroke`, `setShapeStrokeDash` / `getShapeStrokeDash`, `setShapeStrokeArrow` / `getShapeStrokeArrow`, `…NoStroke` |
678
+ | Effects | `setShapeShadow` / `setShapeGlow` / `getShapeEffect`, `clearShapeEffects` |
679
+ | Geometry | `setShapePosition`, `setShapeSize`, `setShapeRotation`, `setShapeFlip`, `setShapeBounds` / `getShapeBounds` |
680
+ | Pictures | `setShapeImage`, `setShapeImageCrop` / `getShapeImageCrop`, `setShapeImageOpacity` / `getShapeImageOpacity`, `setShapeImageBrightness`, `…Contrast` |
681
+ | Z-order | `bringShapeToFront`, `sendShapeToBack`, `bringShapeForward`, `sendShapeBackward`, `getShapeZIndex`, `setShapeZIndex` |
682
+ | Click actions | `setShapeClickAction` / `getShapeClickAction` (`url` / `slide` / `nextSlide` / `prevSlide` / `firstSlide` / `lastSlide`) |
683
+ | Shape removal | `removeShape` |
684
+ | Tables | `getTableCell` / `getTableCells`, `setTableCellText` / `getTableCellText`, `setTableCellParagraphs` / `getTableCellParagraphs`, `setTableCellFill` / `clearTableCellFill`, `setTableCellAlignment`, `setTableCellTextFormat`, `insertTableRow` / `removeTableRow`, `insertTableColumn` / `removeTableColumn`, `mergeTableCells` / `getTableCellSpan` |
685
+ | Charts | `addSlideChart`, `getSlideCharts`, `setChartSpec` — kinds: `bar`, `column`, `line`, `pie`, `doughnut`, `area`; axis tick labels via `categoryAxisTickLabelPos` / `valueAxisTickLabelPos` / `secondaryValueAxis.tickLabelPos`; axis line / gridline widths via `valueAxisLineWidthEmu`, `valueAxisMajorGridlineWidthEmu` and their category / secondary-axis mirrors; series `lineColor` / `markerColor` / `markerLineColor`; `dataLabels.showLeaderLines` |
686
+ | Theme | `getPresentationTheme` / `setPresentationTheme` — color scheme (`accent1`..`accent6`, `dark1`, `light1`, `hyperlink`, ...); `getPresentationFonts` / `setPresentationFonts` — major / minor Latin, East Asian, and complex-script faces |
687
+ | Groups | `groupShapes`, `ungroupShapes`, `getGroupChildren`, `getGroupTransform` |
688
+ | Text autofit | `setShapeTextAutoFit` / `getShapeTextAutoFit`, `getShapeTextAutoFitParams` |
689
+ | Text 3-D (WordArt bevels) | `setShapeText3D` / `getShapeText3D` — `<a:scene3d>` camera and light rig, `<a:sp3d>` top bevel, extrusion, material, contour color |
690
+ | Preset adjustments | `setShapeAdjustValues`; `getShapeCustomGeometry` (custom geometry is read-only) |
691
+ | Document properties | `getCoreProperties` / `setCoreProperties`, `touchModified`, `getThumbnail` / `setThumbnail` / `removeThumbnail` |
692
+ | Package inspection | `listPackageParts`, `readPackagePart`, `getMediaParts`, `getOrphanMediaPartNames`, `getPackageSize`, `compactPackage` |
693
+ | Validation | `validatePresentation(pres)` — invariant checks, returns `ValidationIssue[]` |
694
+ | Units | `inches(n)`, `cm(n)`, `mm(n)`, `pt(n)`, `emu(n)` — return branded `Emu` numbers |
695
+
696
+ `setParagraphLevel` also accepts a UTF-16 text range and a relative level change,
697
+ so a selection can be indented in one update without rebuilding its text or links:
698
+
699
+ ```ts
700
+ setParagraphLevel(shape, { start: 0, end: 24 }, { offset: 1 });
701
+ const levels = getParagraphLevel(shape, { start: 0, end: 24 });
702
+ ```
703
+
704
+ The end offset is exclusive; a collapsed range selects the caret's paragraph.
705
+ Relative levels clamp to 0–8. Passing a paragraph index and an absolute level
706
+ continues to edit that single paragraph.
707
+
708
+ ### Outline view state
709
+
710
+ `getCollapsedOutlineSlides(presentation)` returns collapsed slides in deck order.
711
+ Use `setSlideOutlineCollapsed(slide, true)` to hide a slide's body in PowerPoint's
712
+ outline view, or `false` to expand it. The setting survives a save/load round trip
713
+ without changing the slide's text. Pass an array of slides to update a selection
714
+ or the whole deck in one operation:
715
+
716
+ ```ts
717
+ setSlideOutlineCollapsed(getSlides(presentation)[0]!, true);
718
+ const collapsedSlides = getCollapsedOutlineSlides(presentation);
719
+ setSlideOutlineCollapsed(getSlides(presentation), false);
720
+ ```
721
+
722
+ ### Ordered shape batches
723
+
724
+ `setShapeZIndex(shape, index)` moves one object among its siblings. Pass an array
725
+ instead to insert a contiguous batch in the supplied back-to-front order:
726
+ `setShapeZIndex([third, first], 0)`. Shapes must share a parent container; duplicate
727
+ handles and mixed containers are rejected before mutation. Non-shape XML and
728
+ unselected siblings are preserved.
648
729
 
649
730
  Text formats (`TextFormat`, including a paragraph's `endFormat`) cover the Latin, East Asian and complex-script typefaces (`font`, `fontEastAsian`, `fontComplexScript` — `<a:latin>`, `<a:ea>`, `<a:cs>`). Each is authored and read on its own; setting one leaves the others as they were. Chart labels carry the Latin / East Asian pair and the complex-script slot on `ChartTextStyle`: `font` fills `<a:latin>` and `<a:ea>`, `fontComplexScript` fills `<a:cs>`, and neither implies the other. Rebuilding a typeface writes the `typeface` attribute only, so any `pitchFamily` / `charset` the source file carried on that element is dropped.
650
731
 
732
+ A run's colors take PowerPoint's theme tints the way gradient stops do: `colorTransforms` beside `color`, and inside `outline`, `shadow`, `innerShadow` and `glow`, writes `<a:lumMod>`, `<a:lumOff>`, `<a:tint>`, ... as children of that color, so `{ color: 'accent2', colorTransforms: [{ kind: 'lumMod', value: 0.4 }, { kind: 'lumOff', value: 0.6 }] }` stays linked to the theme. `getShapeRunFormat` reports them beside the unresolved color; the effective readers resolve them into `#RRGGBB` instead.
733
+
651
734
  Runs that name no face fall back to the theme's font scheme, which is also where a per-script list (`<a:font script="Thai" typeface="Cordia New"/>` and 46 siblings) lives. `createPresentation`'s blank deck carries Office's own list in both `majorFont` and `minorFont`.
652
735
 
653
736
  Authored XML text and attribute values must contain only XML 1.0 characters. Illegal C0 controls (except tab, LF, and CR), U+FFFE, U+FFFF, and unpaired UTF-16 surrogates throw an error identifying the code point. Remove these characters before authoring; valid supplementary characters such as emoji are preserved.
654
737
 
738
+ Object geometry can be locked like PowerPoint's Selection Pane:
739
+
740
+ ```ts
741
+ import { isShapeLocked, setShapeLocked } from '@office-kit/pptx';
742
+
743
+ setShapeLocked(shape, true);
744
+ console.log(isShapeLocked(shape)); // true
745
+ setShapeLocked([shape, anotherShape], false);
746
+ ```
747
+
748
+ Locks leave text editable and preserve unrelated drawing constraints. Group children
749
+ keep independent locks; include descendants when locking every object. These APIs
750
+ write drawing restrictions for editing applications; programmatic geometry setters
751
+ remain available.
752
+
655
753
  ## Preview and text-overflow checks
656
754
 
657
755
  [`@office-kit/pptx-preview`](packages/preview) is a companion package that
@@ -723,3 +821,11 @@ PRs are expected to:
723
821
  ## License
724
822
 
725
823
  [MIT](./LICENSE)
824
+
825
+ ## Trademarks
826
+
827
+ Microsoft, PowerPoint, Excel, Word and Office are trademarks of the Microsoft
828
+ group of companies. Keynote is a trademark of Apple Inc., and Google Slides is
829
+ a trademark of Google LLC. Office Kit is an independent open-source project and
830
+ is not affiliated with, sponsored by, or endorsed by any of them; these names
831
+ are used only to describe file-format compatibility.