Skip to content

feat(drawio): infer shape person on re-import for round-trip fidelity#26

Merged
sraphaz merged 3 commits intomainfrom
feat/drawio-infer-shape-person-roundtrip
Mar 14, 2026
Merged

feat(drawio): infer shape person on re-import for round-trip fidelity#26
sraphaz merged 3 commits intomainfrom
feat/drawio-infer-shape-person-roundtrip

Conversation

@sraphaz
Copy link
Copy Markdown
Owner

@sraphaz sraphaz commented Mar 4, 2026

feat(drawio): infer shape person on re-import for round-trip fidelity

Summary

Follow-up to the Draw.io person-shape fix (upstream PR #2682). That PR changes export to use shape=actor instead of shape=umlActor for LikeC4 shape person and updates the parser so inferKind recognizes shape=actor as actor. This PR adds round-trip fidelity on the import side: re-imported actor cells now get an explicit style { shape person } in the emitted .c4 source, so the round-trip is symmetric (export: person → shape=actor; import: shape=actor → actor with shape person).

Changes

  • packages/generators/src/drawio/parse-drawio.ts
    inferShape() now returns 'person' when the DrawIO cell style contains shape=actor, shape=person, or umlactor. Existing logic for cylinder, document, and rectangle is unchanged.

  • packages/generators/src/drawio/parse-drawio.spec.ts
    New test: "parse DrawIO to LikeC4 - vertex with shape=actor emits actor with style { shape person } for round-trip fidelity" (minimal diagram with one vertex style="shape=actor;..."). Asserts that the output contains actor 'User' and shape person, and snapshot updated.

  • .changeset/drawio-infer-shape-person-roundtrip.md
    Patch changeset for @likec4/generators.

Why

After likec4#2682, re-importing a .drawio that contains an actor (with shape=actor) already yields name = actor 'title' and renders correctly, because actor implies the person shape by default. This PR only makes the emitted source explicit: the .c4 file will include style { shape person } for those elements, so the round-trip is fully symmetric and the source faithfully reflects the diagram.

Checklist

  • Change is minimal and focused on round-trip shape fidelity
  • Tests added/updated: parse-drawio.spec.ts + snapshot
  • Tests run: pnpm test -- packages/generators/src/drawio/parse-drawio.spec.ts (or from repo root with vitest and node_modules/.bin in PATH)
  • Changeset included for @likec4/generators (patch)
  • Commit follows conventional style (feat(drawio): ...)
  • CI passes on this branch (run on fork before submitting upstream)

Upstream

Intended as a small follow-up to likec4#2682. Can be proposed to upstream after likec4#2682 is merged, or in parallel at maintainers’ preference.

Summary by CodeRabbit

  • Bug Fixes

    • Improved Draw.io import so actor-shaped elements (actor/person variants) are consistently recognized and re-imported with an explicit person style and actor title for reliable round-trip fidelity.
  • Tests

    • Added a test covering actor-shaped Draw.io vertices to ensure correct round-trip mapping and output.
  • Changelog

    • Added changelog entry describing the Draw.io import behavior improvement.

inferShape() now returns 'person' when DrawIO cell style contains shape=actor, shape=person, or umlactor. Re-imported actor cells get explicit style { shape person } in emitted .c4.

Made-with: Cursor
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ea64812c-234f-45a2-9a5c-e56861fe4f24

📥 Commits

Reviewing files that changed from the base of the PR and between 71ab678 and 03eb4b2.

📒 Files selected for processing (2)
  • .changeset/drawio-infer-shape-person-roundtrip.md
  • packages/generators/src/drawio/parse-drawio.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/generators/src/drawio/parse-drawio.ts
  • .changeset/drawio-infer-shape-person-roundtrip.md

📝 Walkthrough

Walkthrough

Updates DrawIO import inference so shape=actor, shape=person, and umlactor are treated as a person/actor: imported actor vertices now produce an actor label and an explicit shape person style in emitted LikeC4 source for round-trip symmetry. (46 words)

Changes

Cohort / File(s) Summary
Shape inference logic
packages/generators/src/drawio/parse-drawio.ts
Added shape=actor to actor detection in inferKind() and expanded inferShape() to return 'person' for shape=actor, shape=person, or umlactor.
Test coverage
packages/generators/src/drawio/parse-drawio.spec.ts
Added a test and sample DrawIO XML verifying a vertex with shape=actor parses to actor 'User' and that emitted LikeC4 includes shape person; snapshot added.
Changelog / package metadata
.changeset/drawio-infer-shape-person-roundtrip.md
New changeset documenting Draw.io import/export round-trip fidelity for actor/person shapes and package patch metadata for @likec4/generators.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

🐰 I nibble XML by moonlight,
Actors hop in, then out just right,
Person style in every view,
Round-trip dancing, tidy and true,
A tiny thump for parser delight 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding inference of person shape on re-import to achieve round-trip fidelity for Draw.io actor shapes.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering the summary, specific changes to each file, rationale, and a detailed checklist. It provides sufficient context for understanding the round-trip fidelity changes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/drawio-infer-shape-person-roundtrip

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.

inferKind() now includes shape=actor so vertex with shape=actor is emitted as actor (not container). Aligns with upstream likec4#2682 and makes this branch pass ci:test without depending on likec4#2682 merge.

Made-with: Cursor
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d4aa31ac1c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (!style) return undefined
const s = style.toLowerCase()
// Actor/person shape (export uses shape=actor; legacy may have shape=person or umlactor)
if (s.includes('shape=actor') || s.includes('shape=person') || s.includes('umlactor')) return 'person'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Classify shape=actor cells as actor kind on import

This new inferShape branch makes shape=actor produce shape person, but inferKind still only treats umlactor and shape=person as actors, so Draw.io cells exported as shape=actor are still emitted as container declarations. In diagrams that rely on LikeC4’s current export format (shape=actor), the round-trip remains incorrect (container + person style instead of actor), which also makes the added actor snapshot expectation unreachable.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/generators/src/drawio/parse-drawio.ts (1)

556-574: ⚠️ Potential issue | 🔴 Critical

inferKind() not updated to recognize shape=actor — this is the root cause of the CI test failure.

The inferShape() function was updated to return 'person' for shape=actor, but inferKind() was not similarly updated. Line 564 only checks for umlactor and shape=person, but not shape=actor. This causes cells with style="shape=actor" to be emitted as container 'User' instead of actor 'User'.

🐛 Proposed fix to also recognize shape=actor in inferKind
 function inferKind(
   style: string | undefined,
   parentCell?: DrawioCell,
 ): 'actor' | 'system' | 'container' | 'component' {
   const s = style?.toLowerCase() ?? ''
   switch (true) {
     case !style:
       return parentCell?.style?.toLowerCase().includes('container=1') ? 'component' : 'container'
-    case s.includes('umlactor') || s.includes('shape=person'):
+    case s.includes('umlactor') || s.includes('shape=person') || s.includes('shape=actor'):
       return 'actor'
     case s.includes('swimlane'):
     case s.includes('container=1'):
       return 'system'
     case !!parentCell?.style?.toLowerCase().includes('container=1'):
       return 'component'
     default:
       return 'container'
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/generators/src/drawio/parse-drawio.ts` around lines 556 - 574, The
inferKind function currently checks for 'umlactor' and 'shape=person' but misses
'shape=actor', causing actor-shaped cells to be treated as containers; update
inferKind (the function named inferKind) so the actor check includes
s.includes('shape=actor') alongside s.includes('umlactor') and
s.includes('shape=person') (and ensure the lowercase-normalized s variable is
used), leaving the rest of the switch logic unchanged so cells with
style="shape=actor" resolve to 'actor'.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/generators/src/drawio/parse-drawio.ts`:
- Around line 556-574: The inferKind function currently checks for 'umlactor'
and 'shape=person' but misses 'shape=actor', causing actor-shaped cells to be
treated as containers; update inferKind (the function named inferKind) so the
actor check includes s.includes('shape=actor') alongside s.includes('umlactor')
and s.includes('shape=person') (and ensure the lowercase-normalized s variable
is used), leaving the rest of the switch logic unchanged so cells with
style="shape=actor" resolve to 'actor'.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6712fa68-0385-428f-ba26-3125cd5627de

📥 Commits

Reviewing files that changed from the base of the PR and between b381f8a and d4aa31a.

⛔ Files ignored due to path filters (1)
  • packages/generators/src/drawio/__snapshots__/parse-drawio.spec.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (3)
  • .changeset/drawio-infer-shape-person-roundtrip.md
  • packages/generators/src/drawio/parse-drawio.spec.ts
  • packages/generators/src/drawio/parse-drawio.ts

@sraphaz
Copy link
Copy Markdown
Owner Author

sraphaz commented Mar 4, 2026

Thanks for the reviews (@chatgpt-codex-connector, @coderabbitai). This is already addressed in the next commit on this branch: 71ab678 — \ ix(drawio): recognize shape=actor in inferKind for CI/self-contained PR.

\inferKind()\ now includes \shape=actor\ in the actor condition (parse-drawio.ts ~line 564: \case s.includes('umlactor') || s.includes('shape=person') || s.includes('shape=actor'):). So cells with \shape=actor\ are emitted as \�ctor 'title'\ with \style { shape person }, and the round-trip is correct. The actor snapshot test passes in CI. No further code change needed.

@chatgpt-codex-connector
Copy link
Copy Markdown

To use Codex here, create an environment for this repo.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 4, 2026

Tip

For best results, initiate chat on the files or code changes.

@sraphaz: Thanks for the update! The fix in commit 71ab678 looks correct — expanding the inferKind() condition to include s.includes('shape=actor') alongside umlactor and shape=person ensures full round-trip fidelity for actor/person shapes. Glad the snapshot test is passing in CI.

(´• ω •`) ♡

…e=actor or umlActor)

CodeRabbit: changeset now states export may emit shape=actor or shape=umlActor; inferShape comment updated to match.
Made-with: Cursor
@sraphaz sraphaz merged commit 03eb4b2 into main Mar 14, 2026
28 of 37 checks passed
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