Skip to content

feat(cli,playground,docs,generators): Export LikeC4 views to Draw.io#19

Merged
sraphaz merged 3 commits intomainfrom
feat/drawio-export
Feb 14, 2026
Merged

feat(cli,playground,docs,generators): Export LikeC4 views to Draw.io#19
sraphaz merged 3 commits intomainfrom
feat/drawio-export

Conversation

@sraphaz
Copy link
Copy Markdown
Owner

@sraphaz sraphaz commented Feb 14, 2026

feat(cli,playground,docs,generators): Export LikeC4 views to Draw.io

Summary

This PR adds export of LikeC4 views to Draw.io (.drawio) format. Users can export from the CLI (likec4 export drawio) and from the Playground (right-click on diagram → DrawIO → Export view / Export all). This allows editing diagrams in Draw.io and reusing them in tools that support the format.

This PR does not include import. Import from Draw.io will be proposed in a separate PR after this one is merged.


What's in this PR

1. Generators (@likec4/generators)

  • packages/generators/src/drawio/generate-drawio.ts — Exports a single view or multiple views to Draw.io XML. Maps LikeC4 elements (title, description, shape, color, relationships, etc.) to mxCell vertices/edges. Supports optional layoutOverride, strokeColorByNodeId, strokeWidthByNodeId, edgeWaypoints, and compressed.
  • packages/generators/src/drawio/parse-drawio.ts — Used only for round-trip comment parsing (parseDrawioRoundtripComments): when re-exporting after a future import, layout and waypoints from comment blocks in .c4 source can be applied. No import UI or CLI in this PR.
  • packages/generators/src/drawio/index.ts — Public API: generateDrawio, generateDrawioMulti, GenerateDrawioOptions, plus getAllDiagrams, parseDrawioRoundtripComments, parseDrawioToLikeC4, parseDrawioToLikeC4Multi (for roundtrip and for the future import PR).
  • Tests: generate-drawio.spec.ts, parse-drawio.spec.ts; snapshots in __snapshots__/.

2. CLI (@likec4/likec4)

  • packages/likec4/src/cli/export/drawio/handler.tslikec4 export drawio [path] with options: --outdir, -o, --all-in-one, --roundtrip, --uncompressed, --project, --use-dot.
  • packages/likec4/src/cli/export/index.ts — Registers the drawio export command.

3. Playground

  • DrawIO context menu export only: DrawioContextMenuProvider, DrawioContextMenuDropdown (Export view…, Export all…), useDrawioContextMenuActions (handleExport, handleExportAllViews; uses generateDrawio/generateDrawioMulti and parseDrawioRoundtripComments). DrawioContextMenu, drawio-events (DRAWIO_EXPORT_EVENT). No Import item or file input in this PR.
  • Monaco: only Export to DrawIO action in editor context menu (no Import action). Integration in LanguageClientSync and routes as needed for export.

Playground exports are uncompressed by default so files open reliably in Draw.io desktop.

4. Documentation

  • apps/docs/src/content/docs/tooling/drawio.mdx — Export only: mapping (LikeC4 → Draw.io), options, not preserved, multi-diagram, troubleshooting, re-export using comment blocks. No import sections.
  • apps/docs/src/content/docs/tooling/cli.mdx — Export to DrawIO section only; no Import from DrawIO section. Intro mentions Export to DrawIO only.

5. Tests

  • packages/likec4/src/drawio-demo-export-import.spec.ts — Export tests only; import/vice-versa test skipped in this PR.
  • packages/likec4/src/drawio-tutorial-export-import.spec.ts — Export tests only; import and round-trip tests skipped in this PR.
  • e2e/tests/drawio-playground.spec.ts — Asserts DrawIO menu shows Export to DrawIO (and Export all). No Import assertion. Run with playwright.playground.config.ts (playground on 5174); main e2e config ignores this test.

What's not in this PR

  • No likec4 import drawio command (no packages/likec4/src/cli/import/).
  • Playground lacks an "Import from DrawIO" menu item, file input, or Monaco Import action.
  • Documentation for importing from Draw.io is not included.
  • Import/round-trip tests in likec4 specs are skipped; enabled in the import PR.

Post-review fixes (CodeRabbit)

Addresses CodeRabbit AI review (actionable + nitpicks):

Actionable

  • parse-drawio.ts: stripHtml uses shared decodeXmlEntities(); UserObject id escaped with escapeXml(userObjId); collectRoundtripForState single pass; getDecodedStyle/decodeRootStyleField try/catch for decodeURIComponent; getAttr word-boundary so id= does not match userid=.
  • drawio handler: Zero-views guard; ensureSingleProject() only when no --project; exportParams typed as ExportDrawioParams.
  • json handler: await using for languageServices.
  • png handler: startTakeScreenshot per project; logger c4:export.

Nitpicks / cleanup

  • useWorkspaceId.ts: Removed commented code and unused import.
  • documentation-provider.ts: Exhaustiveness check.
  • log: Explicit generics; typo getErrorFromLogRecord/errorMessage; config destructure; removed comment.
  • DrawioContextMenuProvider: Typed EMPTY_DRAWIO_SNAPSHOT; stable getSourceContent; filesRef in useEffect; removed unused usePlayground().
  • useDrawioContextMenuActions: Detached anchor; dev console.warn with error.
  • generate-drawio.ts: Optional modified (top-level); buildOptionsFromRoundtrip + parse-once.
  • Docs: Removed ad-hoc PR/description files from repo.

Checklist (contribution guidelines)

  • I have read the latest contribution guidelines.
  • I have rebased my branch onto main before creating this PR.
  • My commit messages follow Conventional Commits (e.g. feat:, docs:).
  • I have added/updated tests for export; import tests are skipped in this branch.
  • I have run pnpm test and pnpm typecheck (and pnpm test:e2e for e2e); all pass.
  • Documentation updated (drawio.mdx and cli.mdx for export only).
  • A changeset has been added for user-facing packages if applicable.

Notes for reviewers

  • Export: one .drawio file per view by default; --all-in-one for all views as tabs; --roundtrip applies layout/waypoints from comment blocks; --uncompressed for Draw.io desktop compatibility.
  • Playground exposes only Export actions in the DrawIO menu.
  • Generators: parse-drawio is present for round-trip comments and for the upcoming import PR; no import entrypoints used here.
  • E2E: drawio-playground test is excluded from main config (runs only with playground config on port 5174); screenshot diff tolerance and timeouts tuned for CI.

Review context

The original DrawIO bidirectional work (branch feat/drawio-bidirectional-playground) was reviewed upstream in likec4/likec4 PR #2593. This export-only PR is a split from that work; CodeRabbit AI review comments have been addressed in the "Post-review fixes" section above.

Summary by CodeRabbit

  • Bug Fixes
    • Improved Draw.io export parsing to be more accurate and reliable when identifying attributes.
  • Documentation
    • Removed an outdated documentation file describing the Draw.io export feature.

…d (DrawioContextMenuProvider); remove ad-hoc PR docs

Co-authored-by: Cursor <[email protected]>
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 14, 2026

📝 Walkthrough

Walkthrough

Removed a documentation file, switched a Playground component to use the snapshot hook only, and hardened Draw.io attribute parsing by enforcing word-boundary checks to avoid false-positive attribute matches.

Changes

Cohort / File(s) Summary
Documentation Cleanup
PR-DESCRIPTION.md
Deleted the descriptive documentation for Draw.io export (CLI and Playground), removing only a doc file; no code/API changes.
Playground Refactor
apps/playground/src/components/drawio/DrawioContextMenuProvider.tsx
Replaced usePlayground usage with usePlaygroundSnapshot only; removed the local playground = usePlayground() subscription.
Parser Enhancement
packages/generators/src/drawio/parse-drawio.ts
Added isAttrBoundaryChar and updated getAttr to perform boundary-aware attribute matching, avoiding matches like userid= when searching for id= (non-regex, ReDoS-conscious).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I nibbled docs away, a hook hopped aside,
I tuned the parser's ears to where boundaries hide,
No more mistaken id in a longer name's nest,
Draw.io whispers cleaner — the view exports best. 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (2 files):

⚔️ apps/playground/src/components/drawio/DrawioContextMenuProvider.tsx (content)
⚔️ packages/generators/src/drawio/parse-drawio.ts (content)

These conflicts must be resolved before merging into main.
Resolve conflicts locally and push changes to this branch.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly summarizes the main feature: exporting LikeC4 views to Draw.io format across CLI, Playground, and documentation.
Description check ✅ Passed The PR description comprehensively covers all required sections: summary, implementation details, documentation updates, tests, exclusions, post-review fixes, and a complete contribution checklist.
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
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/drawio-export
⚔️ Resolve merge conflicts (beta)
  • Auto-commit resolved conflicts to branch feat/drawio-export
  • Create stacked PR with resolved conflicts
  • Post resolved changes as copyable diffs in a comment

No actionable comments were generated in the recent review. 🎉


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

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.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/playground/src/components/drawio/DrawioContextMenuProvider.tsx`:
- Around line 1-4: The imports need to be reordered so type-only imports come
first: move the value import usePlaygroundSnapshot below the type-only import
block; group LayoutedLikeC4ModelData, LikeC4Model, and DiagramView together at
the top as type-only imports and then import usePlaygroundSnapshot afterwards to
satisfy the import grouping and sorting rule.

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