plotly-print 0.2.3__tar.gz → 0.3.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.
- plotly_print-0.2.3/.cursor/rules/markdown.mdc → plotly_print-0.3.0/.agents/skills/markdown/SKILL.md +5 -4
- plotly_print-0.2.3/.cursor/rules/global.mdc → plotly_print-0.3.0/.agents/skills/project-standards/SKILL.md +3 -3
- plotly_print-0.3.0/.gitignore +36 -0
- plotly_print-0.3.0/AGENTS.md +24 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/PKG-INFO +20 -1
- {plotly_print-0.2.3 → plotly_print-0.3.0}/README.md +19 -0
- plotly_print-0.3.0/THIRD_PARTY_NOTICES.md +154 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/pyproject.toml +7 -2
- plotly_print-0.3.0/src/plotly_print/AGENTS.md +30 -0
- plotly_print-0.3.0/src/plotly_print/_fonts/DejaVu-LICENSE.txt +98 -0
- plotly_print-0.3.0/src/plotly_print/_fonts/DejaVuSans-Bold.ttf +0 -0
- plotly_print-0.3.0/src/plotly_print/_fonts/DejaVuSans.ttf +0 -0
- plotly_print-0.3.0/src/plotly_print/_fonts/DejaVuSansMono.ttf +0 -0
- plotly_print-0.3.0/src/plotly_print/_fonts/DejaVuSerif.ttf +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/src/plotly_print/core.py +27 -7
- {plotly_print-0.2.3 → plotly_print-0.3.0}/src/plotly_print/engine.py +16 -5
- {plotly_print-0.2.3 → plotly_print-0.3.0}/src/plotly_print/fonts.py +75 -13
- plotly_print-0.2.3/.cursor/rules/javascript.mdc → plotly_print-0.3.0/src/plotly_print/js/AGENTS.md +2 -8
- {plotly_print-0.2.3 → plotly_print-0.3.0}/src/plotly_print/plotly_hook.py +9 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/src/plotly_print/raster.py +68 -10
- plotly_print-0.3.0/tests/AGENTS.md +6 -0
- plotly_print-0.3.0/tests/test_fonts.py +112 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/uv.lock +26 -1
- plotly_print-0.2.3/.cursor/rules/map.mdc +0 -34
- plotly_print-0.2.3/.cursorignore +0 -2
- plotly_print-0.2.3/.gitignore +0 -23
- plotly_print-0.2.3/AGENTS.md +0 -17
- plotly_print-0.2.3/THIRD_PARTY_NOTICES.md +0 -40
- {plotly_print-0.2.3 → plotly_print-0.3.0}/.github/workflows/check-tag.yml +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/.github/workflows/publish.yml +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/.github/workflows/quality-checks.yml +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/.github/workflows/version-check.yml +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/.mdformat.toml +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/.pre-commit-config.yaml +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/CONTRIBUTING.md +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/LICENSE +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/benchmark_summary.json +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_annotations_arrowheads.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_annotations_long_arrows.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_bar.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_barpolar.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_box.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_candlestick.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_carpet.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_contour.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_funnel.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_funnelarea.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_heatmap.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_histogram.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_histogram2d.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_icicle.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_indicator.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_ohlc.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_parcats.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_pie.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_rotated_ticks_45.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_rotated_ticks_90.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_sankey.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_scatter_line.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_scatterpolar.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_scatterternary.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_sunburst.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_table.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_table_markup.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_treemap.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_violin.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/assets/benchmarks/compare_waterfall.png +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/benchmark/__init__.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/benchmark/__main__.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/benchmark/cases.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/benchmark/collage.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/benchmark/compare.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/benchmark/report.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/benchmark/runner.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/src/plotly_print/__init__.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/src/plotly_print/js/micro_dom.js +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/src/plotly_print/js/plotly_comprehensive_2d.js +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/tests/test_background.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/tests/test_bar.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/tests/test_cartesian_types.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/tests/test_comprehensive_2d.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/tests/test_heatmap.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/tests/test_json_types.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/tests/test_kaleido_visual.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/tests/test_legend.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/tests/test_pie.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/tests/test_plotly_hook.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/tests/test_raster.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/tests/test_scatter.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/tests/test_svg_path_geometry.py +0 -0
- {plotly_print-0.2.3 → plotly_print-0.3.0}/tests/test_svg_transforms.py +0 -0
plotly_print-0.2.3/.cursor/rules/markdown.mdc → plotly_print-0.3.0/.agents/skills/markdown/SKILL.md
RENAMED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
name: markdown
|
|
3
|
+
description: Markdown formatting standards for plotly-print. Use when creating or editing Markdown files.
|
|
4
|
+
paths:
|
|
5
|
+
- "**/*.md"
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# Markdown
|
|
@@ -13,7 +14,7 @@ Use fenced code blocks with a language tag when the snippet has a language:
|
|
|
13
14
|
```python
|
|
14
15
|
from pathlib import Path
|
|
15
16
|
|
|
16
|
-
Path(
|
|
17
|
+
Path('data') / 'out.csv'
|
|
17
18
|
```
|
|
18
19
|
|
|
19
20
|
Do not leave unlabeled fences for Python, TOML, shell, or JSON. Plain fences are fine for output or prose examples with no language.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
name: project-standards
|
|
3
|
+
description: Coding standards for plotly-print. Use before writing or reviewing code in this repository.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Project standards
|
|
7
7
|
|
|
8
|
-
Python package + QuickJS micro-DOM under `src/plotly_print/js/`. Source of truth: `pyproject.toml` (Python >= 3.12, uv). Package layout and entry points:
|
|
8
|
+
Python package + QuickJS micro-DOM under `src/plotly_print/js/`. Source of truth: `pyproject.toml` (Python >= 3.12, uv). Package layout and entry points: `src/plotly_print/AGENTS.md`.
|
|
9
9
|
|
|
10
10
|
You are a lazy senior developer. Lazy means efficient, not careless. The best code is the code never written.
|
|
11
11
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
.DS_Store
|
|
2
|
+
|
|
3
|
+
.venv/
|
|
4
|
+
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
.ruff_cache/
|
|
8
|
+
.pytest_cache/
|
|
9
|
+
.mypy_cache/
|
|
10
|
+
|
|
11
|
+
.env
|
|
12
|
+
.env.*
|
|
13
|
+
|
|
14
|
+
.idea/
|
|
15
|
+
.vscode/
|
|
16
|
+
|
|
17
|
+
build/
|
|
18
|
+
dist/
|
|
19
|
+
sdist/
|
|
20
|
+
wheels/
|
|
21
|
+
*.egg-info/
|
|
22
|
+
|
|
23
|
+
.artifacts/
|
|
24
|
+
|
|
25
|
+
# Platform-specific agent config, kept local by each maintainer.
|
|
26
|
+
.cursor/
|
|
27
|
+
.cursorignore
|
|
28
|
+
.cursorrules
|
|
29
|
+
.claude/
|
|
30
|
+
CLAUDE.md
|
|
31
|
+
CLAUDE.local.md
|
|
32
|
+
.codex/
|
|
33
|
+
AGENTS.override.md
|
|
34
|
+
.opencode/
|
|
35
|
+
opencode.json
|
|
36
|
+
opencode.jsonc
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Agent instructions
|
|
2
|
+
|
|
3
|
+
plotly-print: Python package + QuickJS micro-DOM for browser-less Plotly static export.
|
|
4
|
+
|
|
5
|
+
## Context, loaded on demand
|
|
6
|
+
|
|
7
|
+
- Package map and flow: `src/plotly_print/AGENTS.md` (auto-loaded there).
|
|
8
|
+
- JS and micro-DOM rules: `src/plotly_print/js/AGENTS.md` (auto-loaded there).
|
|
9
|
+
- Tests: `tests/AGENTS.md` (auto-loaded there).
|
|
10
|
+
- Coding standards: skill `project-standards` (load before changing code).
|
|
11
|
+
- Markdown: skill `markdown` (load before editing `.md`).
|
|
12
|
+
|
|
13
|
+
## Commands
|
|
14
|
+
|
|
15
|
+
`poe format` | `poe test` | `poe check` | `poe benchmark` | `poe format_docs`
|
|
16
|
+
|
|
17
|
+
After Python edits run `poe format`. After Markdown run `poe format_docs`.
|
|
18
|
+
|
|
19
|
+
## Non-negotiables
|
|
20
|
+
|
|
21
|
+
- Vendored `src/plotly_print/js/plotly_comprehensive_2d.js`: never open whole-file, never edit. Use capped shell `grep -o ... | head`.
|
|
22
|
+
- No new dependency outside `pyproject.toml` and the lockfile.
|
|
23
|
+
- Scratch under `.artifacts/` (gitignored); do not commit.
|
|
24
|
+
- ASCII only in identifiers, comments, and docs; no emojis.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: plotly-print
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Lightweight, browser-less static image exporter for Plotly
|
|
5
5
|
Project-URL: Homepage, https://github.com/roman-kaczanowski/plotly-print
|
|
6
6
|
Project-URL: Repository, https://github.com/roman-kaczanowski/plotly-print
|
|
@@ -75,6 +75,25 @@ After registration, existing calls such as `fig.write_image("chart.png")` use pl
|
|
|
75
75
|
|
|
76
76
|
plotly-print targets 2D static charts. The bundled Plotly.js build and its licenses are documented in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
|
77
77
|
|
|
78
|
+
## Fonts
|
|
79
|
+
|
|
80
|
+
Figures keep the font families you set, including `layout.font.family` and any per-trace or per-element override. If a family is not installed, plotly-print uses a system font. With no system fonts, it falls back to the bundled DejaVu Sans, DejaVu Serif, and DejaVu Sans Mono. Licenses for those fonts are in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
|
81
|
+
|
|
82
|
+
To use your own files, set the family on the figure and pass them with the export:
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
fig.update_layout(font={'family': 'Inter'})
|
|
86
|
+
|
|
87
|
+
plotly_print.write_image(
|
|
88
|
+
fig,
|
|
89
|
+
'chart.png',
|
|
90
|
+
font_files=['fonts/Inter-Regular.ttf'],
|
|
91
|
+
# or: font_dirs=['fonts'],
|
|
92
|
+
)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`font_files` and `font_dirs` also work with `to_svg`, `to_image`, and with `fig.write_image` after `plotly_print.register()`.
|
|
96
|
+
|
|
78
97
|
<!-- BENCHMARK-START -->
|
|
79
98
|
|
|
80
99
|
## Benchmarks
|
|
@@ -49,6 +49,25 @@ After registration, existing calls such as `fig.write_image("chart.png")` use pl
|
|
|
49
49
|
|
|
50
50
|
plotly-print targets 2D static charts. The bundled Plotly.js build and its licenses are documented in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
|
51
51
|
|
|
52
|
+
## Fonts
|
|
53
|
+
|
|
54
|
+
Figures keep the font families you set, including `layout.font.family` and any per-trace or per-element override. If a family is not installed, plotly-print uses a system font. With no system fonts, it falls back to the bundled DejaVu Sans, DejaVu Serif, and DejaVu Sans Mono. Licenses for those fonts are in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
|
55
|
+
|
|
56
|
+
To use your own files, set the family on the figure and pass them with the export:
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
fig.update_layout(font={'family': 'Inter'})
|
|
60
|
+
|
|
61
|
+
plotly_print.write_image(
|
|
62
|
+
fig,
|
|
63
|
+
'chart.png',
|
|
64
|
+
font_files=['fonts/Inter-Regular.ttf'],
|
|
65
|
+
# or: font_dirs=['fonts'],
|
|
66
|
+
)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`font_files` and `font_dirs` also work with `to_svg`, `to_image`, and with `fig.write_image` after `plotly_print.register()`.
|
|
70
|
+
|
|
52
71
|
<!-- BENCHMARK-START -->
|
|
53
72
|
|
|
54
73
|
## Benchmarks
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
## plotly.js
|
|
4
|
+
|
|
5
|
+
File: `src/plotly_print/js/plotly_comprehensive_2d.js`
|
|
6
|
+
|
|
7
|
+
Redistributed plotly.js build (minified) used for offline / isolated 2D static
|
|
8
|
+
rendering in the embedded QuickJS runtime. The full `plotly.min.js` shipped with
|
|
9
|
+
the `plotly` Python package does not load in that runtime, so this smaller
|
|
10
|
+
bundle is included instead.
|
|
11
|
+
|
|
12
|
+
Copyright 2012-2026, Plotly, Inc.
|
|
13
|
+
All rights reserved.
|
|
14
|
+
Licensed under the MIT license.
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
The MIT License (MIT)
|
|
18
|
+
|
|
19
|
+
Copyright (c) 2014-2026 Plotly, Inc
|
|
20
|
+
|
|
21
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
22
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
23
|
+
in the Software without restriction, including without limitation the rights
|
|
24
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
25
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
26
|
+
furnished to do so, subject to the following conditions:
|
|
27
|
+
|
|
28
|
+
The above copyright notice and this permission notice shall be included in
|
|
29
|
+
all copies or substantial portions of the Software.
|
|
30
|
+
|
|
31
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
32
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
33
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
34
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
35
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
36
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
37
|
+
THE SOFTWARE.
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Upstream: https://github.com/plotly/plotly.js
|
|
41
|
+
|
|
42
|
+
## DejaVu fonts
|
|
43
|
+
|
|
44
|
+
Files: `src/plotly_print/_fonts/DejaVuSans.ttf`,
|
|
45
|
+
`src/plotly_print/_fonts/DejaVuSans-Bold.ttf`,
|
|
46
|
+
`src/plotly_print/_fonts/DejaVuSerif.ttf`,
|
|
47
|
+
`src/plotly_print/_fonts/DejaVuSansMono.ttf`
|
|
48
|
+
|
|
49
|
+
Bundled as a fallback for systems without the fonts requested by a figure.
|
|
50
|
+
DejaVu changes are in the public domain; the original glyphs are covered by
|
|
51
|
+
the Bitstream Vera and Arev licenses below.
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
|
|
55
|
+
Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
Bitstream Vera Fonts Copyright
|
|
59
|
+
------------------------------
|
|
60
|
+
|
|
61
|
+
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
|
|
62
|
+
a trademark of Bitstream, Inc.
|
|
63
|
+
|
|
64
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
65
|
+
of the fonts accompanying this license ("Fonts") and associated
|
|
66
|
+
documentation files (the "Font Software"), to reproduce and distribute the
|
|
67
|
+
Font Software, including without limitation the rights to use, copy, merge,
|
|
68
|
+
publish, distribute, and/or sell copies of the Font Software, and to permit
|
|
69
|
+
persons to whom the Font Software is furnished to do so, subject to the
|
|
70
|
+
following conditions:
|
|
71
|
+
|
|
72
|
+
The above copyright and trademark notices and this permission notice shall
|
|
73
|
+
be included in all copies of one or more of the Font Software typefaces.
|
|
74
|
+
|
|
75
|
+
The Font Software may be modified, altered, or added to, and in particular
|
|
76
|
+
the designs of glyphs or characters in the Fonts may be modified and
|
|
77
|
+
additional glyphs or characters may be added to the Fonts, only if the fonts
|
|
78
|
+
are renamed to names not containing either the words "Bitstream" or the word
|
|
79
|
+
"Vera".
|
|
80
|
+
|
|
81
|
+
This License becomes null and void to the extent applicable to Fonts or Font
|
|
82
|
+
Software that has been modified and is distributed under the "Bitstream
|
|
83
|
+
Vera" names.
|
|
84
|
+
|
|
85
|
+
The Font Software may be sold as part of a larger software package but no
|
|
86
|
+
copy of one or more of the Font Software typefaces may be sold by itself.
|
|
87
|
+
|
|
88
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
89
|
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
|
|
90
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
|
|
91
|
+
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
|
|
92
|
+
FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
|
|
93
|
+
ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
|
|
94
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
|
95
|
+
THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
|
|
96
|
+
FONT SOFTWARE.
|
|
97
|
+
|
|
98
|
+
Except as contained in this notice, the names of Gnome, the Gnome
|
|
99
|
+
Foundation, and Bitstream Inc., shall not be used in advertising or
|
|
100
|
+
otherwise to promote the sale, use or other dealings in this Font Software
|
|
101
|
+
without prior written authorization from the Gnome Foundation or Bitstream
|
|
102
|
+
Inc., respectively. For further information, contact: fonts at gnome dot
|
|
103
|
+
org.
|
|
104
|
+
|
|
105
|
+
Arev Fonts Copyright
|
|
106
|
+
------------------------------
|
|
107
|
+
|
|
108
|
+
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
|
|
109
|
+
|
|
110
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
111
|
+
a copy of the fonts accompanying this license ("Fonts") and
|
|
112
|
+
associated documentation files (the "Font Software"), to reproduce
|
|
113
|
+
and distribute the modifications to the Bitstream Vera Font Software,
|
|
114
|
+
including without limitation the rights to use, copy, merge, publish,
|
|
115
|
+
distribute, and/or sell copies of the Font Software, and to permit
|
|
116
|
+
persons to whom the Font Software is furnished to do so, subject to
|
|
117
|
+
the following conditions:
|
|
118
|
+
|
|
119
|
+
The above copyright and trademark notices and this permission notice
|
|
120
|
+
shall be included in all copies of one or more of the Font Software
|
|
121
|
+
typefaces.
|
|
122
|
+
|
|
123
|
+
The Font Software may be modified, altered, or added to, and in
|
|
124
|
+
particular the designs of glyphs or characters in the Fonts may be
|
|
125
|
+
modified and additional glyphs or characters may be added to the
|
|
126
|
+
Fonts, only if the fonts are renamed to names not containing either
|
|
127
|
+
the words "Tavmjong Bah" or the word "Arev".
|
|
128
|
+
|
|
129
|
+
This License becomes null and void to the extent applicable to Fonts
|
|
130
|
+
or Font Software that has been modified and is distributed under the
|
|
131
|
+
"Tavmjong Bah Arev" names.
|
|
132
|
+
|
|
133
|
+
The Font Software may be sold as part of a larger software package but
|
|
134
|
+
no copy of one or more of the Font Software typefaces may be sold by
|
|
135
|
+
itself.
|
|
136
|
+
|
|
137
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
138
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
139
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
140
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
|
|
141
|
+
TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
142
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
143
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
144
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
145
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
146
|
+
|
|
147
|
+
Except as contained in this notice, the name of Tavmjong Bah shall not
|
|
148
|
+
be used in advertising or otherwise to promote the sale, use or other
|
|
149
|
+
dealings in this Font Software without prior written authorization
|
|
150
|
+
from Tavmjong Bah. For further information, contact: tavmjong @ free
|
|
151
|
+
. fr.
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Upstream: https://github.com/dejavu-fonts/dejavu-fonts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "plotly-print"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.0"
|
|
4
4
|
description = "Lightweight, browser-less static image exporter for Plotly"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -38,7 +38,11 @@ build-backend = "hatchling.build"
|
|
|
38
38
|
|
|
39
39
|
[tool.hatch.build.targets.wheel]
|
|
40
40
|
packages = ["src/plotly_print"]
|
|
41
|
-
# benchmark/
|
|
41
|
+
# benchmark/ and nested agent instructions are dev-only.
|
|
42
|
+
exclude = [
|
|
43
|
+
"src/plotly_print/AGENTS.md",
|
|
44
|
+
"src/plotly_print/js/AGENTS.md",
|
|
45
|
+
]
|
|
42
46
|
|
|
43
47
|
[tool.uv]
|
|
44
48
|
default-groups = ["dev", "test"]
|
|
@@ -52,6 +56,7 @@ test = [
|
|
|
52
56
|
"kaleido>=0.2.1",
|
|
53
57
|
"ruff",
|
|
54
58
|
"mdformat",
|
|
59
|
+
"mdformat-frontmatter>=2.1.2",
|
|
55
60
|
"mdformat-gfm",
|
|
56
61
|
"mdformat-tables",
|
|
57
62
|
]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Package map
|
|
2
|
+
|
|
3
|
+
Browser-less Plotly static export: QuickJS + micro-DOM + vendored Plotly 2D -> SVG -> resvg raster.
|
|
4
|
+
|
|
5
|
+
## Flow
|
|
6
|
+
|
|
7
|
+
`core.to_svg` / `to_image` / `write_image` -> `engine.PrintEngine` (QuickJS) -> eval `micro_dom.js` + vendored Plotly -> SVG -> `raster.py` for png/jpeg/webp.
|
|
8
|
+
|
|
9
|
+
`plotly_hook.register` patches Plotly `to_image` / `write_image`.
|
|
10
|
+
|
|
11
|
+
## Files
|
|
12
|
+
|
|
13
|
+
| Path | Job |
|
|
14
|
+
| ------------------------------- | ----------------------------------------------- |
|
|
15
|
+
| `core.py` | Public API; figure -> JSON |
|
|
16
|
+
| `engine.py` | QuickJS lifecycle; canvas -> PNG; typed arrays |
|
|
17
|
+
| `fonts.py` | Text metrics callable into JS; font fallbacks |
|
|
18
|
+
| `_fonts/` | Bundled DejaVu fallback fonts + license |
|
|
19
|
+
| `raster.py` | SVG -> raster (resvg) |
|
|
20
|
+
| `plotly_hook.py` | Monkeypatch Plotly |
|
|
21
|
+
| `js/micro_dom.js` | First-party DOM/SVG stubs (**edit here**) |
|
|
22
|
+
| `js/plotly_comprehensive_2d.js` | Vendored; **never** read or grep the whole file |
|
|
23
|
+
|
|
24
|
+
Start from this map. Open only listed files unless the task is outside `src/plotly_print/`.
|
|
25
|
+
|
|
26
|
+
## Related context
|
|
27
|
+
|
|
28
|
+
- JS and micro-DOM: `js/AGENTS.md`.
|
|
29
|
+
- Tests: `../../tests/AGENTS.md`.
|
|
30
|
+
- Vendored bundle: opaque; never read or grep the whole file. Use capped shell `grep -o ... | head` for call shapes.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
|
|
2
|
+
Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
Bitstream Vera Fonts Copyright
|
|
6
|
+
------------------------------
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
|
|
9
|
+
a trademark of Bitstream, Inc.
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of the fonts accompanying this license ("Fonts") and associated
|
|
13
|
+
documentation files (the "Font Software"), to reproduce and distribute the
|
|
14
|
+
Font Software, including without limitation the rights to use, copy, merge,
|
|
15
|
+
publish, distribute, and/or sell copies of the Font Software, and to permit
|
|
16
|
+
persons to whom the Font Software is furnished to do so, subject to the
|
|
17
|
+
following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright and trademark notices and this permission notice shall
|
|
20
|
+
be included in all copies of one or more of the Font Software typefaces.
|
|
21
|
+
|
|
22
|
+
The Font Software may be modified, altered, or added to, and in particular
|
|
23
|
+
the designs of glyphs or characters in the Fonts may be modified and
|
|
24
|
+
additional glyphs or characters may be added to the Fonts, only if the fonts
|
|
25
|
+
are renamed to names not containing either the words "Bitstream" or the word
|
|
26
|
+
"Vera".
|
|
27
|
+
|
|
28
|
+
This License becomes null and void to the extent applicable to Fonts or Font
|
|
29
|
+
Software that has been modified and is distributed under the "Bitstream
|
|
30
|
+
Vera" names.
|
|
31
|
+
|
|
32
|
+
The Font Software may be sold as part of a larger software package but no
|
|
33
|
+
copy of one or more of the Font Software typefaces may be sold by itself.
|
|
34
|
+
|
|
35
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
36
|
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
|
|
37
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
|
|
38
|
+
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
|
|
39
|
+
FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
|
|
40
|
+
ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
|
|
41
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
|
42
|
+
THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
|
|
43
|
+
FONT SOFTWARE.
|
|
44
|
+
|
|
45
|
+
Except as contained in this notice, the names of Gnome, the Gnome
|
|
46
|
+
Foundation, and Bitstream Inc., shall not be used in advertising or
|
|
47
|
+
otherwise to promote the sale, use or other dealings in this Font Software
|
|
48
|
+
without prior written authorization from the Gnome Foundation or Bitstream
|
|
49
|
+
Inc., respectively. For further information, contact: fonts at gnome dot
|
|
50
|
+
org.
|
|
51
|
+
|
|
52
|
+
Arev Fonts Copyright
|
|
53
|
+
------------------------------
|
|
54
|
+
|
|
55
|
+
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
|
|
56
|
+
|
|
57
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
58
|
+
a copy of the fonts accompanying this license ("Fonts") and
|
|
59
|
+
associated documentation files (the "Font Software"), to reproduce
|
|
60
|
+
and distribute the modifications to the Bitstream Vera Font Software,
|
|
61
|
+
including without limitation the rights to use, copy, merge, publish,
|
|
62
|
+
distribute, and/or sell copies of the Font Software, and to permit
|
|
63
|
+
persons to whom the Font Software is furnished to do so, subject to
|
|
64
|
+
the following conditions:
|
|
65
|
+
|
|
66
|
+
The above copyright and trademark notices and this permission notice
|
|
67
|
+
shall be included in all copies of one or more of the Font Software
|
|
68
|
+
typefaces.
|
|
69
|
+
|
|
70
|
+
The Font Software may be modified, altered, or added to, and in
|
|
71
|
+
particular the designs of glyphs or characters in the Fonts may be
|
|
72
|
+
modified and additional glyphs or characters may be added to the
|
|
73
|
+
Fonts, only if the fonts are renamed to names not containing either
|
|
74
|
+
the words "Tavmjong Bah" or the word "Arev".
|
|
75
|
+
|
|
76
|
+
This License becomes null and void to the extent applicable to Fonts
|
|
77
|
+
or Font Software that has been modified and is distributed under the
|
|
78
|
+
"Tavmjong Bah Arev" names.
|
|
79
|
+
|
|
80
|
+
The Font Software may be sold as part of a larger software package but
|
|
81
|
+
no copy of one or more of the Font Software typefaces may be sold by
|
|
82
|
+
itself.
|
|
83
|
+
|
|
84
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
85
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
86
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
87
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
|
|
88
|
+
TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
89
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
90
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
91
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
92
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
93
|
+
|
|
94
|
+
Except as contained in this notice, the name of Tavmjong Bah shall not
|
|
95
|
+
be used in advertising or otherwise to promote the sale, use or other
|
|
96
|
+
dealings in this Font Software without prior written authorization
|
|
97
|
+
from Tavmjong Bah. For further information, contact: tavmjong @ free
|
|
98
|
+
. fr.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -4,6 +4,7 @@ import os
|
|
|
4
4
|
from typing import Any, BinaryIO
|
|
5
5
|
|
|
6
6
|
from plotly_print.engine import get_engine
|
|
7
|
+
from plotly_print.fonts import FontPaths, resolve_font_dirs, resolve_font_files
|
|
7
8
|
from plotly_print.raster import svg_to_jpeg, svg_to_png, svg_to_webp, write_raster
|
|
8
9
|
|
|
9
10
|
|
|
@@ -22,9 +23,11 @@ def to_svg(
|
|
|
22
23
|
fig: Any,
|
|
23
24
|
width: int | None = None,
|
|
24
25
|
height: int | None = None,
|
|
26
|
+
font_files: FontPaths | None = None,
|
|
27
|
+
font_dirs: FontPaths | None = None,
|
|
25
28
|
) -> str:
|
|
26
29
|
data, layout = _extract_figure_spec(fig)
|
|
27
|
-
return get_engine().render_svg(data, layout, width=width, height=height)
|
|
30
|
+
return get_engine().render_svg(data, layout, width=width, height=height, font_files=font_files, font_dirs=font_dirs)
|
|
28
31
|
|
|
29
32
|
|
|
30
33
|
def to_image(
|
|
@@ -33,18 +36,22 @@ def to_image(
|
|
|
33
36
|
width: int | None = None,
|
|
34
37
|
height: int | None = None,
|
|
35
38
|
scale: float = 1.0,
|
|
39
|
+
font_files: FontPaths | None = None,
|
|
40
|
+
font_dirs: FontPaths | None = None,
|
|
36
41
|
) -> bytes:
|
|
37
42
|
fmt = format.lower().strip()
|
|
38
|
-
|
|
43
|
+
font_files = resolve_font_files(font_files) or None
|
|
44
|
+
font_dirs = resolve_font_dirs(font_dirs) or None
|
|
45
|
+
svg = to_svg(fig, width=width, height=height, font_files=font_files, font_dirs=font_dirs)
|
|
39
46
|
|
|
40
47
|
if fmt == 'svg':
|
|
41
48
|
return svg.encode('utf-8')
|
|
42
49
|
if fmt == 'png':
|
|
43
|
-
return svg_to_png(svg, width=width, height=height, scale=scale)
|
|
50
|
+
return svg_to_png(svg, width=width, height=height, scale=scale, font_files=font_files, font_dirs=font_dirs)
|
|
44
51
|
if fmt in ('jpg', 'jpeg'):
|
|
45
|
-
return svg_to_jpeg(svg, width=width, height=height, scale=scale)
|
|
52
|
+
return svg_to_jpeg(svg, width=width, height=height, scale=scale, font_files=font_files, font_dirs=font_dirs)
|
|
46
53
|
if fmt == 'webp':
|
|
47
|
-
return svg_to_webp(svg, width=width, height=height, scale=scale)
|
|
54
|
+
return svg_to_webp(svg, width=width, height=height, scale=scale, font_files=font_files, font_dirs=font_dirs)
|
|
48
55
|
raise ValueError(f"Unsupported format: {format}. Supported: 'svg', 'png', 'jpeg', 'webp'")
|
|
49
56
|
|
|
50
57
|
|
|
@@ -55,6 +62,8 @@ def write_image(
|
|
|
55
62
|
scale: float = 1.0,
|
|
56
63
|
width: int | None = None,
|
|
57
64
|
height: int | None = None,
|
|
65
|
+
font_files: FontPaths | None = None,
|
|
66
|
+
font_dirs: FontPaths | None = None,
|
|
58
67
|
) -> None:
|
|
59
68
|
if format is None:
|
|
60
69
|
if isinstance(file, (str, os.PathLike)):
|
|
@@ -64,7 +73,9 @@ def write_image(
|
|
|
64
73
|
format = 'png'
|
|
65
74
|
|
|
66
75
|
fmt = format.lower().strip()
|
|
67
|
-
|
|
76
|
+
font_files = resolve_font_files(font_files) or None
|
|
77
|
+
font_dirs = resolve_font_dirs(font_dirs) or None
|
|
78
|
+
svg_str = to_svg(fig, width=width, height=height, font_files=font_files, font_dirs=font_dirs)
|
|
68
79
|
if fmt == 'svg':
|
|
69
80
|
if isinstance(file, (str, os.PathLike)):
|
|
70
81
|
with open(file, 'w', encoding='utf-8') as f:
|
|
@@ -73,4 +84,13 @@ def write_image(
|
|
|
73
84
|
file.write(svg_str.encode('utf-8'))
|
|
74
85
|
return
|
|
75
86
|
|
|
76
|
-
write_raster(
|
|
87
|
+
write_raster(
|
|
88
|
+
svg_str,
|
|
89
|
+
file,
|
|
90
|
+
format=fmt,
|
|
91
|
+
width=width,
|
|
92
|
+
height=height,
|
|
93
|
+
scale=scale,
|
|
94
|
+
font_files=font_files,
|
|
95
|
+
font_dirs=font_dirs,
|
|
96
|
+
)
|
|
@@ -13,7 +13,7 @@ import quickjs
|
|
|
13
13
|
from PIL import Image, ImageColor, ImageDraw
|
|
14
14
|
from plotly.utils import PlotlyJSONEncoder
|
|
15
15
|
|
|
16
|
-
from plotly_print.fonts import get_default_font_manager
|
|
16
|
+
from plotly_print.fonts import FontManager, FontPaths, get_default_font_manager
|
|
17
17
|
|
|
18
18
|
_JS_DIR = Path(__file__).resolve().parent / 'js'
|
|
19
19
|
_MICRO_DOM_PATH = _JS_DIR / 'micro_dom.js'
|
|
@@ -139,7 +139,7 @@ class PrintEngine:
|
|
|
139
139
|
self.context = quickjs.Context()
|
|
140
140
|
self.context.set_max_stack_size(10 * 1024 * 1024)
|
|
141
141
|
|
|
142
|
-
self.context.add_callable('_measureTextRaw', self.
|
|
142
|
+
self.context.add_callable('_measureTextRaw', self._measure_text_raw)
|
|
143
143
|
self.context.add_callable('_encodeCanvasToPNG', _encode_canvas_to_png)
|
|
144
144
|
|
|
145
145
|
if not _PLOTLY_JS_PATH.is_file():
|
|
@@ -206,12 +206,17 @@ class PrintEngine:
|
|
|
206
206
|
}
|
|
207
207
|
""")
|
|
208
208
|
|
|
209
|
+
def _measure_text_raw(self, text: str, family: str, size_str: str, weight: str = '') -> str:
|
|
210
|
+
return self.font_manager.measure_raw(text, family, size_str, weight)
|
|
211
|
+
|
|
209
212
|
def render_svg(
|
|
210
213
|
self,
|
|
211
214
|
data: list[dict[str, Any]],
|
|
212
215
|
layout: dict[str, Any],
|
|
213
216
|
width: int | None = None,
|
|
214
217
|
height: int | None = None,
|
|
218
|
+
font_files: FontPaths | None = None,
|
|
219
|
+
font_dirs: FontPaths | None = None,
|
|
215
220
|
) -> str:
|
|
216
221
|
layout_copy = dict(layout) if layout else {}
|
|
217
222
|
if width is not None:
|
|
@@ -222,9 +227,15 @@ class PrintEngine:
|
|
|
222
227
|
data_json = json.dumps(_expand_typed_arrays(data), cls=PlotlyJSONEncoder)
|
|
223
228
|
layout_json = json.dumps(_expand_typed_arrays(layout_copy), cls=PlotlyJSONEncoder)
|
|
224
229
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
230
|
+
previous_font_manager = self.font_manager
|
|
231
|
+
if font_files is not None or font_dirs is not None:
|
|
232
|
+
self.font_manager = FontManager(font_files, font_dirs)
|
|
233
|
+
try:
|
|
234
|
+
self.context.eval(f'var __plotly_print_data = {json.dumps(data_json)};')
|
|
235
|
+
self.context.eval(f'var __plotly_print_layout = {json.dumps(layout_json)};')
|
|
236
|
+
svg = self.context.eval('plotlyPrintRender(__plotly_print_data, __plotly_print_layout);')
|
|
237
|
+
finally:
|
|
238
|
+
self.font_manager = previous_font_manager
|
|
228
239
|
if not svg:
|
|
229
240
|
raise RuntimeError('plotly-print rendering failed: No SVG element was generated by Plotly.')
|
|
230
241
|
return svg
|