dynimg 0.1.9__cp311-abi3-macosx_10_12_x86_64.whl

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.
dynimg/__init__.py ADDED
@@ -0,0 +1,35 @@
1
+ """
2
+ dynimg - Fast HTML/CSS to image rendering
3
+
4
+ Example:
5
+ >>> import dynimg
6
+ >>> html = '''
7
+ ... <html>
8
+ ... <body style="background: linear-gradient(135deg, #667eea, #764ba2);
9
+ ... display: flex; justify-content: center; align-items: center;
10
+ ... height: 630px; margin: 0;">
11
+ ... <h1 style="color: white; font-family: system-ui; font-size: 64px;">
12
+ ... Hello World
13
+ ... </h1>
14
+ ... </body>
15
+ ... </html>
16
+ ... '''
17
+ >>> image = dynimg.render(html)
18
+ >>> image.save_png("output.png")
19
+ """
20
+
21
+ from dynimg._dynimg import (
22
+ RenderOptions,
23
+ Image,
24
+ render,
25
+ render_to_file,
26
+ )
27
+
28
+ __all__ = [
29
+ "RenderOptions",
30
+ "Image",
31
+ "render",
32
+ "render_to_file",
33
+ ]
34
+
35
+ __version__ = "0.1.0"
dynimg/__init__.pyi ADDED
@@ -0,0 +1,111 @@
1
+ """Type stubs for dynimg"""
2
+
3
+ from typing import Optional
4
+
5
+ class RenderOptions:
6
+ """Options for rendering HTML to an image"""
7
+
8
+ width: int
9
+ height: Optional[int]
10
+ scale: float
11
+ allow_net: bool
12
+ assets_dir: Optional[str]
13
+ base_url: Optional[str]
14
+
15
+ def __init__(
16
+ self,
17
+ width: int = 1200,
18
+ height: Optional[int] = None,
19
+ scale: float = 2.0,
20
+ allow_net: bool = False,
21
+ assets_dir: Optional[str] = None,
22
+ base_url: Optional[str] = None,
23
+ ) -> None: ...
24
+
25
+ class Image:
26
+ """A rendered image with RGBA pixel data"""
27
+
28
+ @property
29
+ def width(self) -> int:
30
+ """Image width in pixels"""
31
+ ...
32
+
33
+ @property
34
+ def height(self) -> int:
35
+ """Image height in pixels"""
36
+ ...
37
+
38
+ @property
39
+ def data(self) -> bytes:
40
+ """Raw RGBA pixel data"""
41
+ ...
42
+
43
+ def save_png(self, path: str) -> None:
44
+ """Save the image as PNG"""
45
+ ...
46
+
47
+ def save_jpeg(self, path: str, quality: int = 90) -> None:
48
+ """Save the image as JPEG with the specified quality (1-100)"""
49
+ ...
50
+
51
+ def save_webp(self, path: str) -> None:
52
+ """Save the image as lossless WebP"""
53
+ ...
54
+
55
+ def to_png(self) -> bytes:
56
+ """Encode the image as PNG bytes"""
57
+ ...
58
+
59
+ def to_jpeg(self, quality: int = 90) -> bytes:
60
+ """Encode the image as JPEG bytes with the specified quality (1-100)"""
61
+ ...
62
+
63
+ def to_webp(self) -> bytes:
64
+ """Encode the image as lossless WebP bytes"""
65
+ ...
66
+
67
+ def render(html: str, options: Optional[RenderOptions] = None) -> Image:
68
+ """
69
+ Render HTML to an image.
70
+
71
+ Args:
72
+ html: The HTML content to render
73
+ options: Rendering options (optional, uses defaults if not provided)
74
+
75
+ Returns:
76
+ The rendered image
77
+
78
+ Example:
79
+ >>> import dynimg
80
+ >>> html = '<html><body style="background: blue;"><h1>Hello</h1></body></html>'
81
+ >>> image = dynimg.render(html)
82
+ >>> image.save_png("output.png")
83
+ """
84
+ ...
85
+
86
+ def render_to_file(
87
+ html: str,
88
+ path: str,
89
+ options: Optional[RenderOptions] = None,
90
+ quality: int = 90,
91
+ ) -> None:
92
+ """
93
+ Render HTML and save directly to a file.
94
+
95
+ The output format is detected from the file extension.
96
+
97
+ Args:
98
+ html: The HTML content to render
99
+ path: Output file path (.png, .jpg, .webp)
100
+ options: Rendering options (optional)
101
+ quality: JPEG quality 1-100 (default: 90, ignored for PNG/WebP)
102
+
103
+ Example:
104
+ >>> import dynimg
105
+ >>> html = '<html><body><h1>Hello</h1></body></html>'
106
+ >>> dynimg.render_to_file(html, "output.png")
107
+ """
108
+ ...
109
+
110
+ __version__: str
111
+ __all__: list[str]
dynimg/_dynimg.abi3.so ADDED
Binary file
dynimg/py.typed ADDED
File without changes
@@ -0,0 +1,423 @@
1
+ Metadata-Version: 2.4
2
+ Name: dynimg
3
+ Version: 0.1.9
4
+ Classifier: Development Status :: 4 - Beta
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: License :: OSI Approved :: MIT License
7
+ Classifier: Operating System :: MacOS
8
+ Classifier: Operating System :: POSIX :: Linux
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Rust
14
+ Classifier: Topic :: Multimedia :: Graphics
15
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
16
+ License-File: LICENSE
17
+ Summary: A fast library for rendering HTML/CSS to images
18
+ Keywords: html,css,image,render,screenshot,og-image
19
+ License: MIT
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
22
+ Project-URL: Homepage, https://github.com/blopker/dynimg
23
+ Project-URL: Repository, https://github.com/blopker/dynimg
24
+
25
+ # dynimg
26
+
27
+ A fast library and CLI for rendering HTML/CSS to images. Use from Python, Rust, or the command line. Built on [Blitz](https://github.com/DioxusLabs/blitz), a modular Rust rendering engine.
28
+
29
+ Perfect for generating dynamic images like Open Graph (OG) images, social media cards, email headers, and more.
30
+
31
+ ## Features
32
+
33
+ - **Python + Rust + CLI**: Use from Python, as a Rust library, or command-line tool
34
+ - **Multiple output formats**: PNG, WebP (lossless), and JPEG
35
+ - **High-quality rendering**: Configurable scale factor for retina displays
36
+ - **Fast**: Native Rust performance with no browser overhead
37
+ - **Secure by default**: Network and filesystem access disabled unless explicitly enabled
38
+
39
+ ## Installation
40
+
41
+ ### Python
42
+
43
+ ```bash
44
+ pip install dynimg
45
+ ```
46
+
47
+ ### Rust CLI
48
+
49
+ ```bash
50
+ cargo install dynimg
51
+ ```
52
+
53
+ ### Rust Library
54
+
55
+ ```toml
56
+ [dependencies]
57
+ dynimg = "0.1"
58
+ tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
59
+ ```
60
+
61
+ ## Library Usage
62
+
63
+ ```rust
64
+ use dynimg::{render, RenderOptions};
65
+
66
+ #[tokio::main]
67
+ async fn main() -> Result<(), dynimg::Error> {
68
+ let html = r#"
69
+ <html>
70
+ <body style="background: linear-gradient(135deg, #667eea, #764ba2);
71
+ display: flex; justify-content: center; align-items: center;
72
+ height: 630px; margin: 0;">
73
+ <h1 style="color: white; font-family: system-ui; font-size: 64px;">
74
+ Hello World
75
+ </h1>
76
+ </body>
77
+ </html>
78
+ "#;
79
+
80
+ // Render with default options (1200×auto viewport, 2x scale)
81
+ let image = render(html, RenderOptions::default()).await?;
82
+
83
+ // Save as PNG
84
+ image.save_png("output.png")?;
85
+
86
+ // Or get raw bytes
87
+ let png_bytes = image.to_png()?;
88
+ let webp_bytes = image.to_webp();
89
+ let jpeg_bytes = image.to_jpeg(90)?;
90
+
91
+ Ok(())
92
+ }
93
+ ```
94
+
95
+ ### Configuration
96
+
97
+ ```rust
98
+ use dynimg::RenderOptions;
99
+
100
+ // Using builder pattern
101
+ let options = RenderOptions::default()
102
+ .width(1200)
103
+ .height(630)
104
+ .scale(2.0)
105
+ .allow_net()
106
+ .assets_dir("./assets");
107
+
108
+ // Or struct initialization
109
+ let options = RenderOptions {
110
+ width: 1200,
111
+ height: Some(630),
112
+ scale: 2.0,
113
+ allow_net: true,
114
+ assets_dir: Some("./assets".into()),
115
+ base_url: None,
116
+ };
117
+ ```
118
+
119
+ ### Convenience function
120
+
121
+ ```rust
122
+ use dynimg::{render_to_file, RenderOptions};
123
+
124
+ // Render directly to a file (format detected from extension)
125
+ render_to_file(html, "output.png", RenderOptions::default(), 90).await?;
126
+ ```
127
+
128
+ ## CLI Usage
129
+
130
+ ### Basic Usage
131
+
132
+ Render an HTML file to PNG:
133
+
134
+ ```bash
135
+ dynimg input.html -o output.png
136
+ ```
137
+
138
+ ### Output Formats
139
+
140
+ ```bash
141
+ # PNG (lossless)
142
+ dynimg input.html -o image.png
143
+
144
+ # WebP (lossless)
145
+ dynimg input.html -o image.webp
146
+
147
+ # JPEG (lossy)
148
+ dynimg input.html -o image.jpg --quality 90
149
+ ```
150
+
151
+ ### Image Dimensions
152
+
153
+ The `--width` and `--height` options set the **viewport size** (CSS layout dimensions). The actual output image is scaled by the `--scale` factor (default: 2x for high-DPI/retina displays).
154
+
155
+ **Output image size = viewport × scale**
156
+
157
+ ```bash
158
+ # Default: 1200px viewport → 2400px output (at 2x scale)
159
+ dynimg input.html -o output.png
160
+
161
+ # OG image: 1200×630 viewport → 2400×1260 output
162
+ dynimg input.html -o output.png --width 1200 --height 630
163
+
164
+ # 1x scale for exact pixel dimensions (1200×630 output)
165
+ dynimg input.html -o output.png --width 1200 --height 630 --scale 1
166
+
167
+ # 3x scale for extra-high-DPI (3600×1890 output)
168
+ dynimg input.html -o output.png --width 1200 --height 630 --scale 3
169
+ ```
170
+
171
+ Your HTML/CSS should use the viewport dimensions (e.g., `width: 1200px`) - the scale factor handles the high-resolution rendering.
172
+
173
+ ### Reading from stdin
174
+
175
+ ```bash
176
+ echo '<html><body><h1>Hello</h1></body></html>' | dynimg - -o output.png
177
+ ```
178
+
179
+ ### Loading External Resources
180
+
181
+ By default, network and filesystem access are disabled for security. Enable them to load images, fonts, and other resources:
182
+
183
+ ```bash
184
+ # Load images/fonts from URLs
185
+ dynimg input.html -o output.png --allow-net
186
+
187
+ # Load images/fonts from a local assets directory
188
+ dynimg input.html -o output.png --assets ./assets
189
+
190
+ # Allow both
191
+ dynimg input.html -o output.png --allow-net --assets ./assets
192
+ ```
193
+
194
+ When using `--assets`, all local paths are resolved relative to the asset directory. Attempts to load files outside this directory will error:
195
+
196
+ ```html
197
+ <!-- With --assets ./assets -->
198
+ <img src="logo.png"> <!-- loads ./assets/logo.png -->
199
+ <img src="img/hero.png"> <!-- loads ./assets/img/hero.png -->
200
+ <img src="../secret.png"> <!-- ERROR: outside assets directory -->
201
+ ```
202
+
203
+ For self-contained templates, consider using inline base64 data URIs instead:
204
+
205
+ ```html
206
+ <img src="data:image/png;base64,iVBORw0KGgo...">
207
+ ```
208
+
209
+ ## CLI Reference
210
+
211
+ ```
212
+ dynimg [OPTIONS] <INPUT> -o <OUTPUT>
213
+
214
+ Arguments:
215
+ <INPUT> HTML file path or '-' for stdin
216
+
217
+ Options:
218
+ -o, --output <FILE> Output image path (format detected from extension)
219
+ -w, --width <PIXELS> Viewport width in CSS pixels [default: 1200]
220
+ -H, --height <PIXELS> Viewport height in CSS pixels [default: document height]
221
+ -s, --scale <FACTOR> Scale multiplier for output (2 = 2x resolution) [default: 2]
222
+ -q, --quality <1-100> JPEG quality [default: 90]
223
+ --allow-net Allow network access for loading remote resources
224
+ --assets <DIR> Asset directory for local resources
225
+ -v, --verbose Enable verbose logging
226
+ --help Print help
227
+ --version Print version
228
+
229
+ Options can also be set via HTML meta tags (see below). CLI flags override meta tags.
230
+
231
+ Note: Output image dimensions = viewport × scale. A 1200×630 viewport at 2x scale produces a 2400×1260 image.
232
+ ```
233
+
234
+ ## Python Usage
235
+
236
+ ```python
237
+ import dynimg
238
+
239
+ html = """
240
+ <html>
241
+ <body style="background: linear-gradient(135deg, #667eea, #764ba2);
242
+ display: flex; justify-content: center; align-items: center;
243
+ height: 630px; margin: 0;">
244
+ <h1 style="color: white; font-family: system-ui; font-size: 64px;">
245
+ Hello World
246
+ </h1>
247
+ </body>
248
+ </html>
249
+ """
250
+
251
+ # Render with default options
252
+ image = dynimg.render(html)
253
+
254
+ # Save to file
255
+ image.save("output.png")
256
+
257
+ # Or get bytes
258
+ png_bytes = image.to_png()
259
+ webp_bytes = image.to_webp()
260
+ jpeg_bytes = image.to_jpeg(quality=90)
261
+ ```
262
+
263
+ ### Configuration
264
+
265
+ ```python
266
+ import dynimg
267
+
268
+ options = dynimg.RenderOptions(
269
+ width=1200, # Viewport width (default: 1200)
270
+ height=630, # Viewport height (default: auto)
271
+ scale=2.0, # Output scale factor (default: 2.0)
272
+ allow_net=True, # Allow network requests (default: False)
273
+ assets_dir="./assets", # Local assets directory (default: None)
274
+ base_url="https://example.com", # Base URL for relative URLs (default: None)
275
+ )
276
+
277
+ image = dynimg.render(html, options)
278
+ ```
279
+
280
+ ### Direct File Output
281
+
282
+ ```python
283
+ # Render directly to a file (format detected from extension)
284
+ dynimg.render_to_file(html, "output.png")
285
+
286
+ # With options
287
+ dynimg.render_to_file(html, "output.png", options=options)
288
+
289
+ # JPEG with quality setting
290
+ dynimg.render_to_file(html, "output.jpg", quality=90)
291
+ ```
292
+
293
+ ### Image Properties
294
+
295
+ ```python
296
+ image = dynimg.render(html)
297
+ print(f"Size: {image.width}x{image.height}")
298
+ print(f"Bytes: {len(image.data)}")
299
+ ```
300
+
301
+ ## HTML Meta Tags
302
+
303
+ You can configure rendering options directly in your HTML using meta tags. CLI flags take precedence over meta tags.
304
+
305
+ ```html
306
+ <meta name="dynimg:width" content="1200"> <!-- viewport width -->
307
+ <meta name="dynimg:height" content="630"> <!-- viewport height -->
308
+ <meta name="dynimg:scale" content="2"> <!-- output multiplier -->
309
+ <meta name="dynimg:quality" content="90"> <!-- JPEG quality -->
310
+ ```
311
+
312
+ This is useful for templates that should always render at specific dimensions. Remember: the output image size is viewport × scale.
313
+
314
+ ## Example HTML Template
315
+
316
+ ```html
317
+ <!DOCTYPE html>
318
+ <html>
319
+ <head>
320
+ <meta name="dynimg:width" content="1200">
321
+ <meta name="dynimg:height" content="630">
322
+ <style>
323
+ .container {
324
+ width: 1200px;
325
+ height: 630px;
326
+ display: flex;
327
+ flex-direction: column;
328
+ justify-content: center;
329
+ align-items: center;
330
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
331
+ font-family: system-ui, sans-serif;
332
+ }
333
+ h1 {
334
+ color: white;
335
+ font-size: 64px;
336
+ margin: 0;
337
+ }
338
+ p {
339
+ color: rgba(255,255,255,0.8);
340
+ font-size: 32px;
341
+ }
342
+ </style>
343
+ </head>
344
+ <body>
345
+ <div class="container">
346
+ <h1>Hello World</h1>
347
+ <p>Welcome to my site</p>
348
+ </div>
349
+ </body>
350
+ </html>
351
+ ```
352
+
353
+ ## Supported CSS Features
354
+
355
+ dynimg uses Blitz for rendering, which supports:
356
+
357
+ - Flexbox and Grid layouts
358
+ - CSS variables
359
+ - Media queries
360
+ - Complex selectors
361
+ - Gradients and shadows
362
+ - Web fonts (via `@font-face`, requires `--allow-net` or `--assets`)
363
+ - Images (requires `--allow-net` or `--assets`, or use data URIs)
364
+
365
+ ## Performance
366
+
367
+ dynimg is designed for speed:
368
+
369
+ - No browser startup overhead
370
+ - Native Rust rendering pipeline
371
+ - Efficient image encoding
372
+
373
+ Typical rendering time: 50-200ms depending on complexity.
374
+
375
+ ## Development
376
+
377
+ ### Building
378
+
379
+ ```bash
380
+ # Build CLI
381
+ cargo build --release
382
+
383
+ # Build Python wheel
384
+ pip install maturin
385
+ maturin build --release --features python
386
+
387
+ # Install locally for development
388
+ maturin develop --features python
389
+ ```
390
+
391
+ ### Running Tests
392
+
393
+ ```bash
394
+ cargo test
395
+ cargo clippy -- -D warnings
396
+ cargo fmt -- --check
397
+ ```
398
+
399
+ ## Releasing
400
+
401
+ Releases are automated via GitHub Actions. To create a new release:
402
+
403
+ 1. Update the version in `Cargo.toml`
404
+ 2. Create and push a git tag:
405
+
406
+ ```bash
407
+ git tag v0.1.0
408
+ git push origin v0.1.0
409
+ ```
410
+
411
+ This triggers the release workflow which:
412
+ - Builds wheels for Linux (x86_64, aarch64) and macOS (x86_64, aarch64)
413
+ - Creates a GitHub Release with all artifacts
414
+ - (Optional) Publishes to PyPI (when enabled)
415
+
416
+ ## License
417
+
418
+ MIT
419
+
420
+ ## AI Warning
421
+
422
+ This is AI slop, if you want to use it, fork and make it your own!
423
+
@@ -0,0 +1,8 @@
1
+ dynimg/__init__.py,sha256=0aKwVNQaUq9AbeafWxnOLwl-ge_cOUpfUU6fFivYopA,768
2
+ dynimg/__init__.pyi,sha256=7gWC_cE0XjlRKHUiDFrOoPLKistMje89FRj6ndgVpDQ,2714
3
+ dynimg/_dynimg.abi3.so,sha256=9VyB1X7Oksj_QGXXeFlV_idlClB37td61wdXfusKUpA,17221708
4
+ dynimg/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ dynimg-0.1.9.dist-info/METADATA,sha256=06UgILDNEona3KhsXOhTomrf0-eFcTTXOPcPWCycu2A,10801
6
+ dynimg-0.1.9.dist-info/WHEEL,sha256=kXxrpAlDxFfJk3NKudODw2af-hZi5kEF-I_4llGgByk,106
7
+ dynimg-0.1.9.dist-info/licenses/LICENSE,sha256=PQMmij6bMT3ZG29qvpImWYE-PX-a2lvznHr8obLAfxc,1080
8
+ dynimg-0.1.9.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.11.5)
3
+ Root-Is-Purelib: false
4
+ Tag: cp311-abi3-macosx_10_12_x86_64
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) BO LLC, https://bollc.co
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
13
+ all 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
21
+ THE SOFTWARE.