Skip to content

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

Merged
sraphaz merged 1 commit intomainfrom
feat/drawio-export
Feb 13, 2026
Merged

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

Conversation

@sraphaz
Copy link
Copy Markdown
Owner

@sraphaz sraphaz commented Feb 13, 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 from the CLI (likec4 export drawio) and the Playground (right-click on diagram → DrawIO → Export view / Export all). It does not include import; import will be proposed in a separate PR.

Context for maintainers: This work was first submitted in PR #2614, which received substantial review feedback focused on clean code, structure, and maintainability. We took that feedback seriously and ran a deliberate refactor pass (Uncle Bob / Clean Code) over the DrawIO-related code. This PR re-submits the same feature set with a cleaner, refactored codebase that we believe is easier to review and maintain. We’re grateful for the earlier review and have aimed to address those concerns in this iteration.


What’s in this PR

1. Generators (@likec4/generators)

  • generate-drawio.ts — Export single or multiple views to Draw.io XML; layout, styles, round-trip comments. Refactors: computeDiagramLayout split into smaller helpers; getViewDescriptionString extracted; buildNodeCellXml / buildEdgeCellXml and constants (SOLID/DRY/KISS); exported type DrawioViewModelLike.
  • parse-drawio.ts — Round-trip comment parsing and parse-to-LikeC4 for future import. Refactors: parseDrawioToLikeC4Multi split into mergeDiagramStatesIntoMaps, buildRootsFromFqnToCell, emitMultiDiagramModel (orchestrator ~50–60 lines); buildViewBlockLines / escapeLikec4Quotes; O(n²) deduplication replaced with parsedIds Set; UserObject fullTag uses innerXml so sibling <data> is preserved.
  • Tests: generate-drawio.spec.ts, parse-drawio.spec.ts; snapshots in __snapshots__/. Decompress error assertion accepts (base64 decode|inflate|URI decode) for Node/env behavior; snapshots updated for CI.

2. CLI (@likec4/likec4)

  • export/drawio/handler.tslikec4 export drawio with --outdir/-o, --all-in-one, --roundtrip, --uncompressed, --project, --use-dot. Uses DEFAULT_DRAWIO_ALL_FILENAME from @likec4/generators (DRY). Phase comments and thin handler pattern aligned with other export commands.
  • export/png/handler.ts — Type PngExportArgs, runExportPng(args, logger); PNG export supports --outdir/-o (docs updated).
  • No likec4 import drawio in this PR (no packages/likec4/src/cli/import/).

3. Playground

  • DrawIO context menu export only: Export view…, Export all… (DrawioContextMenuProvider, DrawioContextMenuDropdown, useDrawioContextMenuActions). Uses generateDrawio / generateDrawioMulti and parseDrawioRoundtripComments. No Import menu item or file input.
  • Monaco: only “Export to DrawIO” in editor context menu.

4. Documentation

  • drawio.mdx — Export only: mapping, options, multi-diagram, troubleshooting, re-export via comment blocks.
  • cli.mdx / docker.mdx — Export to DrawIO and PNG --outdir; no Import section.

5. E2E & tests

  • e2e/tests/drawio-playground.spec.ts — DrawIO menu (Export view / Export all). Run with playwright.playground.config.ts.
  • likec4: drawio-demo-export-import.spec.ts, drawio-tutorial-export-import.spec.ts — export tests; import/round-trip tests skipped in this PR.

What’s not in this PR

  • No likec4 import drawio command.
  • No Playground “Import from DrawIO” or Monaco Import action.
  • No docs for importing from Draw.io.
  • Import/round-trip tests remain skipped until the import PR.

Refactor summary (response to PR likec4#2614 feedback)

After the initial submission (PR likec4#2614), we applied a structured clean-code pass:

  • Generators: Smaller, single-responsibility functions; named types (DrawioViewModelLike); constants; phase comments; DRY (e.g. DEFAULT_DRAWIO_ALL_FILENAME, shared helpers).
  • CLI: Thin handlers; args types and runExport*(args, logger) pattern for drawio/PNG/JSON; consistent error handling and JSDoc.
  • Playground: Clear separation in useDrawioContextMenuActions (fillFromLayoutedModel, fillFromViewStates, etc.); constants for fonts/sizes.
  • E2E: Shared helpers (selectors, timeouts) in e2e/helpers/.

We believe this version is in better shape for review and long-term maintenance.


Correções após review (PR #11)

Incorporadas as sugestões do review anterior:

  • Changesets: Escopo export-only; removidas menções a import nos textos de release (drawio-implementation-plan, drawio-import-postpack).
  • DrawioContextMenuProvider: Valor do context api memoizado com useMemo(..., [actions.openMenu]) para evitar re-renders desnecessários.
  • LanguageClientSync: Uso de LayoutView.req em sendRequest (type-safe; removido cast manual).
  • E2E likec4-cli-export-drawio: Teste "empty workspace" agora verifica exitCode === 1 no erro rejeitado.
  • packages/config filenames.ts: basename remove barras finais (/ e \) e trata resultado vazio com fallback.
  • generate-drawio.ts: arcSize=12 (inteiro percentagem) em vez de 0.12 para cantos ligeiramente arredondados no Draw.io.
  • parse-drawio.ts: Lógica comum extraída para buildCommonDiagramStateFromCells; buildSingleDiagramState e buildDiagramState reutilizam (DRY).
  • drawio handler: useDot lido dos args e passado a runExportDrawio; graphviz binary vs wasm conforme flag --use-dot.
  • json handler: Campo useDot nos args e em runExportJson; guard quando projectsModels.length === 0 (warn + throw).

Alterações adicionais (nitpicks e robustez)

  • Changeset drawio-import-postpack: Texto reescrito para descrever apenas export e postpack; removidas menções a import/parser/CLI no bullet do Draw.io.
  • LanguageClientSync: requestLayoutView passa a usar LayoutView.req em sendRequest (type-safe; params e resposta inferidos; cast removido).
  • PNG handler: Bloco que inicia o servidor (viteDev) e o ciclo de export passou para dentro do mesmo try; finally garante server.close() mesmo quando resolveServerUrl ou o export lançam (evita leak do ViteDevServer).
  • Drawio handler: readWorkspaceSourceContent com proteção a ciclos de symlink: realpath + visitedDirs para não seguir o mesmo diretório duas vezes.
  • Comentários: DrawioContextMenuProvider (useCallbackRef evita churn do listener); generate-drawio.spec (navigateTo/ProcessedView); parse-drawio (collectRoundtrip quatro passagens); parse-drawio.spec (fallback getFirstDiagram).

Checklist

  • I have read the latest contribution guidelines.
  • My branch is synced with main (merge/rebase as appropriate).
  • Commit messages follow Conventional Commits (e.g. feat:, refactor:, test:).
  • Tests added/updated; import-related tests skipped in this branch. pnpm ci:test (Vitest) passes.
  • Documentation updated (drawio.mdx, cli.mdx, docker.mdx for export only).
  • Changesets can be added for user-facing packages if maintainers request.

Verification

  • pnpm build (filter !./apps/*), pnpm typecheck, pnpm test (or pnpm ci:test) — pass.
  • E2E drawio-playground: run with playground Playwright config when validating.

Notes for reviewers

  • Export behavior is unchanged from the original feature; changes are structural (refactors, types, constants, tests).
  • Generators: DrawioViewModelLike is the public type for view models passed to generateDrawio / generateDrawioMulti.
  • CLI: Drawio and PNG export handlers follow the same pattern as other export commands (args type + runExport* + thin handler).
  • We’re happy to address any further feedback and to add a changeset for the export feature if desired.

Fork / local CI changes (this session)

  • packages/log formatters: Use loggable (safe-stringify) instead of JSON.stringify in formatters to avoid stack overflow with circular references.
  • .github/workflows/checks.yaml: Linux jobs switched to runs-on: ubuntu-24.04-arm (reviewer davydkov’s suggestion).
  • .github/workflows/ci-pr.yaml: Kept only locally in the fork; added to .gitignore and removed from tracking (git rm --cached) so it is not pushed to upstream. The PR to origin does not include this file.
  • CodeRabbit: Pending comments (buildEdgeGeometryXml relative="1", parse-drawio ln = lines[i]?.trim()) already reflected in code; unresolved items reviewed and confirmed.

Reference

  • Initial submission and review context: PR #2614.
  • Original DrawIO bidirectional discussion: PR #2593. This PR is export-only; import will follow in a separate PR.

Summary by CodeRabbit

  • Chores
    • Updated continuous integration workflow configuration and build system settings.

@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 13, 2026

📝 Walkthrough

Walkthrough

Removed the CI workflow configuration file for pull requests and added it to gitignore to prevent accidental local workflow file commits.

Changes

Cohort / File(s) Summary
CI Workflow Configuration
.github/workflows/ci-pr.yaml, .gitignore
Deleted the pull request CI workflow file and added it to gitignore for local Fork-only configurations.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

🐰 A workflow file bids farewell with grace,
Into .gitignore it finds its place,
Local forks stay tidy, no CI strife,
Order restored to the codebase life! ✨

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

⚔️ .gitignore (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 describes adding Draw.io export functionality across CLI, Playground, Docs, and Generators, which matches the primary objective of the changeset.
Description check ✅ Passed The PR description is comprehensive, addressing all template sections including checklist items, providing detailed context about the feature scope (export-only), refactoring rationale, and verification steps.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
🧪 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.

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