10 KiB
Edison PowerPoint Add-in Developer Documentation
This document provides detailed technical information for developers working on the Edison PowerPoint Add-in.
Architecture Overview
Edison is a PowerPoint add-in built with:
- TypeScript for type-safe code
- React for UI components
- Office.js API for PowerPoint integration
- Fluent UI for Microsoft-style interface components
The application follows a component-based architecture where each tool is encapsulated in its own React component.
UML Diagrams
To better understand the architecture and structure of the Edison PowerPoint Add-in, refer to the following UML diagrams:
- UML Diagrams Index - Overview and index of all UML diagrams
- Component Relationships - Shows the relationships between React components
- Project Structure - Illustrates the file and directory organization
- Data Flow - Demonstrates the flow of data and interactions
These diagrams provide visual representations of the application's architecture, component relationships, and data flow patterns, which can help new developers understand the codebase more quickly.
Project Structure
/
├── assets/ # Images and icons
├── dist/ # Build output (generated)
├── src/
│ ├── commands/ # Command handlers
│ │ ├── commands.html # HTML for command UI
│ │ └── commands.ts # Command implementations
│ └── taskpane/ # Main add-in UI
│ ├── components/ # React components
│ │ ├── ActionButton.tsx # Reusable button with error handling
│ │ ├── AlignmentButtons.tsx
│ │ ├── App.tsx # Main application component
│ │ ├── ConfidentialButtons.tsx
│ │ ├── DraftButtons.tsx
│ │ ├── GridGuidelineManager.tsx
│ │ ├── Header.tsx
│ │ ├── InsertTitles.tsx
│ │ ├── MatchProperties.tsx
│ │ ├── MatchSizes.tsx
│ │ ├── ProgressBarButtons.tsx
│ │ ├── RoundImage.tsx
│ │ ├── Section.tsx # Reusable section component
│ │ ├── SmartTextFormatter.tsx
│ │ ├── SwapPositions.tsx
│ │ └── commonStyles.tsx
│ ├── types/ # TypeScript type definitions
│ │ └── office-types.ts # Office API type utilities
│ ├── index.tsx # Entry point
│ └── taskpane.html # Main HTML container
├── babel.config.json # Babel configuration
├── manifest.xml # Add-in manifest
├── package.json # Dependencies and scripts
├── tsconfig.json # TypeScript configuration
└── webpack.config.js # Webpack configuration
Development Environment Setup
Prerequisites
- Node.js (LTS version recommended)
- npm
- Microsoft PowerPoint (desktop version)
Setup Steps
-
Clone the repository:
git clone https://github.com/your-org/edison-powerpoint-addin.git cd edison-powerpoint-addin -
Install dependencies:
npm install -
Build the project:
npm run build:dev -
Start the development server:
npm run dev-server -
Start the add-in in PowerPoint:
npm run start
Local Development Certificates
Office Add-ins require HTTPS even for local development. The office-addin-dev-certs package is used to create and install self-signed certificates for development.
If you encounter certificate issues, run:
npx office-addin-dev-certs install
Component Development Guidelines
Reusable Components
ActionButton
A reusable button component that handles error states, loading states, and consistent styling:
import ActionButton from "./ActionButton";
// In your component:
<ActionButton
title="Match Sizes"
icon={<ArrowFitInRegular />}
onClick={myAsyncFunction}
/>
Section
A consistent container for organizing the UI:
import Section from "./Section";
// In your component:
<Section title="My Feature Group">
<MyFeatureComponent />
</Section>
Creating a New Tool
- Create a new component file in
src/taskpane/components/ - Import the necessary Office.js APIs and React hooks
- Use the StatusContext for user feedback
- Follow the pattern of existing components:
- Use the
PowerPoint.run()method for PowerPoint operations - Provide clear success/error messaging
- Handle selection states appropriately
- Use the
Example component structure:
import * as React from "react";
import { useState } from "react";
import { Button } from "@fluentui/react-components";
import { useStatusContext } from "./App";
const MyNewTool: React.FC = () => {
const { setStatusMessage, setStatusType, isProcessing, setIsProcessing } = useStatusContext();
const performAction = async () => {
setIsProcessing(true);
try {
await PowerPoint.run(async (context) => {
// Implement your PowerPoint operations here
await context.sync();
});
setStatusMessage("Operation completed successfully!");
setStatusType("success");
} catch (error) {
setStatusMessage(`Error: ${error.message}`);
setStatusType("error");
console.error("Operation error:", error);
} finally {
setIsProcessing(false);
}
};
return (
<Button onClick={performAction} disabled={isProcessing}>
My New Tool
</Button>
);
};
export default MyNewTool;
Common PowerPoint.js Operations
Type-Safe Utilities
The application provides type-safe utility functions in src/taskpane/types/office-types.ts:
// Get error message safely from any error type
const errorMsg = getErrorMessage(error);
// Check if a shape is an image
if (isPictureShape(shape)) {
// It's a picture shape
}
// Get the first selected slide
const slide = getFirstSelectedSlide(context);
// Select shapes by ID
selectShapesById(slide, [shape1.id, shape2.id]);
Selecting Shapes
const shapes = context.presentation.getSelectedShapes();
shapes.load("items");
await context.sync();
Working with Slide Masters
const slideMasters = context.presentation.slideMasters;
slideMasters.load("items");
await context.sync();
Creating Shapes
const shape = slide.shapes.addGeometricShape("Rectangle");
shape.left = 100;
shape.top = 100;
shape.height = 50;
shape.width = 50;
await context.sync();
Status System
The application includes a status system that provides feedback to users:
- Success: Operation completed successfully
- Warning: Operation completed with concerns
- Error: Operation failed
- Processing: Shows a spinner while operations are in progress
Use the status context in your components:
const {
statusMessage,
setStatusMessage,
statusType,
setStatusType,
isProcessing,
setIsProcessing
} = useStatusContext();
Build and Deployment
Development Build
npm run build:dev
Production Build
npm run build
Manifest Validation
npm run validate
This validates the manifest.xml file against the Office Add-in schema.
Testing
Currently, the project doesn't have automated tests. This is an area for future improvement.
Recommended testing approach:
- Manual testing in PowerPoint
- Implementation of unit tests for individual utilities
- Integration tests for PowerPoint API interactions
Performance Considerations
Optimizing context.sync() calls
A key performance optimization is to batch context.sync() calls:
// BAD: Calling context.sync() in a loop
for (let i = 0; i < shapes.items.length; i++) {
shapes.items[i].load("name");
await context.sync(); // Slow! One network roundtrip per shape
if (shapes.items[i].name === "Target") {
// Do something
}
}
// GOOD: Batching context.sync() calls
// Load all properties at once
for (let i = 0; i < shapes.items.length; i++) {
shapes.items[i].load("name");
}
await context.sync(); // Single network roundtrip for all shapes
// Process the data locally
for (let i = 0; i < shapes.items.length; i++) {
if (shapes.items[i].name === "Target") {
// Do something
}
}
Additional performance tips:
- Use memoization for expensive calculations
- Ensure proper cleanup of event listeners
- Use the ActionButton component for consistent loading states
- Consider using Web Workers for heavy computations
Common Issues and Solutions
Add-in not loading in PowerPoint
- Verify the development server is running
- Check for certificate errors in the browser console
- Validate the manifest.xml file
PowerPoint API errors
- Ensure correct API version is being used
- Check the sequence of operations (some operations require specific order)
- Verify selections exist before operating on them
Best Practices
- Error Handling: Always use try/catch blocks with PowerPoint API calls and use proper types (see
office-types.ts) - User Feedback: Provide clear status messages for all operations using the StatusContext
- Accessibility: Ensure all UI elements have proper ARIA attributes and support keyboard navigation
- Theme Support: Use Fluent UI theme tokens for consistent theming
- Code Organization: Keep component files focused on a single responsibility
- Performance: Batch context.sync() calls and avoid calling them inside loops
- Reusability: Use custom hooks for common operations and shared components like ActionButton and Section
- Type Safety: Avoid using "any" type and leverage TypeScript's static typing
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request with a clear description of the changes