Skip to content

Fix PPTX connector endpoints to land on correct shape edges#260

Merged
hackerwins merged 3 commits into
mainfrom
fix/pptx-connector-site-index
May 17, 2026
Merged

Fix PPTX connector endpoints to land on correct shape edges#260
hackerwins merged 3 commits into
mainfrom
fix/pptx-connector-site-index

Conversation

@hackerwins

@hackerwins hackerwins commented May 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Connectors anchored to a target shape's left/right edge in PPTX
    (<a:stCxn idx="1"/> or idx="3") were landing on the opposite edge
    after import. Visible on slide 24 of the "Yorkie, 캐즘 뛰어넘기.pptx"
    deck: all four MVC-diagram arrows hit the wrong side while the
    connector frames themselves stayed correct.
  • Root cause: OOXML rect/roundRect cxnLst is ordered T, L, B, R
    but Waffle's FOUR_CARDINAL is N, E, S, W (i.e. T, R, B, L).
    parseCxnSp was passing the raw OOXML idx through as siteIndex
    without remapping, so indices 1 and 3 silently swapped meaning.
  • Fix: add ooxmlToWaffleSiteIndex (a [0, 3, 2, 1] lookup table) and
    route the attached-endpoint construction through it. Scope of the
    swap is documented as the T,L,B,R family; per-ShapeKind overrides
    for other presets remain deferred to slides-connectors PR2 (today
    harmless because getConnectionSites() is uniform).

Test plan

  • pnpm verify:fast — green (3398 tests across sheets/slides/docs/backend/frontend).
  • New unit tests in packages/slides/test/import/pptx/connector.test.ts:
    • Start endpoint: OOXML idx [0,1,2,3] → siteIndex [0,3,2,1].
    • End endpoint: same mapping on endCxn.
    • Unmapped target id collapses to kind: 'free', not a remapped attached endpoint.
  • Re-import "Yorkie, 캐즘 뛰어넘기.pptx" and visually confirm slide 24 MVC arrows resolve to the correct shape edges. (Recommended manual smoke for reviewers — original repro is at the user's environment.)

Backward compatibility

Decks imported before this fix have the buggy siteIndex values
persisted in Yorkie. They keep rendering at the wrong edge until
re-imported — the fix only changes the import path, not stored data.
PPTX import is one-shot so re-importing is the expected upgrade path.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Corrected connector endpoint attachment indices in imported PowerPoint decks that were previously swapped
    • Fixed connection site positioning for shapes with horizontal or vertical flips to match proper transform order
  • Tests

    • Added comprehensive test coverage for PPTX connector endpoint parsing and flip behavior with various flip combinations
  • Documentation

    • Added documentation detailing connector attachment site remapping fixes and coordinate transformation specifications

Review Change Stack

OOXML's `rect`/`roundRect` cxnLst is ordered T, L, B, R, but Waffle's
`FOUR_CARDINAL` is N, E, S, W — i.e. T, R, B, L. parseCxnSp was passing
the raw OOXML idx through as siteIndex, so every connector anchored to
a left/right edge in PPTX landed on the opposite edge after import.
Visible on the imported "Yorkie, 캐즘 뛰어넘기.pptx" deck (slide 24):
all four MVC-diagram arrows hit the wrong side of their target shapes
while the connector frames themselves stayed correct, which made the
mismatch look like a routing bug instead of an index bug.

Swap idx 1 ↔ 3 when materializing the attached endpoint, and add a
unit test through parseSpTree covering all four cardinal indices.
Per-shape cxnLst overrides (slides-connectors PR2) will need to
replace this static swap with a per-ShapeKind map.
Scope-tighten the OOXML→Waffle helper comment to the T,L,B,R family
(rect, roundRect, *Rect variants, plaque, bevel, flowChartTerminator);
other prsts have their own cxnLst orderings that PR2's per-ShapeKind
overrides will need to address. Today the swap is harmless on those
shapes only because getConnectionSites() returns FOUR_CARDINAL
uniformly — call that out so the next person doesn't assume the helper
is universal. Also correct the fallback wording: out-of-range siteIndex
falls back to sites[0] (N) in connector-frame.ts, not (0,0). Replace
the two if-statements with a `[0, 3, 2, 1]` lookup table since PR2
will turn this into a per-shape map anyway.

Add coverage for the `end` endpoint code path and the free-fallback
path when the stCxn target id has no matching sp in the slide.

Note in lessons that pre-fix imports have the buggy siteIndex
persisted in Yorkie; only re-imported decks pick up the fix.
@coderabbitai

coderabbitai Bot commented May 17, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 31ad085d-31a8-405e-89bc-f6d2e208571c

📥 Commits

Reviewing files that changed from the base of the PR and between aa056f3 and dd7ce00.

📒 Files selected for processing (6)
  • docs/tasks/active/20260517-pptx-connector-site-index-lessons.md
  • docs/tasks/active/20260517-pptx-connector-site-index-todo.md
  • packages/slides/src/import/pptx/shape.ts
  • packages/slides/src/view/canvas/connection-sites/index.ts
  • packages/slides/test/import/pptx/connector.test.ts
  • packages/slides/test/view/canvas/connection-sites/connection-sites.test.ts

📝 Walkthrough

Walkthrough

Fixes OOXML connector endpoint attachment site-index mapping (T,L,B,R → N,E,S,W) via a new remapping helper and integration into resolveEndpoint. Separately corrects siteWorldPos flip/rotation transform order to match paint-time behavior. Both changes include test coverage and retrospective documentation of lessons learned.

Changes

PPTX Connector Site Index and Flip/Rotation Fixes

Layer / File(s) Summary
OOXML connector site index remapping
packages/slides/src/import/pptx/shape.ts, packages/slides/test/import/pptx/connector.test.ts, docs/tasks/active/20260517-pptx-connector-site-index-todo.md
Introduces ooxmlToWaffleSiteIndex() constant mapping and integration point in resolveEndpoint to translate OOXML cxnLst indices (T,L,B,R order 0–3) into Waffle's FOUR_CARDINAL site indices (N,E,S,W order). New test suite validates the remapping for start and end attachment points, and verifies fallback behavior when target shapes are missing. Task documentation records the observed inversion problem and implementation approach.
siteWorldPos flip and rotation transform fix
packages/slides/src/view/canvas/connection-sites/index.ts, packages/slides/test/view/canvas/connection-sites/connection-sites.test.ts, docs/tasks/active/20260517-pptx-connector-site-index-todo.md
Corrects siteWorldPos to apply flipH/flipV transforms to local coordinates before rotation into world space, matching paint-time transform order. Outward-normal angle is adjusted for flips before element rotation is added. Expanded test suite covers flipH, flipV, combined flips, and flip-with-rotation interactions, validating position mirroring and angle normalization.
Lessons and design invariants
docs/tasks/active/20260517-pptx-connector-site-index-lessons.md
Documents OOXML ordering differences, paint-transform–site-resolution coupling invariants, backward-compatibility expectations for already-imported decks, and guidance on testing via parseSpTree rather than private functions.

Sequence Diagram(s)

sequenceDiagram
  participant ImportPPTX as PPTX Import
  participant ParseCxn as parseCxnSp
  participant ResolveEp as resolveEndpoint
  participant IndexMap as ooxmlToWaffleSiteIndex
  participant Output as AttachedEndpoint
  ImportPPTX->>ParseCxn: connector with cxnLst idx
  ParseCxn->>ResolveEp: endpoint (attached, idx)
  ResolveEp->>IndexMap: OOXML idx (0–3)
  IndexMap->>Output: Waffle siteIndex remapped
Loading
flowchart LR
  A["Frame local coords"] --> B["Apply flipH/flipV"]
  B --> C["Rotate into world space"]
  C --> D["World position + angle"]
  E["Outward angle"] --> F["Apply flipH/flipV to angle"]
  F --> G["Add element rotation"]
  G --> D
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • wafflebase/wafflebase#251: Introduces Frame flip propagation and element-renderer flip+rotation transform logic that the siteWorldPos fix depends on.

Poem

A rabbit bounds through indices with care,
OOXML swapped for Waffle's square—
North, East, South, West align just right,
While flips and rotations dance in sight! 🐰✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/pptx-connector-site-index

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented May 17, 2026

Copy link
Copy Markdown
Contributor

Verification: verify:self

Result: ✅ PASS in 204.3s

Lane Status Duration
sheets:build ✅ pass 13.1s
docs:build ✅ pass 12.1s
slides:build ✅ pass 12.8s
verify:fast ✅ pass 119.8s
frontend:build ✅ pass 18.7s
verify:frontend:chunks ✅ pass 0.3s
backend:build ✅ pass 4.8s
cli:build ✅ pass 2.1s
verify:entropy ✅ pass 20.5s

Verification: verify:integration

Result: ✅ PASS

@codecov

codecov Bot commented May 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

`element-renderer.ts` paints flipped shapes by mirroring the path
around the frame centre after rotation, but `siteWorldPos` was only
applying rotation — `frame.flipH`/`frame.flipV` were silently dropped.
OOXML `cxnLst` indices reference pre-flip logical sites, so an
attached connector targeting a `flipH=1` shape resolved to the
unmirrored edge while the shape painted as mirrored. Result: in the
"Yorkie, 캐즘 뛰어넘기.pptx" deck, slide 24 looked correct after the
prior idx-swap fix (no flipped shapes), but slide 26's right-side MVC
group (all `flipH=1`) still routed every connector to the wrong side.

Mirror `lx`/`ly` around the frame centre before rotation, and reflect
the site angle (`flipH: π - a`, `flipV: -a`). Matches the paint
ordering `translate(centre) → rotate → scale(flip) → translate(-w/2)`
in `element-renderer.ts:50-64`. Knock-on benefit: user-flipped shapes
in the editor now drag their attached connectors along to the
mirrored edge, matching PowerPoint / Google Slides behaviour.
@hackerwins hackerwins changed the title Remap PPTX connector cxnLst idx to Waffle FOUR_CARDINAL on import Fix PPTX connector endpoints to land on correct shape edges May 17, 2026
@hackerwins
hackerwins merged commit 3519485 into main May 17, 2026
1 check passed
@hackerwins
hackerwins deleted the fix/pptx-connector-site-index branch May 17, 2026 14:06
hackerwins added a commit that referenced this pull request May 18, 2026
These seven slides + PPTX tasks shipped (PRs #238, #240, #241, #255,
#259, #260, #261) but their checklist boxes were never ticked during
execution, so the archive script left them in active/. Sweep the
checkboxes to reflect what actually landed, add lessons files for the
two that were missing (keyboard-shortcuts, presentation-mode), and
convert the keyboard-shortcuts onLinkRequest popover bullet from a
checkbox to a "Deferred (follow-up)" note so the gate stops blocking on
work that is intentionally out of scope.

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant