weasyvsdx 0.1.0__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.
- weasyvsdx-0.1.0/.gitignore +52 -0
- weasyvsdx-0.1.0/CHANGELOG.md +50 -0
- weasyvsdx-0.1.0/LICENSE +21 -0
- weasyvsdx-0.1.0/PKG-INFO +275 -0
- weasyvsdx-0.1.0/README.md +238 -0
- weasyvsdx-0.1.0/pyproject.toml +113 -0
- weasyvsdx-0.1.0/src/weasyvsdx/__init__.py +88 -0
- weasyvsdx-0.1.0/src/weasyvsdx/convert.py +223 -0
- weasyvsdx-0.1.0/src/weasyvsdx/errors.py +5 -0
- weasyvsdx-0.1.0/src/weasyvsdx/fetch.py +99 -0
- weasyvsdx-0.1.0/src/weasyvsdx/geometry.py +630 -0
- weasyvsdx-0.1.0/src/weasyvsdx/gradients.py +252 -0
- weasyvsdx-0.1.0/src/weasyvsdx/hatch.py +101 -0
- weasyvsdx-0.1.0/src/weasyvsdx/hidden.py +48 -0
- weasyvsdx-0.1.0/src/weasyvsdx/hidden_text.py +82 -0
- weasyvsdx-0.1.0/src/weasyvsdx/images.py +204 -0
- weasyvsdx-0.1.0/src/weasyvsdx/markers.py +193 -0
- weasyvsdx-0.1.0/src/weasyvsdx/package.py +207 -0
- weasyvsdx-0.1.0/src/weasyvsdx/pathdata.py +77 -0
- weasyvsdx-0.1.0/src/weasyvsdx/paths.py +105 -0
- weasyvsdx-0.1.0/src/weasyvsdx/py.typed +0 -0
- weasyvsdx-0.1.0/src/weasyvsdx/raw.py +101 -0
- weasyvsdx-0.1.0/src/weasyvsdx/text.py +352 -0
- weasyvsdx-0.1.0/tests/conftest.py +5 -0
- weasyvsdx-0.1.0/tests/helpers.py +168 -0
- weasyvsdx-0.1.0/tests/test_convert.py +233 -0
- weasyvsdx-0.1.0/tests/test_fetch.py +118 -0
- weasyvsdx-0.1.0/tests/test_geometry.py +304 -0
- weasyvsdx-0.1.0/tests/test_gradients.py +229 -0
- weasyvsdx-0.1.0/tests/test_hatch.py +114 -0
- weasyvsdx-0.1.0/tests/test_hidden.py +27 -0
- weasyvsdx-0.1.0/tests/test_hidden_text.py +117 -0
- weasyvsdx-0.1.0/tests/test_images.py +212 -0
- weasyvsdx-0.1.0/tests/test_install.py +93 -0
- weasyvsdx-0.1.0/tests/test_markers.py +164 -0
- weasyvsdx-0.1.0/tests/test_pathdata.py +30 -0
- weasyvsdx-0.1.0/tests/test_paths.py +70 -0
- weasyvsdx-0.1.0/tests/test_raw.py +61 -0
- weasyvsdx-0.1.0/tests/test_text.py +268 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# IDE
|
|
2
|
+
.idea/
|
|
3
|
+
.vscode/
|
|
4
|
+
*.swp
|
|
5
|
+
*.swo
|
|
6
|
+
|
|
7
|
+
# macOS
|
|
8
|
+
.DS_Store
|
|
9
|
+
|
|
10
|
+
# Python
|
|
11
|
+
__pycache__/
|
|
12
|
+
*.py[cod]
|
|
13
|
+
*$py.class
|
|
14
|
+
*.so
|
|
15
|
+
.Python
|
|
16
|
+
build/
|
|
17
|
+
develop-eggs/
|
|
18
|
+
dist/
|
|
19
|
+
downloads/
|
|
20
|
+
eggs/
|
|
21
|
+
.eggs/
|
|
22
|
+
lib/
|
|
23
|
+
lib64/
|
|
24
|
+
parts/
|
|
25
|
+
sdist/
|
|
26
|
+
var/
|
|
27
|
+
wheels/
|
|
28
|
+
*.egg-info/
|
|
29
|
+
.installed.cfg
|
|
30
|
+
*.egg
|
|
31
|
+
|
|
32
|
+
# Virtual environments
|
|
33
|
+
.venv/
|
|
34
|
+
venv/
|
|
35
|
+
ENV/
|
|
36
|
+
|
|
37
|
+
# Testing
|
|
38
|
+
.pytest_cache/
|
|
39
|
+
.coverage
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
|
|
44
|
+
# Type checking
|
|
45
|
+
.mypy_cache/
|
|
46
|
+
|
|
47
|
+
# Ruff
|
|
48
|
+
.ruff_cache/
|
|
49
|
+
coverage.xml
|
|
50
|
+
|
|
51
|
+
# Visual regression bench output
|
|
52
|
+
tools/visual/out/
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-10-24
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Visio drawings (VSDX, VSDM, VSD and the templates and stencils of Visio) render in WeasyPrint as vector
|
|
15
|
+
SVG: an `<img>`, `<object>` or `<embed>`, a CSS image, an `<image>` inside an SVG. `vsd2xhtml` of
|
|
16
|
+
libvisio draws the first page. An untyped response is a drawing by the suffix of its URL, before or after
|
|
17
|
+
a redirect.
|
|
18
|
+
- The text of a drawing wraps and aligns as in Visio: each text block is HTML in a `<foreignObject>`, from
|
|
19
|
+
the output of `vsd2raw`, with its padding, vertical alignment, rotation, paragraphs, bullets and fonts,
|
|
20
|
+
and the character scale of Visio, which widens the glyphs.
|
|
21
|
+
- Arrowheads take their own shape and size, and a line under one ends at its base, as in Visio. A hollow
|
|
22
|
+
one hides the line under it.
|
|
23
|
+
- A shape on a hidden or non-printing layer is left out, as in Visio.
|
|
24
|
+
- The text a shape of a VSDX hides is left out: the names of the Azure icons no longer show under them.
|
|
25
|
+
- Black behind dark text, which libvisio reads from a palette color, draws white: labels no longer show as
|
|
26
|
+
black bars.
|
|
27
|
+
- A text with a line break of Visio (U+2028) shows, broken at it, instead of going missing.
|
|
28
|
+
- A bitmap inside an EMF that Office draws flipped no longer shows mirrored.
|
|
29
|
+
- A fill pattern draws as hatch lines, on the fill color where it has one, instead of black.
|
|
30
|
+
- A shape of a VSDX that fills with a gradient of Visio 2013 or later gets it, linear or radial, instead of
|
|
31
|
+
black: the icons of Azure show in color.
|
|
32
|
+
- A shape of a VSDX that inherits its geometry from a master group draws, from the XML of the master:
|
|
33
|
+
libvisio drew nothing for it, and parts of the Azure icons went missing.
|
|
34
|
+
- A text block of no width or height is as wide and as high as its text and never wraps, as in Visio.
|
|
35
|
+
- A path that libvisio writes without a leading moveto starts at the end of its first segment, not at the
|
|
36
|
+
corner of the page.
|
|
37
|
+
- EMF images become SVG through `emf2svg-conv`, and so does the EMF that Office puts inside a WMF image,
|
|
38
|
+
and the picture an embedded OLE object shows.
|
|
39
|
+
- The tools run in processes of their own, with a timeout and, on Linux, limits on memory and output.
|
|
40
|
+
The EMF images of a page share one timeout.
|
|
41
|
+
A drawing that does not convert renders as a broken image.
|
|
42
|
+
- A drawing that libvisio draws as a page of no size renders as a broken image.
|
|
43
|
+
- `install()` warns when `vsd2xhtml` reports another libvisio than 0.1.7, the release weasyvsdx is tested
|
|
44
|
+
with: 0.1.8 to 0.1.11 fill the shapes of a VSDX with the colors of its theme over their own.
|
|
45
|
+
- A font of Microsoft that the system lacks falls back to its free replacement: Calibri to Carlito, Cambria to
|
|
46
|
+
Caladea, Segoe UI to Selawik.
|
|
47
|
+
- A comparison page on GitHub Pages shows each drawing of the corpus in LibreOffice, as libvisio writes it,
|
|
48
|
+
and in weasyvsdx.
|
|
49
|
+
- The bench also compares the Azure diagrams with the SVG that Visio exported for their article.
|
|
50
|
+
LibreOffice reads them through libvisio and shares its errors.
|
weasyvsdx-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sergey Grigoriev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
weasyvsdx-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: weasyvsdx
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Visio drawings (VSDX, VSD) for WeasyPrint, drawn as vector SVG through libvisio.
|
|
5
|
+
Project-URL: Homepage, https://github.com/grigoriev/weasyvsdx
|
|
6
|
+
Project-URL: Repository, https://github.com/grigoriev/weasyvsdx
|
|
7
|
+
Project-URL: Issues, https://github.com/grigoriev/weasyvsdx/issues
|
|
8
|
+
Author-email: Sergey Grigoriev <grigoriev@fastmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
21
|
+
Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
|
|
22
|
+
Classifier: Topic :: Printing
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.11
|
|
25
|
+
Requires-Dist: olefile>=0.47
|
|
26
|
+
Requires-Dist: weasyprint<71,>=70
|
|
27
|
+
Requires-Dist: weasysvg>=0.3.1
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: mypy==2.4.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pypdfium2==5.14.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-cov==7.1.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest==9.1.1; extra == 'dev'
|
|
33
|
+
Requires-Dist: ruff==0.17.2; extra == 'dev'
|
|
34
|
+
Provides-Extra: visual
|
|
35
|
+
Requires-Dist: numpy==2.5.4; (python_version >= '3.12') and extra == 'visual'
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
|
|
38
|
+
# weasyvsdx
|
|
39
|
+
|
|
40
|
+
[](https://github.com/grigoriev/weasyvsdx/actions/workflows/ci.yml)
|
|
41
|
+
[](https://scorecard.dev/viewer/?uri=github.com/grigoriev/weasyvsdx)
|
|
42
|
+
[](https://github.com/grigoriev/weasyvsdx/releases)
|
|
43
|
+
[](https://www.python.org/downloads/)
|
|
44
|
+
[](https://mypy-lang.org/)
|
|
45
|
+
[](https://github.com/astral-sh/ruff)
|
|
46
|
+
[](https://github.com/grigoriev/weasyvsdx/blob/main/LICENSE)
|
|
47
|
+
|
|
48
|
+
[](https://sonarcloud.io/summary/new_code?id=grigoriev_weasyvsdx)
|
|
49
|
+
[](https://sonarcloud.io/summary/new_code?id=grigoriev_weasyvsdx)
|
|
50
|
+
|
|
51
|
+
A plugin for [WeasyPrint](https://weasyprint.org) 70.x that draws Microsoft Visio drawings (VSDX, VSD) as
|
|
52
|
+
vector SVG, through [libvisio](https://github.com/LibreOffice/libvisio).
|
|
53
|
+
|
|
54
|
+
## Why?
|
|
55
|
+
|
|
56
|
+
WeasyPrint cannot read Visio drawings. Services that turn HTML into PDF convert them with LibreOffice
|
|
57
|
+
first, to a PNG. LibreOffice adds some 730 MB to an image and hundreds of findings to its scans, and the
|
|
58
|
+
drawing ends up as pixels.
|
|
59
|
+
|
|
60
|
+
weasyvsdx hands each drawing to the tools of libvisio, the library LibreOffice itself imports Visio with,
|
|
61
|
+
and draws the result as SVG inside WeasyPrint. The drawing stays vector and its text stays selectable. The
|
|
62
|
+
tools take some 41 MB on Debian.
|
|
63
|
+
|
|
64
|
+
## Installation
|
|
65
|
+
|
|
66
|
+
weasyvsdx runs on CPython 3.11 to 3.14.
|
|
67
|
+
|
|
68
|
+
Install the tools of libvisio, and emf2svg for the EMF images that many drawings hold. On Debian 13 and
|
|
69
|
+
Ubuntu 24.04, which have the libvisio weasyvsdx needs (see "libvisio version"):
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
apt-get install libvisio-tools emf2svg
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Then install weasyvsdx from PyPI:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
pip install weasyvsdx
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
weasyvsdx depends on WeasyPrint and on [weasysvg](https://github.com/grigoriev/weasysvg), which draws the
|
|
82
|
+
text of the drawings. WeasyPrint needs Pango, see its
|
|
83
|
+
[installation guide](https://doc.courtbouillon.org/weasyprint/stable/first_steps.html).
|
|
84
|
+
|
|
85
|
+
### libvisio version
|
|
86
|
+
|
|
87
|
+
Use libvisio 0.1.7. The tests and the bench run with it, and `install()` warns on any other release.
|
|
88
|
+
libvisio 0.1.8 to 0.1.11, the latest, fill the shapes of a VSDX with the colors of its theme over their own
|
|
89
|
+
colors: on the Azure diagrams of the bench, icons turn into olive disks and subnets into olive boxes.
|
|
90
|
+
|
|
91
|
+
| Distribution | libvisio |
|
|
92
|
+
|---|---|
|
|
93
|
+
| Debian 13 (trixie) | 0.1.7 |
|
|
94
|
+
| Ubuntu 24.04 | 0.1.7 |
|
|
95
|
+
| Debian testing, unstable | 0.1.11 |
|
|
96
|
+
| Ubuntu 26.04 | 0.1.10 |
|
|
97
|
+
| Alpine 3.22, 3.23 | 0.1.8 |
|
|
98
|
+
| Wolfi | none |
|
|
99
|
+
|
|
100
|
+
To keep it, pin the release of the base image, for example `python:3.14-slim-trixie`, and check it at
|
|
101
|
+
build time:
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
test "$(vsd2xhtml --version)" = "vsd2xhtml 0.1.7"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
libvisio 0.1.9 and later also read the text background of a VSD, which 0.1.7 reads as black. weasyvsdx
|
|
108
|
+
draws black behind dark text as white, the most common background, so the labels show. A colored
|
|
109
|
+
background draws white as well.
|
|
110
|
+
|
|
111
|
+
### Verify
|
|
112
|
+
|
|
113
|
+
The build of each release has signed provenance on GitHub, and the GitHub release carries its bundle.
|
|
114
|
+
PyPI and the GitHub release hold the same files, so verify a file from either with
|
|
115
|
+
`gh attestation verify <file> --repo grigoriev/weasyvsdx`. On PyPI each file also has a publish
|
|
116
|
+
attestation (PEP 740): it ties the upload to `release.yml` of this repository.
|
|
117
|
+
|
|
118
|
+
## Usage
|
|
119
|
+
|
|
120
|
+
Call `install()` once, before the first rendering:
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
import weasyprint
|
|
124
|
+
import weasyvsdx
|
|
125
|
+
|
|
126
|
+
weasyvsdx.install()
|
|
127
|
+
weasyprint.HTML(string='<img src="plan.vsdx">', base_url=".").write_pdf("plan.pdf")
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
An image renders as a Visio drawing when its media type says so, `application/vnd.ms-visio.drawing` for
|
|
131
|
+
VSDX or `application/vnd.visio` for VSD, or when a file or URL without a type ends in `.vsdx`, `.vsd` or
|
|
132
|
+
another Visio suffix. A data URL counts by its type alone. This works for `<img>`, `<object>`, `<embed>`,
|
|
133
|
+
CSS images and `<image>` inside an SVG.
|
|
134
|
+
|
|
135
|
+
`install()` patches WeasyPrint in place, for the whole process, and returns the path of `vsd2xhtml`. It
|
|
136
|
+
raises `ConverterNotFoundError` when `vsd2xhtml` is not on the PATH. A later call changes the settings.
|
|
137
|
+
|
|
138
|
+
| Argument | Default | Effect |
|
|
139
|
+
|---|---|---|
|
|
140
|
+
| `converter` | `"vsd2xhtml"` | the `vsd2xhtml` to run, a name on the PATH or a path |
|
|
141
|
+
| `text` | `True` | lay the text out anew from `vsd2raw`, next to `vsd2xhtml`; installs weasysvg with its defaults unless its `foreign_object` is installed |
|
|
142
|
+
| `emf` | `True` | turn EMF images into SVG through `emf2svg-conv`, where it is on the PATH |
|
|
143
|
+
| `timeout` | `30.0` | seconds one run of a tool may take |
|
|
144
|
+
| `max_input_mb` | `64` | the largest drawing, in MB |
|
|
145
|
+
| `max_output_mb` | `256` | the most a tool may write, in MB (Linux) |
|
|
146
|
+
| `max_memory_mb` | `2048` | the address space of each tool, in MB (Linux) |
|
|
147
|
+
|
|
148
|
+
A drawing that does not convert, or that passes a limit, renders as a broken image: WeasyPrint logs the
|
|
149
|
+
error and leaves it out, and the rest of the document renders.
|
|
150
|
+
|
|
151
|
+
## Fonts
|
|
152
|
+
|
|
153
|
+
Visio drawings ask for fonts of Microsoft, Segoe UI and Calibri most. weasyvsdx names a free replacement
|
|
154
|
+
after each, so an installed original still wins:
|
|
155
|
+
|
|
156
|
+
| Font | Replacement | Debian package |
|
|
157
|
+
|---|---|---|
|
|
158
|
+
| Calibri | Carlito, same metrics | `fonts-crosextra-carlito` |
|
|
159
|
+
| Cambria | Caladea, same metrics | `fonts-crosextra-caladea` |
|
|
160
|
+
| Segoe UI, Light, Semilight, Semibold | Selawik, close, not equal | none: the [release of microsoft/Selawik](https://github.com/microsoft/Selawik/releases) |
|
|
161
|
+
|
|
162
|
+
Without them, text falls back to the sans-serif font of the system, which breaks lines elsewhere than Visio.
|
|
163
|
+
Where the license allows it, install the original fonts instead.
|
|
164
|
+
|
|
165
|
+
## How it works
|
|
166
|
+
|
|
167
|
+
1. `vsd2xhtml` of libvisio writes each page of the drawing as SVG. weasyvsdx takes the first page, as
|
|
168
|
+
LibreOffice does.
|
|
169
|
+
2. The generic SVG generator behind `vsd2xhtml` drops part of what libvisio reads. `vsd2raw` prints the
|
|
170
|
+
same calls with all their properties, and weasyvsdx takes the rest from there:
|
|
171
|
+
- **Text**: each text block becomes a `<foreignObject>` of its size, with its padding, vertical
|
|
172
|
+
alignment and rotation, and its paragraphs and spans as HTML: alignment, line spacing, indents, bullets,
|
|
173
|
+
font, size, scale, weight, style, color, underline, highlight, super- and subscript. WeasyPrint lays it out,
|
|
174
|
+
so labels wrap inside their shapes as in Visio. The generator wrote each text as one line at the left
|
|
175
|
+
edge of its block.
|
|
176
|
+
- **Arrowheads**: each marker gets the shape and size of its line end. The generator drew one stock
|
|
177
|
+
arrow for all of them, sized by the width of the line.
|
|
178
|
+
- **Hidden shapes**: a shape on a hidden or non-printing layer goes. The generator drew it.
|
|
179
|
+
- **Hidden text**: the text a shape of a VSDX hides (HideText, or a text cleared on the shape) goes. The
|
|
180
|
+
generator wrote the name of each Azure icon under it.
|
|
181
|
+
- **Hatches**: a fill pattern of Visio draws as the lines of its hatch. The generator filled it black.
|
|
182
|
+
- **Gradients**: a shape of a VSDX that fills with a gradient of Visio 2013 or later gets it, linear or
|
|
183
|
+
radial, from the XML of the page, its masters and styles. libvisio reads none, and filled it black.
|
|
184
|
+
- **Shapes of master groups**: a shape of a VSDX that inherits its geometry from a master group is drawn
|
|
185
|
+
from the XML of the master, with its fill, line, dashes and gradient. libvisio drew nothing for it, and
|
|
186
|
+
parts of the Azure icons went missing.
|
|
187
|
+
- **Line ends**: a line under an arrowhead ends at its base, as in Visio, not at its tip.
|
|
188
|
+
3. EMF images become SVG through `emf2svg-conv`, and so does the EMF that Office puts inside a WMF image,
|
|
189
|
+
and the picture an embedded OLE object shows.
|
|
190
|
+
WeasyPrint reads neither, and left them out.
|
|
191
|
+
4. A path that starts without a moveto loses its first segment, whose start libvisio does not give. Drawn as
|
|
192
|
+
it was, it ran from the corner of the page.
|
|
193
|
+
|
|
194
|
+
The tools parse untrusted input in C, and a broken file can crash them. Each runs in a process of its own,
|
|
195
|
+
in a temporary directory, with a time limit and, on Linux, limits on its memory and its output.
|
|
196
|
+
`vsd2xhtml` and `vsd2raw` run at the same time. The SVG then goes through WeasyPrint like any other SVG,
|
|
197
|
+
and every URL inside it through the URL fetcher of the caller.
|
|
198
|
+
|
|
199
|
+
## How it compares to LibreOffice and Visio
|
|
200
|
+
|
|
201
|
+
The bench in [`tools/visual`](https://github.com/grigoriev/weasyvsdx/tree/main/tools/visual) renders 291
|
|
202
|
+
drawings and compares each with its PNG export by LibreOffice 25.2:
|
|
203
|
+
|
|
204
|
+
- the 41 test drawings of libvisio, Apache POI and LibreOffice in [`corpus/visio`](https://github.com/grigoriev/weasyvsdx/tree/main/corpus/visio);
|
|
205
|
+
- the 250 Visio diagrams of the Azure Architecture Center, which the bench downloads into a cache: their
|
|
206
|
+
icons may not be copied into this repository, see [`corpus/SOURCES.md`](https://github.com/grigoriev/weasyvsdx/blob/main/corpus/SOURCES.md).
|
|
207
|
+
|
|
208
|
+
The [comparison page](https://grigoriev.github.io/weasyvsdx/corpus/comparison.html) shows each drawing of the
|
|
209
|
+
corpus in LibreOffice, as libvisio writes it, and in weasyvsdx, side by side, with a swipe between any two;
|
|
210
|
+
[`corpus/COMPARISON.md`](https://github.com/grigoriev/weasyvsdx/blob/main/corpus/COMPARISON.md) holds the same in the repository. The Azure
|
|
211
|
+
diagrams are not on it: their icons may not be redistributed.
|
|
212
|
+
|
|
213
|
+
All but two convert: libvisio crashes on `recursion-cycle.vsdx` and refuses `tab-short-prefix.vsdx`, two
|
|
214
|
+
of its tests that are broken on purpose. LibreOffice fails on the same two. Geometry, fills, gradients,
|
|
215
|
+
dashes, arrowheads and images match. The text differs most, and LibreOffice is no exact reference for it:
|
|
216
|
+
it lays text out with fonts of its own choice, and breaks words in narrow blocks where Visio does not. On
|
|
217
|
+
some drawings LibreOffice is wrong where weasyvsdx is right, for example it fills the whole of
|
|
218
|
+
`netapp-files-moodle-zonal` blue.
|
|
219
|
+
|
|
220
|
+
LibreOffice reads the drawings through libvisio, as weasyvsdx does, and shares its errors. So the bench
|
|
221
|
+
also compares 206 Azure diagrams with the SVG that Visio exported for their article. The median mismatch
|
|
222
|
+
is 25.0% against Visio, 49.5% against LibreOffice: weasyvsdx draws the gradients and the master
|
|
223
|
+
shapes of the Azure icons, which LibreOffice fills black or leaves out. Much of the rest is the icons of Azure, see "Known gaps".
|
|
224
|
+
|
|
225
|
+
The median Azure diagram converts in 0.08 s, and 9 in 10 in less than 0.5 s. Drawings that embed bitmaps
|
|
226
|
+
of tens of MB take seconds, 17 of the 250 more than one: libvisio writes the bitmaps out as base64. One,
|
|
227
|
+
`adaptive-apps`, takes 46 s, more than the default timeout of 30 s: it converts only with a larger `timeout`.
|
|
228
|
+
|
|
229
|
+
## Known gaps
|
|
230
|
+
|
|
231
|
+
- A shape whose ID another shape that libvisio draws shares keeps what libvisio drew: no gradient, and no
|
|
232
|
+
geometry from its master. So do the shapes of a VSD, gradients of the rarer kinds (FillGradientDir 8 to
|
|
233
|
+
13) and colors of the theme of a drawing.
|
|
234
|
+
- Only the first page renders. LibreOffice and the converters before it did the same.
|
|
235
|
+
- Visio drawings ask for Calibri and Segoe UI most, fonts of Microsoft. A font the system lacks falls back
|
|
236
|
+
to its free replacement, else to sans-serif: Calibri to Carlito and Cambria to Caladea, which share their
|
|
237
|
+
metrics, so text breaks where Visio breaks it; Segoe UI to Selawik, the open fallback of Microsoft, close
|
|
238
|
+
to it but not equal. Install them, see "Fonts".
|
|
239
|
+
- Character scaling (the "Scale" of a Visio font) applies where all text of a block shares one scale; a block
|
|
240
|
+
of mixed scales draws unscaled. Fields show the value libvisio formats.
|
|
241
|
+
- A WMF image without an EMF inside is left out, and so is an embedded OLE object whose picture is no EMF.
|
|
242
|
+
Office writes the EMF into each WMF it saves, and into the picture of each OLE object.
|
|
243
|
+
- Text that a VSD hides stays: only a VSDX holds HideText where weasyvsdx reads it.
|
|
244
|
+
- A shape on a hidden or non-printing layer goes, but its text would stay: libvisio marks the path of
|
|
245
|
+
such a shape as hidden, not its text.
|
|
246
|
+
- An EMF draws its GDI records only. Part of an icon that Office drew in EMF+ alone, the newer records an EMF
|
|
247
|
+
can carry in its comments, stays out: `emf2svg-conv` does not read EMF+, LibreOffice does.
|
|
248
|
+
|
|
249
|
+
## Development
|
|
250
|
+
|
|
251
|
+
Tests and the bench run in Docker, since WeasyPrint needs Pango and weasyvsdx the tools of libvisio. See
|
|
252
|
+
[CONTRIBUTING.md](https://github.com/grigoriev/weasyvsdx/blob/main/CONTRIBUTING.md).
|
|
253
|
+
|
|
254
|
+
```sh
|
|
255
|
+
make lint # ruff and mypy, on the host
|
|
256
|
+
make test # pytest with coverage, in Docker
|
|
257
|
+
make visual # the visual bench, report in tools/visual/out/report.html
|
|
258
|
+
make comparison # corpus/COMPARISON.md and corpus/comparison.html, the panels in corpus/render
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Contributing
|
|
262
|
+
|
|
263
|
+
See [CONTRIBUTING.md](https://github.com/grigoriev/weasyvsdx/blob/main/CONTRIBUTING.md). Report vulnerabilities privately, see [SECURITY.md](https://github.com/grigoriev/weasyvsdx/blob/main/SECURITY.md).
|
|
264
|
+
|
|
265
|
+
## Disclaimer
|
|
266
|
+
|
|
267
|
+
This software is provided "as is", without warranty of any kind, as the LICENSE states. Use
|
|
268
|
+
it at your own risk. Sergey Grigoriev is not liable for damage from its use, as far as the law
|
|
269
|
+
allows. It is published free of charge, outside of any commercial offering, with no
|
|
270
|
+
obligation to support it. Security reports are welcome, see [SECURITY.md](https://github.com/grigoriev/weasyvsdx/blob/main/SECURITY.md).
|
|
271
|
+
|
|
272
|
+
## License
|
|
273
|
+
|
|
274
|
+
MIT, see [LICENSE](https://github.com/grigoriev/weasyvsdx/blob/main/LICENSE). The test corpus keeps the licenses of its sources, see
|
|
275
|
+
[corpus/SOURCES.md](https://github.com/grigoriev/weasyvsdx/blob/main/corpus/SOURCES.md).
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# weasyvsdx
|
|
2
|
+
|
|
3
|
+
[](https://github.com/grigoriev/weasyvsdx/actions/workflows/ci.yml)
|
|
4
|
+
[](https://scorecard.dev/viewer/?uri=github.com/grigoriev/weasyvsdx)
|
|
5
|
+
[](https://github.com/grigoriev/weasyvsdx/releases)
|
|
6
|
+
[](https://www.python.org/downloads/)
|
|
7
|
+
[](https://mypy-lang.org/)
|
|
8
|
+
[](https://github.com/astral-sh/ruff)
|
|
9
|
+
[](https://github.com/grigoriev/weasyvsdx/blob/main/LICENSE)
|
|
10
|
+
|
|
11
|
+
[](https://sonarcloud.io/summary/new_code?id=grigoriev_weasyvsdx)
|
|
12
|
+
[](https://sonarcloud.io/summary/new_code?id=grigoriev_weasyvsdx)
|
|
13
|
+
|
|
14
|
+
A plugin for [WeasyPrint](https://weasyprint.org) 70.x that draws Microsoft Visio drawings (VSDX, VSD) as
|
|
15
|
+
vector SVG, through [libvisio](https://github.com/LibreOffice/libvisio).
|
|
16
|
+
|
|
17
|
+
## Why?
|
|
18
|
+
|
|
19
|
+
WeasyPrint cannot read Visio drawings. Services that turn HTML into PDF convert them with LibreOffice
|
|
20
|
+
first, to a PNG. LibreOffice adds some 730 MB to an image and hundreds of findings to its scans, and the
|
|
21
|
+
drawing ends up as pixels.
|
|
22
|
+
|
|
23
|
+
weasyvsdx hands each drawing to the tools of libvisio, the library LibreOffice itself imports Visio with,
|
|
24
|
+
and draws the result as SVG inside WeasyPrint. The drawing stays vector and its text stays selectable. The
|
|
25
|
+
tools take some 41 MB on Debian.
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
weasyvsdx runs on CPython 3.11 to 3.14.
|
|
30
|
+
|
|
31
|
+
Install the tools of libvisio, and emf2svg for the EMF images that many drawings hold. On Debian 13 and
|
|
32
|
+
Ubuntu 24.04, which have the libvisio weasyvsdx needs (see "libvisio version"):
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
apt-get install libvisio-tools emf2svg
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Then install weasyvsdx from PyPI:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
pip install weasyvsdx
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
weasyvsdx depends on WeasyPrint and on [weasysvg](https://github.com/grigoriev/weasysvg), which draws the
|
|
45
|
+
text of the drawings. WeasyPrint needs Pango, see its
|
|
46
|
+
[installation guide](https://doc.courtbouillon.org/weasyprint/stable/first_steps.html).
|
|
47
|
+
|
|
48
|
+
### libvisio version
|
|
49
|
+
|
|
50
|
+
Use libvisio 0.1.7. The tests and the bench run with it, and `install()` warns on any other release.
|
|
51
|
+
libvisio 0.1.8 to 0.1.11, the latest, fill the shapes of a VSDX with the colors of its theme over their own
|
|
52
|
+
colors: on the Azure diagrams of the bench, icons turn into olive disks and subnets into olive boxes.
|
|
53
|
+
|
|
54
|
+
| Distribution | libvisio |
|
|
55
|
+
|---|---|
|
|
56
|
+
| Debian 13 (trixie) | 0.1.7 |
|
|
57
|
+
| Ubuntu 24.04 | 0.1.7 |
|
|
58
|
+
| Debian testing, unstable | 0.1.11 |
|
|
59
|
+
| Ubuntu 26.04 | 0.1.10 |
|
|
60
|
+
| Alpine 3.22, 3.23 | 0.1.8 |
|
|
61
|
+
| Wolfi | none |
|
|
62
|
+
|
|
63
|
+
To keep it, pin the release of the base image, for example `python:3.14-slim-trixie`, and check it at
|
|
64
|
+
build time:
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
test "$(vsd2xhtml --version)" = "vsd2xhtml 0.1.7"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
libvisio 0.1.9 and later also read the text background of a VSD, which 0.1.7 reads as black. weasyvsdx
|
|
71
|
+
draws black behind dark text as white, the most common background, so the labels show. A colored
|
|
72
|
+
background draws white as well.
|
|
73
|
+
|
|
74
|
+
### Verify
|
|
75
|
+
|
|
76
|
+
The build of each release has signed provenance on GitHub, and the GitHub release carries its bundle.
|
|
77
|
+
PyPI and the GitHub release hold the same files, so verify a file from either with
|
|
78
|
+
`gh attestation verify <file> --repo grigoriev/weasyvsdx`. On PyPI each file also has a publish
|
|
79
|
+
attestation (PEP 740): it ties the upload to `release.yml` of this repository.
|
|
80
|
+
|
|
81
|
+
## Usage
|
|
82
|
+
|
|
83
|
+
Call `install()` once, before the first rendering:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
import weasyprint
|
|
87
|
+
import weasyvsdx
|
|
88
|
+
|
|
89
|
+
weasyvsdx.install()
|
|
90
|
+
weasyprint.HTML(string='<img src="plan.vsdx">', base_url=".").write_pdf("plan.pdf")
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
An image renders as a Visio drawing when its media type says so, `application/vnd.ms-visio.drawing` for
|
|
94
|
+
VSDX or `application/vnd.visio` for VSD, or when a file or URL without a type ends in `.vsdx`, `.vsd` or
|
|
95
|
+
another Visio suffix. A data URL counts by its type alone. This works for `<img>`, `<object>`, `<embed>`,
|
|
96
|
+
CSS images and `<image>` inside an SVG.
|
|
97
|
+
|
|
98
|
+
`install()` patches WeasyPrint in place, for the whole process, and returns the path of `vsd2xhtml`. It
|
|
99
|
+
raises `ConverterNotFoundError` when `vsd2xhtml` is not on the PATH. A later call changes the settings.
|
|
100
|
+
|
|
101
|
+
| Argument | Default | Effect |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| `converter` | `"vsd2xhtml"` | the `vsd2xhtml` to run, a name on the PATH or a path |
|
|
104
|
+
| `text` | `True` | lay the text out anew from `vsd2raw`, next to `vsd2xhtml`; installs weasysvg with its defaults unless its `foreign_object` is installed |
|
|
105
|
+
| `emf` | `True` | turn EMF images into SVG through `emf2svg-conv`, where it is on the PATH |
|
|
106
|
+
| `timeout` | `30.0` | seconds one run of a tool may take |
|
|
107
|
+
| `max_input_mb` | `64` | the largest drawing, in MB |
|
|
108
|
+
| `max_output_mb` | `256` | the most a tool may write, in MB (Linux) |
|
|
109
|
+
| `max_memory_mb` | `2048` | the address space of each tool, in MB (Linux) |
|
|
110
|
+
|
|
111
|
+
A drawing that does not convert, or that passes a limit, renders as a broken image: WeasyPrint logs the
|
|
112
|
+
error and leaves it out, and the rest of the document renders.
|
|
113
|
+
|
|
114
|
+
## Fonts
|
|
115
|
+
|
|
116
|
+
Visio drawings ask for fonts of Microsoft, Segoe UI and Calibri most. weasyvsdx names a free replacement
|
|
117
|
+
after each, so an installed original still wins:
|
|
118
|
+
|
|
119
|
+
| Font | Replacement | Debian package |
|
|
120
|
+
|---|---|---|
|
|
121
|
+
| Calibri | Carlito, same metrics | `fonts-crosextra-carlito` |
|
|
122
|
+
| Cambria | Caladea, same metrics | `fonts-crosextra-caladea` |
|
|
123
|
+
| Segoe UI, Light, Semilight, Semibold | Selawik, close, not equal | none: the [release of microsoft/Selawik](https://github.com/microsoft/Selawik/releases) |
|
|
124
|
+
|
|
125
|
+
Without them, text falls back to the sans-serif font of the system, which breaks lines elsewhere than Visio.
|
|
126
|
+
Where the license allows it, install the original fonts instead.
|
|
127
|
+
|
|
128
|
+
## How it works
|
|
129
|
+
|
|
130
|
+
1. `vsd2xhtml` of libvisio writes each page of the drawing as SVG. weasyvsdx takes the first page, as
|
|
131
|
+
LibreOffice does.
|
|
132
|
+
2. The generic SVG generator behind `vsd2xhtml` drops part of what libvisio reads. `vsd2raw` prints the
|
|
133
|
+
same calls with all their properties, and weasyvsdx takes the rest from there:
|
|
134
|
+
- **Text**: each text block becomes a `<foreignObject>` of its size, with its padding, vertical
|
|
135
|
+
alignment and rotation, and its paragraphs and spans as HTML: alignment, line spacing, indents, bullets,
|
|
136
|
+
font, size, scale, weight, style, color, underline, highlight, super- and subscript. WeasyPrint lays it out,
|
|
137
|
+
so labels wrap inside their shapes as in Visio. The generator wrote each text as one line at the left
|
|
138
|
+
edge of its block.
|
|
139
|
+
- **Arrowheads**: each marker gets the shape and size of its line end. The generator drew one stock
|
|
140
|
+
arrow for all of them, sized by the width of the line.
|
|
141
|
+
- **Hidden shapes**: a shape on a hidden or non-printing layer goes. The generator drew it.
|
|
142
|
+
- **Hidden text**: the text a shape of a VSDX hides (HideText, or a text cleared on the shape) goes. The
|
|
143
|
+
generator wrote the name of each Azure icon under it.
|
|
144
|
+
- **Hatches**: a fill pattern of Visio draws as the lines of its hatch. The generator filled it black.
|
|
145
|
+
- **Gradients**: a shape of a VSDX that fills with a gradient of Visio 2013 or later gets it, linear or
|
|
146
|
+
radial, from the XML of the page, its masters and styles. libvisio reads none, and filled it black.
|
|
147
|
+
- **Shapes of master groups**: a shape of a VSDX that inherits its geometry from a master group is drawn
|
|
148
|
+
from the XML of the master, with its fill, line, dashes and gradient. libvisio drew nothing for it, and
|
|
149
|
+
parts of the Azure icons went missing.
|
|
150
|
+
- **Line ends**: a line under an arrowhead ends at its base, as in Visio, not at its tip.
|
|
151
|
+
3. EMF images become SVG through `emf2svg-conv`, and so does the EMF that Office puts inside a WMF image,
|
|
152
|
+
and the picture an embedded OLE object shows.
|
|
153
|
+
WeasyPrint reads neither, and left them out.
|
|
154
|
+
4. A path that starts without a moveto loses its first segment, whose start libvisio does not give. Drawn as
|
|
155
|
+
it was, it ran from the corner of the page.
|
|
156
|
+
|
|
157
|
+
The tools parse untrusted input in C, and a broken file can crash them. Each runs in a process of its own,
|
|
158
|
+
in a temporary directory, with a time limit and, on Linux, limits on its memory and its output.
|
|
159
|
+
`vsd2xhtml` and `vsd2raw` run at the same time. The SVG then goes through WeasyPrint like any other SVG,
|
|
160
|
+
and every URL inside it through the URL fetcher of the caller.
|
|
161
|
+
|
|
162
|
+
## How it compares to LibreOffice and Visio
|
|
163
|
+
|
|
164
|
+
The bench in [`tools/visual`](https://github.com/grigoriev/weasyvsdx/tree/main/tools/visual) renders 291
|
|
165
|
+
drawings and compares each with its PNG export by LibreOffice 25.2:
|
|
166
|
+
|
|
167
|
+
- the 41 test drawings of libvisio, Apache POI and LibreOffice in [`corpus/visio`](https://github.com/grigoriev/weasyvsdx/tree/main/corpus/visio);
|
|
168
|
+
- the 250 Visio diagrams of the Azure Architecture Center, which the bench downloads into a cache: their
|
|
169
|
+
icons may not be copied into this repository, see [`corpus/SOURCES.md`](https://github.com/grigoriev/weasyvsdx/blob/main/corpus/SOURCES.md).
|
|
170
|
+
|
|
171
|
+
The [comparison page](https://grigoriev.github.io/weasyvsdx/corpus/comparison.html) shows each drawing of the
|
|
172
|
+
corpus in LibreOffice, as libvisio writes it, and in weasyvsdx, side by side, with a swipe between any two;
|
|
173
|
+
[`corpus/COMPARISON.md`](https://github.com/grigoriev/weasyvsdx/blob/main/corpus/COMPARISON.md) holds the same in the repository. The Azure
|
|
174
|
+
diagrams are not on it: their icons may not be redistributed.
|
|
175
|
+
|
|
176
|
+
All but two convert: libvisio crashes on `recursion-cycle.vsdx` and refuses `tab-short-prefix.vsdx`, two
|
|
177
|
+
of its tests that are broken on purpose. LibreOffice fails on the same two. Geometry, fills, gradients,
|
|
178
|
+
dashes, arrowheads and images match. The text differs most, and LibreOffice is no exact reference for it:
|
|
179
|
+
it lays text out with fonts of its own choice, and breaks words in narrow blocks where Visio does not. On
|
|
180
|
+
some drawings LibreOffice is wrong where weasyvsdx is right, for example it fills the whole of
|
|
181
|
+
`netapp-files-moodle-zonal` blue.
|
|
182
|
+
|
|
183
|
+
LibreOffice reads the drawings through libvisio, as weasyvsdx does, and shares its errors. So the bench
|
|
184
|
+
also compares 206 Azure diagrams with the SVG that Visio exported for their article. The median mismatch
|
|
185
|
+
is 25.0% against Visio, 49.5% against LibreOffice: weasyvsdx draws the gradients and the master
|
|
186
|
+
shapes of the Azure icons, which LibreOffice fills black or leaves out. Much of the rest is the icons of Azure, see "Known gaps".
|
|
187
|
+
|
|
188
|
+
The median Azure diagram converts in 0.08 s, and 9 in 10 in less than 0.5 s. Drawings that embed bitmaps
|
|
189
|
+
of tens of MB take seconds, 17 of the 250 more than one: libvisio writes the bitmaps out as base64. One,
|
|
190
|
+
`adaptive-apps`, takes 46 s, more than the default timeout of 30 s: it converts only with a larger `timeout`.
|
|
191
|
+
|
|
192
|
+
## Known gaps
|
|
193
|
+
|
|
194
|
+
- A shape whose ID another shape that libvisio draws shares keeps what libvisio drew: no gradient, and no
|
|
195
|
+
geometry from its master. So do the shapes of a VSD, gradients of the rarer kinds (FillGradientDir 8 to
|
|
196
|
+
13) and colors of the theme of a drawing.
|
|
197
|
+
- Only the first page renders. LibreOffice and the converters before it did the same.
|
|
198
|
+
- Visio drawings ask for Calibri and Segoe UI most, fonts of Microsoft. A font the system lacks falls back
|
|
199
|
+
to its free replacement, else to sans-serif: Calibri to Carlito and Cambria to Caladea, which share their
|
|
200
|
+
metrics, so text breaks where Visio breaks it; Segoe UI to Selawik, the open fallback of Microsoft, close
|
|
201
|
+
to it but not equal. Install them, see "Fonts".
|
|
202
|
+
- Character scaling (the "Scale" of a Visio font) applies where all text of a block shares one scale; a block
|
|
203
|
+
of mixed scales draws unscaled. Fields show the value libvisio formats.
|
|
204
|
+
- A WMF image without an EMF inside is left out, and so is an embedded OLE object whose picture is no EMF.
|
|
205
|
+
Office writes the EMF into each WMF it saves, and into the picture of each OLE object.
|
|
206
|
+
- Text that a VSD hides stays: only a VSDX holds HideText where weasyvsdx reads it.
|
|
207
|
+
- A shape on a hidden or non-printing layer goes, but its text would stay: libvisio marks the path of
|
|
208
|
+
such a shape as hidden, not its text.
|
|
209
|
+
- An EMF draws its GDI records only. Part of an icon that Office drew in EMF+ alone, the newer records an EMF
|
|
210
|
+
can carry in its comments, stays out: `emf2svg-conv` does not read EMF+, LibreOffice does.
|
|
211
|
+
|
|
212
|
+
## Development
|
|
213
|
+
|
|
214
|
+
Tests and the bench run in Docker, since WeasyPrint needs Pango and weasyvsdx the tools of libvisio. See
|
|
215
|
+
[CONTRIBUTING.md](https://github.com/grigoriev/weasyvsdx/blob/main/CONTRIBUTING.md).
|
|
216
|
+
|
|
217
|
+
```sh
|
|
218
|
+
make lint # ruff and mypy, on the host
|
|
219
|
+
make test # pytest with coverage, in Docker
|
|
220
|
+
make visual # the visual bench, report in tools/visual/out/report.html
|
|
221
|
+
make comparison # corpus/COMPARISON.md and corpus/comparison.html, the panels in corpus/render
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Contributing
|
|
225
|
+
|
|
226
|
+
See [CONTRIBUTING.md](https://github.com/grigoriev/weasyvsdx/blob/main/CONTRIBUTING.md). Report vulnerabilities privately, see [SECURITY.md](https://github.com/grigoriev/weasyvsdx/blob/main/SECURITY.md).
|
|
227
|
+
|
|
228
|
+
## Disclaimer
|
|
229
|
+
|
|
230
|
+
This software is provided "as is", without warranty of any kind, as the LICENSE states. Use
|
|
231
|
+
it at your own risk. Sergey Grigoriev is not liable for damage from its use, as far as the law
|
|
232
|
+
allows. It is published free of charge, outside of any commercial offering, with no
|
|
233
|
+
obligation to support it. Security reports are welcome, see [SECURITY.md](https://github.com/grigoriev/weasyvsdx/blob/main/SECURITY.md).
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
MIT, see [LICENSE](https://github.com/grigoriev/weasyvsdx/blob/main/LICENSE). The test corpus keeps the licenses of its sources, see
|
|
238
|
+
[corpus/SOURCES.md](https://github.com/grigoriev/weasyvsdx/blob/main/corpus/SOURCES.md).
|