html2pic 0.1.1__py3-none-any.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.
@@ -0,0 +1,192 @@
1
+ """
2
+ Warning system for html2pic - provides detailed debugging information
3
+ """
4
+
5
+ import warnings
6
+ from typing import List, Dict, Any, Optional
7
+ from enum import Enum
8
+
9
+ class WarningCategory(Enum):
10
+ """Categories of warnings for better organization"""
11
+ HTML_PARSING = "html_parsing"
12
+ CSS_PARSING = "css_parsing"
13
+ STYLE_APPLICATION = "style_application"
14
+ TRANSLATION = "translation"
15
+ RENDERING = "rendering"
16
+ UNSUPPORTED_FEATURE = "unsupported_feature"
17
+
18
+ class Html2PicWarning(UserWarning):
19
+ """Base warning class for html2pic"""
20
+ pass
21
+
22
+ class UnsupportedFeatureWarning(Html2PicWarning):
23
+ """Warning for unsupported HTML/CSS features"""
24
+ pass
25
+
26
+ class StyleApplicationWarning(Html2PicWarning):
27
+ """Warning for style application issues"""
28
+ pass
29
+
30
+ class TranslationWarning(Html2PicWarning):
31
+ """Warning for DOM to PicTex translation issues"""
32
+ pass
33
+
34
+ class ParsingWarning(Html2PicWarning):
35
+ """Warning for HTML/CSS parsing issues"""
36
+ pass
37
+
38
+ class WarningCollector:
39
+ """
40
+ Collects and manages warnings during the html2pic conversion process.
41
+
42
+ This provides a centralized way to track all issues that occur during
43
+ HTML/CSS parsing, style application, and rendering.
44
+ """
45
+
46
+ def __init__(self):
47
+ self.warnings: List[Dict[str, Any]] = []
48
+ self._enabled = True
49
+
50
+ def warn(self, message: str, category: WarningCategory, details: Optional[Dict[str, Any]] = None,
51
+ warning_class: type = Html2PicWarning):
52
+ """
53
+ Add a warning with detailed context information.
54
+
55
+ Args:
56
+ message: Human-readable warning message
57
+ category: Category of the warning
58
+ details: Additional context (element info, CSS rule, etc.)
59
+ warning_class: Specific warning class to use
60
+ """
61
+ if not self._enabled:
62
+ return
63
+
64
+ warning_info = {
65
+ 'message': message,
66
+ 'category': category.value,
67
+ 'details': details or {},
68
+ 'warning_class': warning_class.__name__
69
+ }
70
+
71
+ self.warnings.append(warning_info)
72
+
73
+ # Also emit a standard Python warning
74
+ warnings.warn(f"[{category.value.upper()}] {message}", warning_class, stacklevel=3)
75
+
76
+ def warn_unsupported_html_tag(self, tag_name: str, context: str = ""):
77
+ """Warn about unsupported HTML tags"""
78
+ self.warn(
79
+ f"HTML tag '<{tag_name}>' is not supported and was skipped",
80
+ WarningCategory.HTML_PARSING,
81
+ {'tag': tag_name, 'context': context},
82
+ UnsupportedFeatureWarning
83
+ )
84
+
85
+ def warn_unsupported_css_property(self, property_name: str, value: str, selector: str = ""):
86
+ """Warn about unsupported CSS properties"""
87
+ self.warn(
88
+ f"CSS property '{property_name}: {value}' is not supported",
89
+ WarningCategory.CSS_PARSING,
90
+ {'property': property_name, 'value': value, 'selector': selector},
91
+ UnsupportedFeatureWarning
92
+ )
93
+
94
+ def warn_css_selector_ignored(self, selector: str, reason: str):
95
+ """Warn about CSS selectors that were ignored"""
96
+ self.warn(
97
+ f"CSS selector '{selector}' was ignored: {reason}",
98
+ WarningCategory.CSS_PARSING,
99
+ {'selector': selector, 'reason': reason},
100
+ ParsingWarning
101
+ )
102
+
103
+ def warn_style_not_applied(self, property_name: str, value: str, element_info: str, reason: str):
104
+ """Warn about styles that couldn't be applied"""
105
+ self.warn(
106
+ f"Style '{property_name}: {value}' could not be applied to {element_info}: {reason}",
107
+ WarningCategory.STYLE_APPLICATION,
108
+ {'property': property_name, 'value': value, 'element': element_info, 'reason': reason},
109
+ StyleApplicationWarning
110
+ )
111
+
112
+ def warn_element_skipped(self, element_info: str, reason: str):
113
+ """Warn about elements that were skipped during translation"""
114
+ self.warn(
115
+ f"Element {element_info} was skipped: {reason}",
116
+ WarningCategory.TRANSLATION,
117
+ {'element': element_info, 'reason': reason},
118
+ TranslationWarning
119
+ )
120
+
121
+ def warn_color_fallback(self, original_color: str, fallback_color: str, reason: str):
122
+ """Warn about color values that fell back to defaults"""
123
+ self.warn(
124
+ f"Color '{original_color}' fell back to '{fallback_color}': {reason}",
125
+ WarningCategory.STYLE_APPLICATION,
126
+ {'original': original_color, 'fallback': fallback_color, 'reason': reason},
127
+ StyleApplicationWarning
128
+ )
129
+
130
+ def get_warnings(self, category: Optional[WarningCategory] = None) -> List[Dict[str, Any]]:
131
+ """Get all warnings, optionally filtered by category"""
132
+ if category is None:
133
+ return self.warnings.copy()
134
+ return [w for w in self.warnings if w['category'] == category.value]
135
+
136
+ def get_summary(self) -> Dict[str, Any]:
137
+ """Get a summary of all warnings"""
138
+ by_category = {}
139
+ for warning in self.warnings:
140
+ cat = warning['category']
141
+ if cat not in by_category:
142
+ by_category[cat] = []
143
+ by_category[cat].append(warning)
144
+
145
+ return {
146
+ 'total_warnings': len(self.warnings),
147
+ 'by_category': {cat: len(warnings) for cat, warnings in by_category.items()},
148
+ 'categories': by_category
149
+ }
150
+
151
+ def print_summary(self):
152
+ """Print a formatted summary of warnings"""
153
+ if not self.warnings:
154
+ print("✅ No warnings - conversion completed successfully!")
155
+ return
156
+
157
+ summary = self.get_summary()
158
+ print(f"\n⚠️ Conversion completed with {summary['total_warnings']} warnings:")
159
+
160
+ for category, count in summary['by_category'].items():
161
+ print(f" {category.replace('_', ' ').title()}: {count}")
162
+
163
+ print("\nDetailed warnings:")
164
+ for i, warning in enumerate(self.warnings, 1):
165
+ print(f" {i}. [{warning['category'].upper()}] {warning['message']}")
166
+ if warning['details']:
167
+ for key, value in warning['details'].items():
168
+ print(f" {key}: {value}")
169
+
170
+ def clear(self):
171
+ """Clear all collected warnings"""
172
+ self.warnings.clear()
173
+
174
+ def enable(self):
175
+ """Enable warning collection"""
176
+ self._enabled = True
177
+
178
+ def disable(self):
179
+ """Disable warning collection"""
180
+ self._enabled = False
181
+
182
+ # Global warning collector instance
183
+ _global_collector = WarningCollector()
184
+
185
+ def get_warning_collector() -> WarningCollector:
186
+ """Get the global warning collector instance"""
187
+ return _global_collector
188
+
189
+ def reset_warnings():
190
+ """Reset the global warning collector"""
191
+ global _global_collector
192
+ _global_collector.clear()
@@ -0,0 +1,347 @@
1
+ Metadata-Version: 2.4
2
+ Name: html2pic
3
+ Version: 0.1.1
4
+ Summary: Convert HTML + CSS to images without a browser
5
+ Project-URL: Homepage, https://github.com/francozanardi/html2pic
6
+ Project-URL: Repository, https://github.com/francozanardi/html2pic.git
7
+ Project-URL: Bug Tracker, https://github.com/francozanardi/html2pic/issues
8
+ Project-URL: Documentation, https://github.com/francozanardi/html2pic/blob/main/README.md
9
+ Project-URL: Examples, https://github.com/francozanardi/html2pic/tree/main/examples
10
+ Author-email: Franco Zanardi <francozanardi97@gmail.com>
11
+ License-Expression: MIT
12
+ Keywords: conversion,css,html,image,rendering
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
24
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
+ Classifier: Topic :: Text Processing :: Markup :: HTML
26
+ Requires-Python: >=3.8
27
+ Requires-Dist: beautifulsoup4>=4.9.0
28
+ Requires-Dist: pictex
29
+ Requires-Dist: tinycss2>=1.1.0
30
+ Provides-Extra: examples
31
+ Requires-Dist: pillow>=8.0.0; extra == 'examples'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # html2pic
35
+
36
+ **Convert HTML + CSS to beautiful images using PicTex**
37
+
38
+ `html2pic` is a Python library that translates a subset of HTML and CSS to high-quality images without requiring a browser engine. Built on top of [PicTex](https://github.com/francozanardi/pictex), it provides a powerful and intuitive way to generate images from web markup.
39
+
40
+ ## ⚠️ **Experimental Software Notice**
41
+
42
+ **This is experimental software developed primarily using AI assistance (Claude Code).** While functional, it should be used with caution in production environments. Key considerations:
43
+
44
+ - **Rapid Development**: Most of the codebase was generated and refined through AI-assisted programming
45
+ - **Limited Testing**: Extensive testing in diverse environments is still ongoing
46
+ - **Active Development**: APIs and behavior may change significantly in future versions
47
+ - **Community Feedback Welcome**: Please report issues and suggest improvements via GitHub
48
+
49
+ Use this library for prototyping, experimentation, and non-critical applications. For production use, thorough testing is recommended.
50
+
51
+ ## 🚀 Key Features
52
+
53
+ - **No Browser Required**: Pure Python implementation using PicTex as the rendering engine
54
+ - **Flexbox Support**: Modern CSS layout with `display: flex`, `justify-content`, `align-items`, etc.
55
+ - **Rich Typography**: Font families, sizes, weights, colors, and text decorations
56
+ - **Box Model**: Complete support for padding, margins, borders, and border-radius
57
+ - **Responsive Sizing**: Supports px, em, rem, % units and flexible sizing modes
58
+ - **High Quality Output**: Vector (SVG) and raster (PNG, JPG) output formats
59
+ - **Simple API**: Clean, intuitive interface inspired by modern web development
60
+
61
+ ## 📦 Installation
62
+
63
+ ```bash
64
+ pip install html2pic
65
+ ```
66
+
67
+ ## 🎯 Quick Start
68
+
69
+ ```python
70
+ from html2pic import Html2Pic
71
+
72
+ # Your HTML content
73
+ html = '''
74
+ <div class="card">
75
+ <h1>Hello, World!</h1>
76
+ <p class="subtitle">Generated with html2pic</p>
77
+ </div>
78
+ '''
79
+
80
+ # Your CSS styles
81
+ css = '''
82
+ .card {
83
+ display: flex;
84
+ flex-direction: column;
85
+ align-items: center;
86
+ padding: 30px;
87
+ background-color: #f0f8ff;
88
+ border-radius: 15px;
89
+ width: 300px;
90
+ }
91
+
92
+ h1 {
93
+ color: #2c3e50;
94
+ font-size: 28px;
95
+ margin: 0 0 10px 0;
96
+ }
97
+
98
+ .subtitle {
99
+ color: #7f8c8d;
100
+ font-size: 16px;
101
+ margin: 0;
102
+ }
103
+ '''
104
+
105
+ # Create and render
106
+ renderer = Html2Pic(html, css)
107
+ image = renderer.render()
108
+ image.save("output.png")
109
+ ```
110
+
111
+ ## 🏗️ Architecture
112
+
113
+ html2pic works by translating HTML + CSS concepts to PicTex builders:
114
+
115
+ 1. **HTML Parser**: Uses BeautifulSoup to create a DOM tree
116
+ 2. **CSS Parser**: Uses tinycss2 to extract style rules
117
+ 3. **Style Engine**: Applies CSS cascade, specificity, and inheritance
118
+ 4. **Translator**: Maps styled DOM nodes to PicTex builders (Canvas, Row, Column, Text, Image)
119
+ 5. **Renderer**: Uses PicTex to generate the final image
120
+
121
+ ## 📋 Supported HTML/CSS Features
122
+
123
+ ### HTML Elements
124
+ - `<div>`, `<section>`, `<article>` → Layout containers
125
+ - `<h1>`-`<h6>`, `<p>`, `<span>` → Text elements
126
+ - `<img>` → Image elements
127
+
128
+ ### CSS Layout
129
+ - `display: flex` with `flex-direction: row|column`
130
+ - `justify-content`: `flex-start`, `center`, `flex-end`, `space-between`, `space-around`, `space-evenly`
131
+ - `align-items`: `flex-start`, `center`, `flex-end`, `stretch`
132
+ - `gap` for spacing between flex items
133
+
134
+ ### CSS Box Model
135
+ - `width`, `height` (px, %, auto, fit-content, fill-available)
136
+ - `padding`, `margin` (shorthand and individual sides)
137
+ - `border` with width, style (solid, dashed, dotted), and color
138
+ - `border-radius` (px and %)
139
+ - `background-color` (solid colors and linear gradients)
140
+ - `background-image` (url() and linear-gradient())
141
+ - `background-size` (cover, contain, tile for images)
142
+ - `box-shadow` (offset-x, offset-y, blur-radius, color)
143
+
144
+ ### CSS Typography
145
+ - `font-family`, `font-size`, `font-weight`, `font-style`
146
+ - `color`, `text-align`, `line-height`
147
+ - `text-decoration` (underline, line-through)
148
+ - `text-shadow` (offset-x, offset-y, blur-radius, color)
149
+
150
+ #### Font Loading
151
+ html2pic supports loading fonts from the system or custom font files:
152
+
153
+ ```css
154
+ /* System font */
155
+ font-family: "Arial", sans-serif;
156
+
157
+ /* Custom font file (provide absolute path) */
158
+ font-family: "/path/to/custom-font.ttf";
159
+
160
+ /* Multiple fallbacks */
161
+ font-family: "Custom Font", "Arial", sans-serif;
162
+ ```
163
+
164
+ **Note**: When using custom fonts, provide the full path to the font file (.ttf, .otf). If the font cannot be loaded, it will fall back to system defaults.
165
+
166
+ #### Linear Gradients
167
+ html2pic supports CSS linear-gradient syntax for backgrounds:
168
+
169
+ ```css
170
+ /* Angle-based gradients */
171
+ background-image: linear-gradient(135deg, #667eea, #764ba2);
172
+
173
+ /* Direction keywords */
174
+ background-image: linear-gradient(to right, red, blue);
175
+
176
+ /* Color stops with percentages */
177
+ background-image: linear-gradient(90deg, #ff0000 0%, #00ff00 50%, #0000ff 100%);
178
+
179
+ /* Multiple colors */
180
+ background-image: linear-gradient(45deg, yellow, orange, red, purple);
181
+ ```
182
+
183
+ **Supported features:**
184
+ - Angle directions (0deg, 45deg, 135deg, etc.)
185
+ - Keyword directions (to right, to bottom, to top left, etc.)
186
+ - Color stops with percentages
187
+ - Multiple colors with automatic distribution
188
+ - All CSS color formats (hex, rgb, rgba, named colors)
189
+
190
+ **Limitations**: Only linear gradients are supported. Radial and conic gradients are not yet implemented.
191
+
192
+ ### CSS Positioning
193
+ - `position: absolute` with `left` and `top` properties (px, %, em, rem)
194
+ - **Limitation**: Only `left` and `top` are supported, not `right` or `bottom`
195
+
196
+ ### CSS Selectors
197
+ - Tag selectors: `div`, `p`, `h1`
198
+ - Class selectors: `.my-class`
199
+ - ID selectors: `#my-id`
200
+ - Universal selector: `*`
201
+
202
+ ## 📝 Examples
203
+
204
+ Explore the `examples/` folder for complete runnable examples with generated output images.
205
+
206
+ ### Quick Start Example
207
+ Basic card layout demonstrating core html2pic functionality:
208
+
209
+ ```python
210
+ from html2pic import Html2Pic
211
+
212
+ html = '''
213
+ <div class="card">
214
+ <h1>Hello, World!</h1>
215
+ <p class="subtitle">Generated with html2pic</p>
216
+ </div>
217
+ '''
218
+
219
+ css = '''
220
+ .card {
221
+ display: flex;
222
+ flex-direction: column;
223
+ align-items: center;
224
+ padding: 30px;
225
+ background-color: #f0f8ff;
226
+ border-radius: 15px;
227
+ width: 300px;
228
+ }
229
+
230
+ h1 {
231
+ color: #2c3e50;
232
+ font-size: 28px;
233
+ margin: 0 0 10px 0;
234
+ }
235
+
236
+ .subtitle {
237
+ color: #7f8c8d;
238
+ font-size: 16px;
239
+ margin: 0;
240
+ }
241
+ '''
242
+
243
+ renderer = Html2Pic(html, css)
244
+ image = renderer.render()
245
+ image.save("output.png")
246
+ ```
247
+
248
+ ![Quick Start Result](examples/01_quick_start_output.png)
249
+
250
+ ### Flexbox Card Layout
251
+ Social media style user card with horizontal layout:
252
+
253
+ ```python
254
+ html = '''
255
+ <div class="user-card">
256
+ <div class="avatar"></div>
257
+ <div class="user-info">
258
+ <h2>Alex Doe</h2>
259
+ <p>@alexdoe</p>
260
+ </div>
261
+ </div>
262
+ '''
263
+
264
+ css = '''
265
+ .user-card {
266
+ display: flex;
267
+ align-items: center;
268
+ gap: 15px;
269
+ padding: 20px;
270
+ background-color: white;
271
+ border-radius: 12px;
272
+ border: 1px solid #e1e8ed;
273
+ }
274
+
275
+ .avatar {
276
+ width: 60px;
277
+ height: 60px;
278
+ background-color: #1da1f2;
279
+ border-radius: 50%;
280
+ }
281
+
282
+ .user-info h2 {
283
+ margin: 0 0 4px 0;
284
+ font-size: 18px;
285
+ color: #14171a;
286
+ }
287
+
288
+ .user-info p {
289
+ margin: 0;
290
+ color: #657786;
291
+ font-size: 14px;
292
+ }
293
+ '''
294
+ ```
295
+
296
+ ![Flexbox Card Result](examples/02_flexbox_card_output.png)
297
+
298
+ ### Advanced Visual Effects
299
+ Shadows, positioning, and advanced styling features:
300
+
301
+ ![Shadows and Effects Result](examples/04_shadows_and_effects_output.png)
302
+
303
+ ### Background Images
304
+ Background image support with different sizing modes:
305
+
306
+ ![Background Images Result](examples/05_background_images_output.png)
307
+
308
+ **Complete examples** with full source code are available in the [`examples/`](examples/) directory.
309
+
310
+ ## 🔧 API Reference
311
+
312
+ ### Html2Pic Class
313
+
314
+ ```python
315
+ Html2Pic(html: str, css: str = "", base_font_size: int = 16)
316
+ ```
317
+
318
+ **Methods:**
319
+ - `render(crop_mode=CropMode.SMART) -> BitmapImage`: Render to raster image
320
+ - `render_as_svg(embed_font=True) -> VectorImage`: Render to SVG
321
+ - `debug_info() -> dict`: Get debugging information about parsing and styling
322
+
323
+ ### Output Objects
324
+
325
+ The rendered images are PicTex `BitmapImage` or `VectorImage` objects with methods like:
326
+ - `save(filename)`: Save to file
327
+ - `to_numpy()`: Convert to NumPy array
328
+ - `to_pillow()`: Convert to PIL Image
329
+ - `show()`: Display the image
330
+
331
+ ## 🚧 Current Limitations
332
+
333
+ This is an early version focusing on core functionality. A lot of features are not yet supported.
334
+
335
+ ## 🤝 Contributing
336
+
337
+ Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
338
+
339
+ ## 📄 License
340
+
341
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
342
+
343
+ ## 🙏 Acknowledgments
344
+
345
+ - Built on top of [PicTex](https://github.com/your-pictex-repo) for high-quality rendering
346
+ - Uses [BeautifulSoup](https://www.crummy.com/software/BeautifulSoup/) for HTML parsing
347
+ - Uses [tinycss2](https://github.com/Kozea/tinycss2) for CSS parsing
@@ -0,0 +1,12 @@
1
+ html2pic/__init__.py,sha256=E1yV95IM2tTDTNgJO97vWxy5a_Aml_TsJrJd4yUW0bA,1169
2
+ html2pic/core.py,sha256=BUmxV6L3MmCMFs2BMVYWyXWyaPe4OTg0pcbzG2Cy62Y,6517
3
+ html2pic/css_parser.py,sha256=nJoKRCaopGGAazH5w-MGq6Z5Dm0ohKpAaWH-xo6X5LU,11355
4
+ html2pic/exceptions.py,sha256=UCTkyOaCQ13V5Rziz_aKN1XyLhyV5j3jS7_x94F46Iw,455
5
+ html2pic/html_parser.py,sha256=zmZxVj4_2wPEDl8JNfqGrEFxL61Hp0T3m4HZXnLTVJA,6349
6
+ html2pic/models.py,sha256=QPrLvN-lFxWS8D3uS_R3J2KLVJDK6mhwb55Idhxl9gQ,5492
7
+ html2pic/style_engine.py,sha256=HgqX6es1cUUWFTC-LXfZJPKGhUVyQ6MrLDjlXO43cps,17630
8
+ html2pic/translator.py,sha256=IM1YtiyOY878pvYhvfxkmYeq3eI87YLsgz1kEBGZp80,38195
9
+ html2pic/warnings_system.py,sha256=3nxjmrrjUnmxk_7GgMVIUCCQJDgzS9Vr-bENfSigUPY,7158
10
+ html2pic-0.1.1.dist-info/METADATA,sha256=eApxktFCOl5YiG-i_8dXyL8p9M_EBlLftkZqsC9MZAA,10491
11
+ html2pic-0.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
+ html2pic-0.1.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any