Skip to content
Merged

Dev #25

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .cursorrules

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions AGENT.md

Large diffs are not rendered by default.

27 changes: 14 additions & 13 deletions ARCHITECTURE.md

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,25 @@ OpenFCPXMLKit uses **New Features**, **Improvements**, and **Bug Fixes** for eac

---

## [3.0.6](https://github.com/TheAcharya/OpenFCPXMLKit/releases/tag/3.0.6) - 2026-07-15

### ✨ New Features

- **Universal report Row column:** Excel and PDF tabular sheets (Markers, Keywords, Titles & Generators, Transitions, Video & Audio Effects, Speed Change Effects, Summary role-duration table, Media Summary, plus role inventory) include a 1-based **Row** column by default via `ReportColumnExclusion.ensuringRowColumn`. PDF multi-page / multi-column-set injection uses `allowsInjectedRowColumn` / `preparePaginatedTable(allowInjectedRowColumn:)`. CLI `--exclude-column Row` (aliases: Row Numbers, Row Number) omits Row everywhere.

### 🔧 Improvements

- **Summary Excel layout:** Project title moves to **B1** so column A stays a narrow **Row** column; title column width uses a generous autofit range (`summaryProjectTitleColumnWidth`).
- **PDF cover notes:** Black “About This PDF Export” header band with white `info.circle` SF Symbol; tightened cover body copy (default Row; exclude via `--exclude-column Row`).
- **Test suite:** Expanded to **960** tests listed in `swift test --list-tests` (**957** in `OpenFCPXMLKitTests`: 954 XCTest + 3 Swift Testing `@Test`; plus **3** optional `ExcelReportTest`).
- **Documentation:** Manual **19 — Reporting** / **16 — CLI**, CLI README, `AGENT.md`, `.cursorrules`, `ARCHITECTURE.md` (§2.7 + mermaid test counts), `Tests/README.md`, and `Tests/ExcelReportTest/README.md` updated for universal Row, Summary **B1**, PDF cover polish, and test counts.

### 🐛 Bug Fixes

- **Summary Row column width:** Long project titles no longer inflate the Excel **Row** column when the title shared column A.

---

## [3.0.5](https://github.com/TheAcharya/OpenFCPXMLKit/releases/tag/3.0.5) - 2026-07-14

### ✨ New Features
Expand Down
2 changes: 1 addition & 1 deletion Documentation/Manual/00-Index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Complete manual and usage guide for **OpenFCPXMLKit**, a Swift 6 framework for F
| [16 — CLI](16-CLI.md) | Experimental command-line interface (OpenFCPXMLKit-CLI) |
| [17 — Examples](17-Examples.md) | End-to-end workflows and code examples |
| [18 — Cross-Platform & iOS](18-Cross-Platform-iOS.md) | XML abstraction layer, OFKXML protocols, Foundation vs AEXML backends, iOS support |
| [19 — Reporting, Excel & PDF Export](19-Reporting.md) | Report builder, ReportOptions, ReportTimecodeFormat, ReportBuildPhase progress order, report sections, column/disabled-clip exclusion, RoleDisplayPreference, XLKit workbook export, CoreGraphics PDF export (TOC colour chips, column expansion after exclusions), and shared row colour policy |
| [19 — Reporting, Excel & PDF Export](19-Reporting.md) | Report builder, ReportOptions, ReportTimecodeFormat, ReportBuildPhase progress order, report sections, universal **Row** column (`ensuringRowColumn`), column/disabled-clip exclusion, RoleDisplayPreference, XLKit workbook export (Summary **B1**), CoreGraphics PDF export (cover notes, TOC colour chips, column expansion after exclusions), and shared row colour policy |

---

Expand Down
2 changes: 1 addition & 1 deletion Documentation/Manual/16-CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Common values:

| CLI value | Effect |
|-----------|--------|
| `Row Numbers` | Removes the Row index column on inventory sheets |
| `Row` / `Row Numbers` | Removes the Row index column from **every** Excel and PDF tabular sheet, including PDF multi-page Row injection |
| `Role Subrole` | Removes Role ▸ Subrole |
| `Reel`, `Scene`, `Take` | Removes the named fixed column |
| `Metadata` | Removes all dynamic metadata key columns on role inventory sheets |
Expand Down
2 changes: 1 addition & 1 deletion Documentation/Manual/18-Cross-Platform-iOS.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ let version = root?.stringValue(forAttributeNamed: "version")

## Testing

- The `OpenFCPXMLKitTests` suite (**948 tests** listed under that target: 945 XCTest + 3 Swift Testing `@Test`) runs on **macOS** and uses the Foundation backend. `swift test --list-tests` also lists **3** optional `ExcelReportTest` integration tests (**951** total).
- The `OpenFCPXMLKitTests` suite (**957 tests** listed under that target: 954 XCTest + 3 Swift Testing `@Test`) runs on **macOS** and uses the Foundation backend. `swift test --list-tests` also lists **3** optional `ExcelReportTest` integration tests (**960** total).
- **iOS** is supported for building the library (e.g. iOS Simulator); running the same tests on iOS is not required for CI because they depend on Foundation XML. AEXML parity and structural validation are covered by tests that run on macOS.

---
Expand Down
32 changes: 18 additions & 14 deletions Documentation/Manual/19-Reporting.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ A section property is `nil` when that section was not requested. Every section c

### Sections and columns

**Row column (all tabular sheets):** Excel and PDF export prepend a 1-based **Row** column to every tabular sheet — Selected Roles Inventory and per-role sheets, Markers, Keywords, Titles & Generators, Transitions, Video & Audio Effects, Speed Change Effects, the Summary role-duration table, and Media Summary — unless `ReportColumn.row` is excluded. Inventory sheets include Row in their layout; other sheets receive it at export via **`ReportColumnExclusion.ensuringRowColumn`**. PDF pagination pins or injects the same column for multi-page / multi-column-set tables (see [PDF export](#pdf-export)).

#### Role inventory

**RoleInventoryReportSection** contains:
Expand Down Expand Up @@ -210,38 +212,38 @@ Use **RoleInventoryColumnLayout** (internal layout helper) or `RoleClipReportRow

#### Markers

**MarkersReportSection** of **MarkerReportRow**: Marker Name, Type, Notes, Position, Clip Name, Role ▸ Subrole, Reel, Scene, Source Position.
**MarkersReportSection** of **MarkerReportRow**: **Row**, Marker Name, Type, Notes, Position, Clip Name, Role ▸ Subrole, Reel, Scene, Source Position. (**Row** is added at export unless excluded.)

**MarkerReportType**: `.standard`, `.incompleteToDo`, `.completedToDo`, `.chapter`.

#### Keywords

**KeywordsReportSection** of **KeywordReportRow**: Keyword, Notes, Timeline In/Out, Duration, Clip Name, Role ▸ Subrole, Reel, Scene.
**KeywordsReportSection** of **KeywordReportRow**: **Row**, Keyword, Notes, Timeline In/Out, Duration, Clip Name, Role ▸ Subrole, Reel, Scene.

#### Titles & Generators

**TitlesReportSection** of **TitleReportRow**: Clip Name, Enabled, Apple, Role ▸ Subrole, Timeline In/Out, Duration, Font, Title Text.
**TitlesReportSection** of **TitleReportRow**: **Row**, Clip Name, Enabled, Apple, Role ▸ Subrole, Timeline In/Out, Duration, Font, Title Text.

#### Transitions

**TransitionsReportSection** of **TransitionReportRow**: Transition, Category, Apple, Timeline In/Out, Duration.
**TransitionsReportSection** of **TransitionReportRow**: **Row**, Transition, Category, Apple, Timeline In/Out, Duration.

#### Video & Audio Effects

**EffectsReportSection** of **EffectReportRow**: Effect, Settings, Enabled, Apple, Clip Name, Role ▸ Subrole, Timeline In/Out.
**EffectsReportSection** of **EffectReportRow**: **Row**, Effect, Settings, Enabled, Apple, Clip Name, Role ▸ Subrole, Timeline In/Out.

#### Speed Change Effects

**SpeedChangeEffectsReportSection** (reuses **EffectReportRow**).
**SpeedChangeEffectsReportSection** (reuses **EffectReportRow**, including leading **Row** at export).

#### Summary

**SummaryReportSection** (`defaultSheetName`: **Summary**):

- `projectSummary: ProjectSummary?` — title, duration, resolution, frame rate, audio sample rate.
- `roleDurations: [SummaryRoleDurationRow]` — Role ▸ Subrole, Estimated Total, % of Total.
- `roleDurations: [SummaryRoleDurationRow]` — **Row**, Role ▸ Subrole, Estimated Total, % of Total (Row prepended at export).

In Excel export, the **project title** uses the table header style (bold white text on a black fill). Project metrics and role-duration rows use default **black** text (no role colour coding). The **% of Total** value is stored as a fraction (for example `0.42`) and written as a numeric cell with percentage number format (`0.0%`).
In Excel export, the **project title** is written in **B1** (not A1) with table-header style (bold white text on a black fill) so column **A** stays a narrow **Row** index. Column **B** is auto-fit with a generous title-based minimum width. Project metrics and role-duration body cells use default **black** text (no role colour coding). The **% of Total** value is stored as a fraction (for example `0.42`) and written as a numeric cell with percentage number format (`0.0%`).

See [Sheet order and formatting](#sheet-order-and-formatting) for colours on other sheets.

Expand All @@ -251,7 +253,7 @@ See [Sheet order and formatting](#sheet-order-and-formatting) for colours on oth

- `missingMediaPaths: [String]` — file paths that could not be resolved on disk.

The sheet renders a **Missing Media** section with a black header row (matching other report sheets). Each missing file path is written in **red** text (`#FF0000`). Relative paths are resolved against `mediaBaseURL` when provided.
The sheet renders **Row** | **Missing Media** (black header row). Each missing file path is written in **red** text (`#FF0000`). Relative paths are resolved against `mediaBaseURL` when provided.

---

Expand Down Expand Up @@ -280,11 +282,13 @@ let report = try await fcpxml.buildReport(options: options)

At build time, labels are resolved to `Set<ReportColumn>` and stored on **`Report.excludedColumns`**. Excel and PDF export apply the same filtering to role inventory sheets, markers, keywords, titles, transitions, effects, speed-change effects, summary (including project metric cells), and media summary.

**`ReportColumnExclusion.filter`** calls **`ensuringRowColumn`** first (prepends the 1-based **Row** column unless `.row` is excluded), then removes other excluded columns. PDF table pagination uses **`allowsInjectedRowColumn(excluded:)`** so excluding `.row` also suppresses multi-page / multi-column-set Row injection (`preparePaginatedTable(allowInjectedRowColumn:)`).

### ReportColumn cases

| Case | Primary header | Notes |
|------|----------------|-------|
| `.row` | Row | Row index on inventory sheets |
| `.row` | Row | 1-based row index on **all** Excel/PDF tabular sheets (inventory, Markers … Media Summary, Summary role-duration table). Also suppresses PDF multi-page / multi-column-set Row injection. Aliases: Row Numbers, Row Number. |
| `.roleSubrole` | Role ▸ Subrole | |
| `.clipName` | Clip Name | |
| `.category` | Category | |
Expand Down Expand Up @@ -420,9 +424,9 @@ Role/subrole cells are colour-coded by category on inventory sheets (video/capti

Section sheets without a Category column use sheet-specific colour rules: **Keywords** rows are always blue; **Titles & Generators** infer purple for title roles; **Video & Audio Effects** and **Speed Change Effects** infer blue for video/VFX/title-host rows and green for audio roles; **Transitions** use gray text.

The **Summary** sheet uses default black text for project metrics and role-duration data. The **project title** (row 1) and column header rows use the standard table header style: bold white text on a black fill.
The **Summary** sheet uses default black text for project metrics and role-duration data. The **project title** is in **B1** (table header style: bold white on black) so column **A** remains a narrow **Row** index; column **B** uses a generous title-based width. Role-duration column headers (including **Row**) and body cells follow the same black/white header convention as other sheets.

The **Media Summary** sheet lists missing file paths in **red** (`#FF0000`).
The **Media Summary** sheet lists missing file paths in **red** (`#FF0000`), with a leading **Row** column unless excluded.

**Markers** use marker-type colours for the whole row: standard blue, incomplete to-do red, completed to-do green, chapter orange.

Expand Down Expand Up @@ -462,7 +466,7 @@ Throws **ReportPDFExportError** (`couldNotCreateDocument`, `couldNotWriteFile`)

PDF export mirrors Excel **section order** and **sheet names** (via `FCPXMLReportPDFSheetPlan`):

1. **Cover page** — project name, event name (when present), generated timestamp, experimental-notice info box, and `exportBrandingText`.
1. **Cover page** — project name, event name (when present), generated timestamp, `exportBrandingText`, and an info box with a **black header band** (white **`info.circle`** SF Symbol + title **“About This PDF Export”**) and a smaller body paragraph describing experimental A4-landscape export, pagination/truncation, the default **Row** column (excludable like Excel), tinted matching pages, and a pointer to the companion `.xlsx` for the full dataset.
2. **Table of contents** — one or more pages listing every included section with start page numbers (built dynamically in a two-pass render so page numbers are accurate). The TOC is not a workbook sheet in Excel; it is PDF-only. Each TOC row uses the **same colour index** as that sheet’s content pages: a small **accent-palette colour chip** beside the row number, plus a light **content-tint wash** on the row (Menlo text stays high-contrast on the near-white wash).
3. **Content pages** — each enabled section, in workbook order, with running header (project name + section title) and footer (branding + page number).

Expand All @@ -472,7 +476,7 @@ Per-section presentation:
- **Row colours** — the same rules as Excel (`FCPXMLReportRowColorPolicy`): role inventory category colours, marker-type colours, keywords/titles/effects/transitions inference, red missing-media paths.
- **Tables** — black header row with white text; body uses Menlo. Column widths are measured from content (clamped for horizontal packing), then **expanded proportionally to fill the A4 landscape content width** when leftover space remains (for example after many `excludedColumns`). Wide tables still **paginate horizontally** into column sets (running header shows `Columns 2 of 5` when chunked); each set also fills the page width. Pinned **Row** columns keep their packed width.
- **Truncation** — cell text that exceeds column width is ellipsized (`…`). For the full untruncated dataset, use the Excel export.
- **Row traceability** — on multi-page or multi-column-set tables, a **Row** (`#`) column is injected and pinned on the left when not already present.
- **Row column** — included by default on all tabular content (same as Excel) via **`ensuringRowColumn`**. On multi-page or multi-column-set tables, Row is **pinned** on the left; if headers lack Row and injection is allowed, PDF injects it via **`preparePaginatedTable(allowInjectedRowColumn:)`**. Exclude `ReportColumn.row` (CLI `--exclude-column Row`) to omit Row everywhere, including continuation pages.

### Configuration reflected in PDF

Expand Down
4 changes: 2 additions & 2 deletions Documentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ The manual is split into **chapters** for easier navigation and maintenance:
| [15 — Errors & Utilities](Manual/15-Errors-Utilities.md) | Error types, ErrorHandling, ProgressBar, FCPXMLUID |
| [16 — CLI](Manual/16-CLI.md) | Experimental command-line interface (OpenFCPXMLKit-CLI) |
| [17 — Examples](Manual/17-Examples.md) | End-to-end workflows and code examples |
| [19 — Reporting, Excel & PDF Export](Manual/19-Reporting.md) | Report builder, ReportOptions, ReportTimecodeFormat, ReportBuildPhase progress order, report sections, column/disabled-clip exclusion, RoleDisplayPreference, XLKit workbook export, CoreGraphics PDF export (TOC colour chips, column expansion after exclusions), and shared row colour policy |
| [19 — Reporting, Excel & PDF Export](Manual/19-Reporting.md) | Report builder, ReportOptions, ReportTimecodeFormat, ReportBuildPhase progress order, report sections, universal **Row** column (`ensuringRowColumn`), column/disabled-clip exclusion, RoleDisplayPreference, XLKit workbook export (Summary **B1**), CoreGraphics PDF export (cover notes, TOC colour chips, column expansion after exclusions), and shared row colour policy |

The manual covers the **entire public API** with examples: core operations, async/await, file I/O, validation, timeline creation and manipulation, metadata, media processing, typed models (including Live Drawing, HiddenClipMarker, SmartCollection match rules, Format/Asset 1.13+), version conversion, reporting and Excel/PDF export, CLI, and utilities. **Chapter 18** describes the cross-platform XML abstraction (OFKXML protocols, Foundation vs AEXML backends) and **iOS 26+** support. **Chapter 19** covers the reporting subsystem (report builder, sections, role inventory columns, Summary and Media Summary sheets, timecode display formats, inventory-first progress phases, global column and disabled-clip exclusion, XLKit `.xlsx` export, CoreGraphics `.pdf` export with cover/TOC colour chips/pagination/column-width expansion, and shared workbook row colours).
The manual covers the **entire public API** with examples: core operations, async/await, file I/O, validation, timeline creation and manipulation, metadata, media processing, typed models (including Live Drawing, HiddenClipMarker, SmartCollection match rules, Format/Asset 1.13+), version conversion, reporting and Excel/PDF export, CLI, and utilities. **Chapter 18** describes the cross-platform XML abstraction (OFKXML protocols, Foundation vs AEXML backends) and **iOS 26+** support. **Chapter 19** covers the reporting subsystem (report builder, sections, universal **Row** column, role inventory columns, Summary **B1** / Media Summary sheets, timecode display formats, inventory-first progress phases, global column and disabled-clip exclusion, XLKit `.xlsx` export, CoreGraphics `.pdf` export with cover notes / TOC colour chips / pagination / column-width expansion, and shared workbook row colours).

---

Expand Down
Loading