plotly-print 0.2.2__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.2/.cursor/rules/markdown.mdc → plotly_print-0.3.0/.agents/skills/markdown/SKILL.md +5 -4
- plotly_print-0.3.0/.agents/skills/project-standards/SKILL.md +52 -0
- plotly_print-0.3.0/.gitignore +36 -0
- plotly_print-0.3.0/AGENTS.md +24 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/PKG-INFO +20 -1
- {plotly_print-0.2.2 → plotly_print-0.3.0}/README.md +19 -0
- plotly_print-0.3.0/THIRD_PARTY_NOTICES.md +154 -0
- {plotly_print-0.2.2 → 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.2 → plotly_print-0.3.0}/src/plotly_print/core.py +27 -7
- {plotly_print-0.2.2 → plotly_print-0.3.0}/src/plotly_print/engine.py +83 -8
- {plotly_print-0.2.2 → plotly_print-0.3.0}/src/plotly_print/fonts.py +75 -13
- plotly_print-0.2.2/.cursor/rules/javascript.mdc → plotly_print-0.3.0/src/plotly_print/js/AGENTS.md +2 -7
- {plotly_print-0.2.2 → plotly_print-0.3.0}/src/plotly_print/plotly_hook.py +9 -0
- {plotly_print-0.2.2 → 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.2 → plotly_print-0.3.0}/tests/test_json_types.py +58 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/uv.lock +26 -1
- plotly_print-0.2.2/.cursor/rules/artifacts.mdc +0 -14
- plotly_print-0.2.2/.cursor/rules/global.mdc +0 -72
- plotly_print-0.2.2/.gitignore +0 -23
- plotly_print-0.2.2/AGENTS.md +0 -15
- plotly_print-0.2.2/THIRD_PARTY_NOTICES.md +0 -40
- {plotly_print-0.2.2 → plotly_print-0.3.0}/.github/workflows/check-tag.yml +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/.github/workflows/publish.yml +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/.github/workflows/quality-checks.yml +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/.github/workflows/version-check.yml +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/.mdformat.toml +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/.pre-commit-config.yaml +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/CONTRIBUTING.md +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/LICENSE +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/benchmark_summary.json +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_annotations_arrowheads.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_annotations_long_arrows.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_bar.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_barpolar.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_box.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_candlestick.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_carpet.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_contour.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_funnel.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_funnelarea.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_heatmap.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_histogram.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_histogram2d.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_icicle.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_indicator.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_ohlc.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_parcats.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_pie.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_rotated_ticks_45.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_rotated_ticks_90.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_sankey.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_scatter_line.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_scatterpolar.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_scatterternary.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_sunburst.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_table.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_table_markup.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_treemap.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_violin.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/assets/benchmarks/compare_waterfall.png +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/benchmark/__init__.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/benchmark/__main__.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/benchmark/cases.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/benchmark/collage.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/benchmark/compare.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/benchmark/report.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/benchmark/runner.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/src/plotly_print/__init__.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/src/plotly_print/js/micro_dom.js +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/src/plotly_print/js/plotly_comprehensive_2d.js +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/tests/test_background.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/tests/test_bar.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/tests/test_cartesian_types.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/tests/test_comprehensive_2d.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/tests/test_heatmap.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/tests/test_kaleido_visual.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/tests/test_legend.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/tests/test_pie.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/tests/test_plotly_hook.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/tests/test_raster.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/tests/test_scatter.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/tests/test_svg_path_geometry.py +0 -0
- {plotly_print-0.2.2 → plotly_print-0.3.0}/tests/test_svg_transforms.py +0 -0
plotly_print-0.2.2/.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.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: project-standards
|
|
3
|
+
description: Coding standards for plotly-print. Use before writing or reviewing code in this repository.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Project standards
|
|
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: `src/plotly_print/AGENTS.md`.
|
|
9
|
+
|
|
10
|
+
You are a lazy senior developer. Lazy means efficient, not careless. The best code is the code never written.
|
|
11
|
+
|
|
12
|
+
## Before writing code
|
|
13
|
+
|
|
14
|
+
Read the task and the code it touches, trace the real flow end to end, then stop at the first rung that holds:
|
|
15
|
+
|
|
16
|
+
1. Does this need to be built at all? (YAGNI)
|
|
17
|
+
2. Does it already exist in this codebase? Reuse it.
|
|
18
|
+
3. Does the standard library already do this? Use it.
|
|
19
|
+
4. Does an already-declared dependency solve it? Use it.
|
|
20
|
+
5. Can this be one boring line? Make it one line.
|
|
21
|
+
6. Only then: write the minimum code that works.
|
|
22
|
+
|
|
23
|
+
Bug fix = root cause, not symptom. Grep every caller of the function you touch and fix the shared function once.
|
|
24
|
+
|
|
25
|
+
## Toolchain
|
|
26
|
+
|
|
27
|
+
- Do not add a dependency unless it is declared in `pyproject.toml` (or the lockfile). Prefer stdlib.
|
|
28
|
+
- Ruff via `pyproject.toml`. After Python edits: `poe format`. After Markdown: `poe format_docs`.
|
|
29
|
+
- No JS formatter/linter; match `micro_dom.js`. Never hand-edit vendored Plotly bundles.
|
|
30
|
+
|
|
31
|
+
## Comments and docs
|
|
32
|
+
|
|
33
|
+
- No docstrings except on base/abstract contracts and complex functions that need them.
|
|
34
|
+
- No unnecessary comments; if needed, explain why, not what.
|
|
35
|
+
- No section-divider comments in classes/functions (allowed in test classes). Group by proximity.
|
|
36
|
+
|
|
37
|
+
## Language
|
|
38
|
+
|
|
39
|
+
Shared: ASCII only in identifiers/comments/docs (no emojis). No unnecessary imports.
|
|
40
|
+
|
|
41
|
+
Python: type-hint every function/method; f-strings; join with `/` on `Path` (avoid extra wrappers).
|
|
42
|
+
|
|
43
|
+
## Quality
|
|
44
|
+
|
|
45
|
+
- Deletion over addition. Boring over clever. Fewest files; shortest working diff after understanding the problem.
|
|
46
|
+
- No unrequested abstractions, boilerplate, or dependencies. Question complex asks: does Y cover it?
|
|
47
|
+
- Prefer the edge-case-correct stdlib approach when sizes match.
|
|
48
|
+
- Deliberate ceilings: `ponytail:` comment naming the ceiling and upgrade path.
|
|
49
|
+
- Non-trivial logic: one smallest test that fails if it breaks. Run `poe test` before claiming done.
|
|
50
|
+
- No secrets, `.env`, or local virtualenvs in commits.
|
|
51
|
+
|
|
52
|
+
Not lazy about: understanding the problem, trust-boundary validation, error handling that prevents data loss, security, anything explicitly requested.
|
|
@@ -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
|
+
)
|