drawio-python 0.1.3__tar.gz → 0.1.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. drawio_python-0.1.4/HISTORY.md +41 -0
  2. {drawio_python-0.1.3 → drawio_python-0.1.4}/PKG-INFO +107 -20
  3. drawio_python-0.1.4/README.md +248 -0
  4. {drawio_python-0.1.3 → drawio_python-0.1.4}/docs/index.md +6 -4
  5. drawio_python-0.1.4/drawio/VERSION +1 -0
  6. drawio_python-0.1.4/drawio/__init__.py +5 -0
  7. drawio_python-0.1.4/drawio/cli.py +399 -0
  8. drawio_python-0.1.4/drawio/doctor.py +144 -0
  9. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/document.py +446 -17
  10. drawio_python-0.1.4/drawio/layout.py +283 -0
  11. drawio_python-0.1.4/drawio/lint.py +531 -0
  12. drawio_python-0.1.4/drawio/render/__init__.py +223 -0
  13. drawio_python-0.1.4/drawio/render/browser.py +169 -0
  14. drawio_python-0.1.4/drawio/render/desktop.py +104 -0
  15. drawio_python-0.1.4/drawio/render/fonts.py +239 -0
  16. drawio_python-0.1.4/drawio/render/native.py +638 -0
  17. drawio_python-0.1.4/drawio/scene.py +658 -0
  18. drawio_python-0.1.4/drawio/shapes.py +82 -0
  19. drawio_python-0.1.4/drawio/skill/SKILL.md +155 -0
  20. drawio_python-0.1.4/drawio/skill/references/api.md +101 -0
  21. drawio_python-0.1.4/drawio/skill.py +40 -0
  22. drawio_python-0.1.4/drawio/text.py +127 -0
  23. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio_python.egg-info/PKG-INFO +107 -20
  24. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio_python.egg-info/SOURCES.txt +19 -1
  25. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio_python.egg-info/requires.txt +7 -0
  26. drawio_python-0.1.4/examples/agent_workflow.py +36 -0
  27. {drawio_python-0.1.3 → drawio_python-0.1.4}/requirements-test.txt +1 -0
  28. {drawio_python-0.1.3 → drawio_python-0.1.4}/setup.py +5 -1
  29. drawio_python-0.1.4/tests/test_cli.py +110 -0
  30. {drawio_python-0.1.3 → drawio_python-0.1.4}/tests/test_examples.py +1 -0
  31. drawio_python-0.1.4/tests/test_layout_text.py +76 -0
  32. drawio_python-0.1.4/tests/test_lint_render.py +220 -0
  33. drawio_python-0.1.4/tests/test_toolkit_api.py +141 -0
  34. drawio_python-0.1.3/HISTORY.md +0 -26
  35. drawio_python-0.1.3/README.md +0 -166
  36. drawio_python-0.1.3/drawio/VERSION +0 -1
  37. drawio_python-0.1.3/drawio/__init__.py +0 -5
  38. drawio_python-0.1.3/drawio/cli.py +0 -60
  39. drawio_python-0.1.3/tests/test_cli.py +0 -46
  40. {drawio_python-0.1.3 → drawio_python-0.1.4}/Containerfile +0 -0
  41. {drawio_python-0.1.3 → drawio_python-0.1.4}/LICENSE +0 -0
  42. {drawio_python-0.1.3 → drawio_python-0.1.4}/MANIFEST.in +0 -0
  43. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/__main__.py +0 -0
  44. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/base.py +0 -0
  45. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/controllers/__init__.py +0 -0
  46. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/__init__.py +0 -0
  47. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/base_entity.py +0 -0
  48. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/config.py +0 -0
  49. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/drawio.py +0 -0
  50. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/drawio_app.py +0 -0
  51. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/drawio_browser.py +0 -0
  52. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/drawio_config/__init__.py +0 -0
  53. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/drawio_config/abstract_config.py +0 -0
  54. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/drawio_config/connect_config.py +0 -0
  55. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/drawio_config/drawio_config.py +0 -0
  56. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/drawio_config/label_config.py +0 -0
  57. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/erd/__init__.py +0 -0
  58. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/erd/column.py +0 -0
  59. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/erd/erd.py +0 -0
  60. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/erd/table.py +0 -0
  61. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/graph/__init__.py +0 -0
  62. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/graph/edge.py +0 -0
  63. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/graph/graph.py +0 -0
  64. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/graph/node.py +0 -0
  65. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/logger.py +0 -0
  66. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/renderers/__init__.py +0 -0
  67. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/renderers/base_render.py +0 -0
  68. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/renderers/drawio_render.py +0 -0
  69. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/entities/renderers/pdf_render.py +0 -0
  70. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/itergrations/__init__.py +0 -0
  71. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/itergrations/mermaid/__init__.py +0 -0
  72. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio/itergrations/mermaid/mermaid_controller.py +0 -0
  73. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio_python.egg-info/dependency_links.txt +0 -0
  74. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio_python.egg-info/entry_points.txt +0 -0
  75. {drawio_python-0.1.3 → drawio_python-0.1.4}/drawio_python.egg-info/top_level.txt +0 -0
  76. {drawio_python-0.1.3 → drawio_python-0.1.4}/examples/complex-example.py +0 -0
  77. {drawio_python-0.1.3 → drawio_python-0.1.4}/examples/draw-flow-diagrams.png +0 -0
  78. {drawio_python-0.1.3 → drawio_python-0.1.4}/examples/draw-flow-diagrams.py +0 -0
  79. {drawio_python-0.1.3 → drawio_python-0.1.4}/examples/mermaid-to-drawio.py +0 -0
  80. {drawio_python-0.1.3 → drawio_python-0.1.4}/examples/native_document.py +0 -0
  81. {drawio_python-0.1.3 → drawio_python-0.1.4}/mkdocs.yml +0 -0
  82. {drawio_python-0.1.3 → drawio_python-0.1.4}/pyproject.toml +0 -0
  83. {drawio_python-0.1.3 → drawio_python-0.1.4}/requirements.txt +0 -0
  84. {drawio_python-0.1.3 → drawio_python-0.1.4}/setup.cfg +0 -0
  85. {drawio_python-0.1.3 → drawio_python-0.1.4}/tests/__init__.py +0 -0
  86. {drawio_python-0.1.3 → drawio_python-0.1.4}/tests/conftest.py +0 -0
  87. {drawio_python-0.1.3 → drawio_python-0.1.4}/tests/test_base.py +0 -0
  88. {drawio_python-0.1.3 → drawio_python-0.1.4}/tests/test_document.py +0 -0
  89. {drawio_python-0.1.3 → drawio_python-0.1.4}/tests/test_graph.py +0 -0
  90. {drawio_python-0.1.3 → drawio_python-0.1.4}/tests/test_graph_native.py +0 -0
  91. {drawio_python-0.1.3 → drawio_python-0.1.4}/tests/test_imports.py +0 -0
  92. {drawio_python-0.1.3 → drawio_python-0.1.4}/tests/test_mermaid.py +0 -0
@@ -0,0 +1,41 @@
1
+ # Unreleased
2
+
3
+ - Render pages to PNG, SVG, PDF and JPEG on any OS: a built-in native renderer (SVG
4
+ with no dependencies, raster through Pillow), the draw.io desktop exporter, or the
5
+ official diagrams.net viewer in a headless browser.
6
+ - Add layout checks (`drawio lint`): overflowing text, overlaps, connectors through
7
+ shapes or labels, children outside containers, small text and aspect ratio for a
8
+ target size.
9
+ - Add automatic layout (`drawio.layout`: layered, row, column, grid), `page.fit()`,
10
+ `page.autosize()`, text metrics, named shapes, images, colour presets,
11
+ `Theme.drawio()`, arrow ends, absolute coordinates, cell geometry accessors,
12
+ `page.remove()`, `page.find()`, `Document.import_page()` and `remove_page()`.
13
+ - New CLI commands for agents, all with `--json`: render, lint, inspect, fit, layout,
14
+ merge, shapes, doctor and skill; ship an agent skill installable with
15
+ `drawio skill install`.
16
+ - Fix `save()` creating files with mode 0600; explain duplicate-ID clashes with
17
+ generated IDs.
18
+ - Add a standard-library XML API for documents, pages, nested containers,
19
+ editable shapes, port anchors and connector waypoints.
20
+ - Load existing uncompressed/compressed diagrams and append pages while retaining
21
+ existing XML and metadata.
22
+ - Render legacy Graph output to `.drawio` / `.xml` without Selenium; retain CSV,
23
+ text, optional PDF export and explicit browser helpers.
24
+ - Fix graph edge identity, child registration, repeated CSV output and CSV quoting.
25
+ - Preserve labels and circular nodes in the basic Mermaid importer; reject
26
+ unsupported syntax instead of silently dropping edges.
27
+ - Add an offline CLI, native examples, tests and a Python/OS CI matrix.
28
+
29
+ Changelog
30
+ =========
31
+
32
+
33
+ 0.1.2 (2021-08-14)
34
+ ------------------
35
+ - Fix release, README and windows CI. [Bruno Rocha]
36
+ - Release: version 0.1.0. [Bruno Rocha]
37
+
38
+
39
+ 0.1.0 (2021-08-14)
40
+ ------------------
41
+ - Add release command. [Bruno Rocha]
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drawio-python
3
- Version: 0.1.3
4
- Summary: Create editable, multi-page draw.io diagrams with native Python XML
3
+ Version: 0.1.4
4
+ Summary: Build, check and export editable draw.io diagrams in Python; made for people and agents
5
5
  Home-page: https://github.com/maycuatroi1/drawio/
6
6
  Author: Nguyen Anh Binh
7
7
  Requires-Python: >=3.9
@@ -12,6 +12,11 @@ Requires-Dist: pytest>=7; extra == "test"
12
12
  Requires-Dist: pytest-cov>=4; extra == "test"
13
13
  Requires-Dist: ruff>=0.9; extra == "test"
14
14
  Requires-Dist: build>=1; extra == "test"
15
+ Requires-Dist: Pillow>=9.1; extra == "test"
16
+ Provides-Extra: render
17
+ Requires-Dist: Pillow>=9.1; extra == "render"
18
+ Provides-Extra: browser-render
19
+ Requires-Dist: playwright>=1.40; extra == "browser-render"
15
20
  Provides-Extra: browser
16
21
  Requires-Dist: selenium>=4; extra == "browser"
17
22
  Requires-Dist: webdriver-manager>=4; extra == "browser"
@@ -33,21 +38,34 @@ Dynamic: summary
33
38
 
34
39
  # drawio-python
35
40
 
36
- Build editable draw.io diagrams in Python. Save XML files without Selenium,
37
- Chrome, an export server, or runtime dependencies. Requires Python 3.9 or newer.
41
+ Build, check and export editable draw.io diagrams in Python. The library writes
42
+ native draw.io XML (every shape stays editable in draw.io), measures labels, finds
43
+ layout problems, lays shapes out, and renders PNG, SVG or PDF on Linux, macOS and
44
+ Windows. The core needs only the Python standard library; Python 3.9 or newer.
38
45
 
39
- The native API supports multiple pages, nested containers, styled shapes,
40
- connector ports and waypoints. The existing `Graph` / `Node` API still works.
46
+ It is built to be driven by coding agents as much as by people: every command has
47
+ `--json` output, and an agent skill ships with the package.
41
48
 
42
- ## Install this checkout
49
+ ## Install
43
50
 
44
51
  ```sh
45
- python3 -m venv .venv
46
- source .venv/bin/activate
47
- python -m pip install -e '.[test]'
52
+ pip install 'drawio-python[render]' # core + PNG/JPEG/PDF output (Pillow)
53
+ pip install drawio-python # core only: build, lint, SVG
54
+ pip install 'drawio-python[browser-render]' # exact rendering of any draw.io file
48
55
  ```
49
56
 
50
- These instructions use the updated source. The version on PyPI may differ.
57
+ From a checkout: `python -m pip install -e '.[render,test]'`. Check what the machine
58
+ can render with `drawio doctor`.
59
+
60
+ ## Agents
61
+
62
+ ```sh
63
+ drawio skill install # into ~/.claude/skills, ~/.codex/skills and/or ~/.agents/skills
64
+ drawio skill show # print the skill
65
+ ```
66
+
67
+ The skill (`drawio/skill/SKILL.md`) teaches the loop **build, `drawio lint`,
68
+ `drawio render`, look, fix**, the API, slide sizing and the common errors.
51
69
 
52
70
  ## Create a diagram
53
71
 
@@ -111,16 +129,82 @@ Labels default to plain text. Use `html=True` only for markup you trust. Style
111
129
  mappings use draw.io property names such as `fillColor`, `shape` and `fontSize`.
112
130
  XML escaping is handled by the writer.
113
131
 
132
+ ## Shapes, layout and fitting text
133
+
134
+ ```python
135
+ from drawio import Document, Theme
136
+ from drawio.layout import layered
137
+ from drawio.shapes import color
138
+
139
+ doc = Document(theme=Theme.drawio()) # the draw.io editor's own look
140
+ page = doc.add_page("Flow")
141
+ start = page.box("Start", 0, 0, 120, 50, shape="rounded", style=color("green"))
142
+ check = page.box("Valid?", 0, 0, 120, 80, shape="rhombus")
143
+ store = page.box("Orders", 0, 0, 120, 80, shape="cylinder", style=color("yellow"))
144
+ page.connect(start, check)
145
+ page.connect(check, store, "yes")
146
+ layered(page, direction="down") # ranks along the connectors; also row/column/grid
147
+ page.fit() # grow containers and the page around the shapes
148
+ doc.save("flow.drawio", overwrite=True)
149
+ ```
150
+
151
+ - `shape=` accepts `rounded, ellipse, circle, rhombus, cylinder, hexagon, triangle,
152
+ parallelogram, document, cloud, process, note, card, step, actor` or any draw.io
153
+ shape name; `page.image()` embeds a picture file.
154
+ - `connect(..., arrow=None)` draws an undirected line; `arrow` and `start_arrow` take
155
+ any draw.io marker (`drawio shapes` lists them).
156
+ - `box(..., absolute=True)` takes page coordinates inside a container;
157
+ `box(..., autosize=True)` or `page.autosize(cell)` grows a box to fit its label.
158
+ - Cells expose `x`, `y`, `width`, `height`, `bounds`, `style`, `text`, `move()`,
159
+ `resize()`, `set_style()`; pages offer `find()`, `children()`, `remove()`;
160
+ documents offer `import_page()` and `remove_page()`.
161
+
162
+ ## Check the layout
163
+
164
+ ```sh
165
+ drawio lint flow.drawio # exit status 1 when something is wrong
166
+ drawio lint deck.drawio --fit 8.15x4.85in # also: text below 12 pt once placed on a slide
167
+ drawio inspect flow.drawio --json # every shape box and connector route
168
+ ```
169
+
170
+ Lint reports overflowing labels, overlapping shapes and labels, connectors that run
171
+ through shapes or labels, children outside containers, and (with `--fit`) text that
172
+ ends up too small and aspect-ratio mismatches. Text widths are estimated from
173
+ Helvetica/Arial metrics, close to draw.io's wrapping.
174
+
175
+ ## Render
176
+
177
+ ```sh
178
+ drawio render flow.drawio -o flow.png --scale 2
179
+ drawio render flow.drawio -o flow.svg # plain SVG text, no foreignObject
180
+ drawio render deck.drawio -o slide.png --aspect 16:9
181
+ drawio render big.drawio --all-pages -f pdf
182
+ ```
183
+
184
+ | Backend | Requirements | Output |
185
+ |---|---|---|
186
+ | `native` | none for SVG; Pillow for PNG, JPEG, PDF | shapes this library makes and common draw.io shapes |
187
+ | `desktop` | [draw.io desktop](https://github.com/jgraph/drawio-desktop/releases) | exact |
188
+ | `browser` | `[browser-render]` extra plus Chrome, Edge or `playwright install chromium` | exact, including stencils and icons |
189
+ | `auto` | | desktop when installed, otherwise native |
190
+
191
+ The browser backend loads the official diagrams.net viewer, downloaded once to the
192
+ user cache (set `DRAWIO_VIEWER_JS` to work offline). On Linux the desktop backend
193
+ needs a display or `xvfb-run`. Native PDF is vector when `cairosvg` or `rsvg-convert`
194
+ is available, otherwise a raster image. `drawio doctor` reports all of this.
195
+
114
196
  ## CLI
115
197
 
116
198
  ```sh
117
- python -m drawio new empty.drawio --name Overview
118
- python -m drawio validate publishing.drawio --check-bounds
119
- python -m drawio info publishing.drawio
120
- python -m drawio url publishing.drawio
199
+ drawio new empty.drawio --name Overview
200
+ drawio validate publishing.drawio --check-bounds
201
+ drawio info publishing.drawio
202
+ drawio url publishing.drawio
203
+ drawio render | lint | inspect | fit | layout | merge | shapes | doctor | skill
121
204
  ```
122
205
 
123
- The installed `drawio` command exposes the same interface. `url` prints an editor
206
+ `python -m drawio` runs the same commands, which helps when the draw.io desktop
207
+ app also installed a `drawio` command. Commands that report take `--json`. `url` prints an editor
124
208
  link containing the complete diagram. Generating the URL makes no network
125
209
  request; anyone with the link can read its embedded content.
126
210
 
@@ -148,8 +232,8 @@ then asks the default browser to open an encoded editor URL; it no longer waits
148
232
  for console input. Tests and examples use `show=False`.
149
233
 
150
234
  Unpositioned legacy nodes use a simple grid, including disconnected graphs and
151
- cycles. Use `Node(x=..., y=...)` or the native `Page` API for an authored layout.
152
- The library does not provide automatic graph layout or SVG/PNG rendering.
235
+ cycles. Use `Node(x=..., y=...)` or the native `Page` API with `drawio.layout` for
236
+ an authored or automatic layout.
153
237
 
154
238
  `to_draw_io_csv()` and `to_draw_io()` still return the legacy CSV and text forms.
155
239
  The basic Mermaid importer retains the historical import path:
@@ -179,6 +263,8 @@ containers. The second demonstrates loading a file and adding a page.
179
263
 
180
264
  Optional extras:
181
265
 
266
+ - `.[render]`: Pillow, for PNG, JPEG and PDF output of the native renderer.
267
+ - `.[browser-render]`: Playwright, for the exact `browser` render backend.
182
268
  - `.[pdf]`: Python Graphviz binding; also install the Graphviz `dot` executable.
183
269
  - `.[browser]`: legacy Selenium helpers for callers importing `DrawIOBrowser`
184
270
  directly. They are not part of native rendering and are not live-browser
@@ -194,6 +280,7 @@ make test
194
280
  make build
195
281
  ```
196
282
 
197
- Tests write real XML and run examples in temporary directories. They do not
198
- install packages, download browser drivers, or launch Chrome. See
283
+ Tests write real XML, render with the native backend and run examples in
284
+ temporary directories. They do not install packages, download browser drivers, or
285
+ launch Chrome. See
199
286
  [the API reference](docs/index.md) and [contribution guide](CONTRIBUTING.md).
@@ -0,0 +1,248 @@
1
+ # drawio-python
2
+
3
+ Build, check and export editable draw.io diagrams in Python. The library writes
4
+ native draw.io XML (every shape stays editable in draw.io), measures labels, finds
5
+ layout problems, lays shapes out, and renders PNG, SVG or PDF on Linux, macOS and
6
+ Windows. The core needs only the Python standard library; Python 3.9 or newer.
7
+
8
+ It is built to be driven by coding agents as much as by people: every command has
9
+ `--json` output, and an agent skill ships with the package.
10
+
11
+ ## Install
12
+
13
+ ```sh
14
+ pip install 'drawio-python[render]' # core + PNG/JPEG/PDF output (Pillow)
15
+ pip install drawio-python # core only: build, lint, SVG
16
+ pip install 'drawio-python[browser-render]' # exact rendering of any draw.io file
17
+ ```
18
+
19
+ From a checkout: `python -m pip install -e '.[render,test]'`. Check what the machine
20
+ can render with `drawio doctor`.
21
+
22
+ ## Agents
23
+
24
+ ```sh
25
+ drawio skill install # into ~/.claude/skills, ~/.codex/skills and/or ~/.agents/skills
26
+ drawio skill show # print the skill
27
+ ```
28
+
29
+ The skill (`drawio/skill/SKILL.md`) teaches the loop **build, `drawio lint`,
30
+ `drawio render`, look, fix**, the API, slide sizing and the common errors.
31
+
32
+ ## Create a diagram
33
+
34
+ ```python
35
+ from drawio import Document
36
+
37
+ document = Document()
38
+ page = document.add_page("Publishing", id="publishing")
39
+
40
+ source = page.box("Draft", 40, 180, id="draft")
41
+ library = page.container("Library", 500, 80, 350, 350, id="library")
42
+ articles = page.box("Articles", 20, 70, 310, 70, parent=library)
43
+ page.box("Images", 20, 180, 310, 70, parent=library)
44
+
45
+ page.connect(
46
+ source, articles, "publish",
47
+ source_port=(1, 0.5), target_port=(0, 0.5),
48
+ waypoints=[(370, 225), (370, 185)],
49
+ )
50
+
51
+ document.add_page("Notes").text("A second editable tab", 40, 40)
52
+ document.validate(check_bounds=True)
53
+ document.save("publishing.drawio")
54
+ ```
55
+
56
+ Open the file in draw.io or diagrams.net. Each block and connector remains a
57
+ native editable object. Child coordinates are relative to the parent container;
58
+ connector waypoints use page coordinates.
59
+
60
+ `save()` refuses to replace an existing file. Pass `overwrite=True` when you
61
+ intend to update it. File writing uses an atomic replace or exclusive creation.
62
+
63
+ ## Add a page to an existing file
64
+
65
+ ```python
66
+ from drawio import Document
67
+
68
+ document = Document.load("publishing.drawio")
69
+ page = document.add_page("Review Details", id="review-details")
70
+ page.box("Editorial review", 40, 80)
71
+ document.save("publishing-v2.drawio")
72
+ ```
73
+
74
+ The loader accepts uncompressed and compressed draw.io XML. It retains existing
75
+ page IDs, cells, geometry and metadata; it expands compressed pages on output.
76
+ It does not preserve byte-for-byte formatting, signatures or compression.
77
+
78
+ ## Style and labels
79
+
80
+ ```python
81
+ from drawio import Document, Theme
82
+
83
+ document = Document(theme=Theme(font_family="Arial", font_size=20))
84
+ page = document.add_page("Styled")
85
+ page.box("Plain text: A & B < C", 40, 40,
86
+ style={"fillColor": "#e7effb", "fontStyle": 1})
87
+ page.box("<b>Trusted HTML</b><br/>Subtitle", 300, 40, html=True)
88
+ ```
89
+
90
+ Labels default to plain text. Use `html=True` only for markup you trust. Style
91
+ mappings use draw.io property names such as `fillColor`, `shape` and `fontSize`.
92
+ XML escaping is handled by the writer.
93
+
94
+ ## Shapes, layout and fitting text
95
+
96
+ ```python
97
+ from drawio import Document, Theme
98
+ from drawio.layout import layered
99
+ from drawio.shapes import color
100
+
101
+ doc = Document(theme=Theme.drawio()) # the draw.io editor's own look
102
+ page = doc.add_page("Flow")
103
+ start = page.box("Start", 0, 0, 120, 50, shape="rounded", style=color("green"))
104
+ check = page.box("Valid?", 0, 0, 120, 80, shape="rhombus")
105
+ store = page.box("Orders", 0, 0, 120, 80, shape="cylinder", style=color("yellow"))
106
+ page.connect(start, check)
107
+ page.connect(check, store, "yes")
108
+ layered(page, direction="down") # ranks along the connectors; also row/column/grid
109
+ page.fit() # grow containers and the page around the shapes
110
+ doc.save("flow.drawio", overwrite=True)
111
+ ```
112
+
113
+ - `shape=` accepts `rounded, ellipse, circle, rhombus, cylinder, hexagon, triangle,
114
+ parallelogram, document, cloud, process, note, card, step, actor` or any draw.io
115
+ shape name; `page.image()` embeds a picture file.
116
+ - `connect(..., arrow=None)` draws an undirected line; `arrow` and `start_arrow` take
117
+ any draw.io marker (`drawio shapes` lists them).
118
+ - `box(..., absolute=True)` takes page coordinates inside a container;
119
+ `box(..., autosize=True)` or `page.autosize(cell)` grows a box to fit its label.
120
+ - Cells expose `x`, `y`, `width`, `height`, `bounds`, `style`, `text`, `move()`,
121
+ `resize()`, `set_style()`; pages offer `find()`, `children()`, `remove()`;
122
+ documents offer `import_page()` and `remove_page()`.
123
+
124
+ ## Check the layout
125
+
126
+ ```sh
127
+ drawio lint flow.drawio # exit status 1 when something is wrong
128
+ drawio lint deck.drawio --fit 8.15x4.85in # also: text below 12 pt once placed on a slide
129
+ drawio inspect flow.drawio --json # every shape box and connector route
130
+ ```
131
+
132
+ Lint reports overflowing labels, overlapping shapes and labels, connectors that run
133
+ through shapes or labels, children outside containers, and (with `--fit`) text that
134
+ ends up too small and aspect-ratio mismatches. Text widths are estimated from
135
+ Helvetica/Arial metrics, close to draw.io's wrapping.
136
+
137
+ ## Render
138
+
139
+ ```sh
140
+ drawio render flow.drawio -o flow.png --scale 2
141
+ drawio render flow.drawio -o flow.svg # plain SVG text, no foreignObject
142
+ drawio render deck.drawio -o slide.png --aspect 16:9
143
+ drawio render big.drawio --all-pages -f pdf
144
+ ```
145
+
146
+ | Backend | Requirements | Output |
147
+ |---|---|---|
148
+ | `native` | none for SVG; Pillow for PNG, JPEG, PDF | shapes this library makes and common draw.io shapes |
149
+ | `desktop` | [draw.io desktop](https://github.com/jgraph/drawio-desktop/releases) | exact |
150
+ | `browser` | `[browser-render]` extra plus Chrome, Edge or `playwright install chromium` | exact, including stencils and icons |
151
+ | `auto` | | desktop when installed, otherwise native |
152
+
153
+ The browser backend loads the official diagrams.net viewer, downloaded once to the
154
+ user cache (set `DRAWIO_VIEWER_JS` to work offline). On Linux the desktop backend
155
+ needs a display or `xvfb-run`. Native PDF is vector when `cairosvg` or `rsvg-convert`
156
+ is available, otherwise a raster image. `drawio doctor` reports all of this.
157
+
158
+ ## CLI
159
+
160
+ ```sh
161
+ drawio new empty.drawio --name Overview
162
+ drawio validate publishing.drawio --check-bounds
163
+ drawio info publishing.drawio
164
+ drawio url publishing.drawio
165
+ drawio render | lint | inspect | fit | layout | merge | shapes | doctor | skill
166
+ ```
167
+
168
+ `python -m drawio` runs the same commands, which helps when the draw.io desktop
169
+ app also installed a `drawio` command. Commands that report take `--json`. `url` prints an editor
170
+ link containing the complete diagram. Generating the URL makes no network
171
+ request; anyone with the link can read its embedded content.
172
+
173
+ For an open editor's **Extras > Edit Diagram** dialog, use `page.to_xml()` to
174
+ obtain that page's `mxGraphModel`. Importing through that dialog may retain the
175
+ editor's current Grid, Page View and Background settings.
176
+
177
+ ## Existing Graph / Node API
178
+
179
+ ```python
180
+ from drawio import Graph, Node
181
+
182
+ graph = Graph(name="Review")
183
+ a = Node("Draft", shape="rectangle", x=40, y=80)
184
+ b = Node("Published", shape="rectangle", x=400, y=80)
185
+ graph.add_nodes([a, b])
186
+ a >> "approve" >> b
187
+
188
+ graph.render("review.drawio", show=False)
189
+ ```
190
+
191
+ `.drawio` and `.xml` rendering now uses the native writer and returns the output
192
+ path. `Graph.render()` retains its overwrite behavior. `show=True` saves first,
193
+ then asks the default browser to open an encoded editor URL; it no longer waits
194
+ for console input. Tests and examples use `show=False`.
195
+
196
+ Unpositioned legacy nodes use a simple grid, including disconnected graphs and
197
+ cycles. Use `Node(x=..., y=...)` or the native `Page` API with `drawio.layout` for
198
+ an authored or automatic layout.
199
+
200
+ `to_draw_io_csv()` and `to_draw_io()` still return the legacy CSV and text forms.
201
+ The basic Mermaid importer retains the historical import path:
202
+
203
+ ```python
204
+ from drawio.itergrations.mermaid.mermaid_controller import MermaidController
205
+
206
+ graph = MermaidController().load("flowchart LR; A[Draft] -->|approve| B[Published]")
207
+ graph.render("mermaid.drawio")
208
+ ```
209
+
210
+ Supported Mermaid input includes node declarations, `-->`, `-->|label|`, chained
211
+ edges, and rectangular, circular, parenthesized and diamond node labels. Direction
212
+ headers are accepted, but the legacy renderer uses the grid described above.
213
+ Subgraphs, styling directives and other edge syntax raise errors rather than
214
+ silently dropping content. This importer is not a complete Mermaid parser.
215
+
216
+ ## Examples and optional integrations
217
+
218
+ ```sh
219
+ python examples/native_document.py
220
+ python examples/complex-example.py
221
+ ```
222
+
223
+ The first example writes `output/publishing.drawio` with two tabs and nested
224
+ containers. The second demonstrates loading a file and adding a page.
225
+
226
+ Optional extras:
227
+
228
+ - `.[render]`: Pillow, for PNG, JPEG and PDF output of the native renderer.
229
+ - `.[browser-render]`: Playwright, for the exact `browser` render backend.
230
+ - `.[pdf]`: Python Graphviz binding; also install the Graphviz `dot` executable.
231
+ - `.[browser]`: legacy Selenium helpers for callers importing `DrawIOBrowser`
232
+ directly. They are not part of native rendering and are not live-browser
233
+ tested by the default suite.
234
+ - `.[excel]`: dependencies for the existing ERD spreadsheet exporter.
235
+ - `.[docs]`: MkDocs.
236
+
237
+ ## Development
238
+
239
+ ```sh
240
+ make lint
241
+ make test
242
+ make build
243
+ ```
244
+
245
+ Tests write real XML, render with the native backend and run examples in
246
+ temporary directories. They do not install packages, download browser drivers, or
247
+ launch Chrome. See
248
+ [the API reference](docs/index.md) and [contribution guide](CONTRIBUTING.md).
@@ -64,8 +64,9 @@ heading yourself. Nested container coordinates follow the same rule. The writer
64
64
  does not pack, resize or align child blocks for you.
65
65
 
66
66
  `validate(check_bounds=True)` also checks ordinary child rectangles against
67
- parent bounds. Relative ports are exempt from this bounds check. Validation does
68
- not measure text, detect shape overlaps or guarantee optimal connector routing.
67
+ parent bounds. Relative ports are exempt from this bounds check. Validation checks
68
+ structure only; `drawio.lint.check(document)` (or `drawio lint`) measures text and
69
+ finds overlaps and connectors that cross shapes or labels.
69
70
 
70
71
  `Cell.element`, `Page.model`, `Page.element` and `Document.element` expose the
71
72
  underlying ElementTree elements for advanced XML editing. Call `validate()`
@@ -105,5 +106,6 @@ pass `html=True` to a shape method when you intend to render trusted markup.
105
106
  page.box("<b>Title</b><br/>Subtitle", 40, 300, html=True)
106
107
  ```
107
108
 
108
- XML generation works offline. To inspect the visual result, open the file in
109
- draw.io. Use that editor or draw.io Desktop for image/PDF exports.
109
+ XML generation works offline. `drawio.render.render(document, "out.png")` exports a
110
+ page; see the README for backends. The full agent-oriented reference, including
111
+ layout, lint, rendering and the CLI, is `drawio/skill/references/api.md`.
@@ -0,0 +1 @@
1
+ 0.1.4
@@ -0,0 +1,5 @@
1
+ from .document import Cell, Document, Page, Theme, parse_style
2
+ from .entities.graph.graph import Graph
3
+ from .entities.graph.node import Node
4
+
5
+ __all__ = ["Cell", "Document", "Graph", "Node", "Page", "Theme", "parse_style"]