From 972884098acb619b71a914561e410abe2e40dd98 Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Sun, 12 Oct 2025 00:51:53 +0200
Subject: [PATCH] all renderers using json
---
.../renderers/rendererHtml.py | 84 ++++---------------
1 file changed, 18 insertions(+), 66 deletions(-)
diff --git a/modules/services/serviceGeneration/renderers/rendererHtml.py b/modules/services/serviceGeneration/renderers/rendererHtml.py
index 03d3c9fd..79d9df1e 100644
--- a/modules/services/serviceGeneration/renderers/rendererHtml.py
+++ b/modules/services/serviceGeneration/renderers/rendererHtml.py
@@ -99,73 +99,25 @@ class RendererHtml(BaseRenderer):
async def _get_html_styles(self, user_prompt: str, ai_service=None) -> Dict[str, Any]:
"""Get HTML styling definitions using base template AI styling."""
- if not ai_service:
- return self._get_default_html_styles()
+ style_schema = {
+ "title": {"font_size": "2.5em", "color": "#1F4E79", "font_weight": "bold", "text_align": "center", "margin": "0 0 1em 0"},
+ "heading1": {"font_size": "2em", "color": "#2F2F2F", "font_weight": "bold", "text_align": "left", "margin": "1.5em 0 0.5em 0"},
+ "heading2": {"font_size": "1.5em", "color": "#4F4F4F", "font_weight": "bold", "text_align": "left", "margin": "1em 0 0.5em 0"},
+ "paragraph": {"font_size": "1em", "color": "#2F2F2F", "font_weight": "normal", "text_align": "left", "margin": "0 0 1em 0", "line_height": "1.6"},
+ "table": {"border": "1px solid #ddd", "border_collapse": "collapse", "width": "100%", "margin": "1em 0"},
+ "table_header": {"background": "#4F4F4F", "color": "#FFFFFF", "font_weight": "bold", "text_align": "center", "padding": "12px"},
+ "table_cell": {"background": "#FFFFFF", "color": "#2F2F2F", "font_weight": "normal", "text_align": "left", "padding": "8px", "border": "1px solid #ddd"},
+ "bullet_list": {"font_size": "1em", "color": "#2F2F2F", "margin": "0 0 1em 0", "padding_left": "20px"},
+ "code_block": {"font_family": "Courier New, monospace", "font_size": "0.9em", "color": "#2F2F2F", "background": "#F5F5F5", "padding": "1em", "border": "1px solid #ddd", "border_radius": "4px", "margin": "1em 0"},
+ "image": {"max_width": "100%", "height": "auto", "margin": "1em 0", "border_radius": "4px"},
+ "body": {"font_family": "Arial, sans-serif", "background": "#FFFFFF", "color": "#2F2F2F", "margin": "0", "padding": "20px"}
+ }
- try:
- prompt = f"""Return this exact JSON structure with your styling customizations:
-
-{{
- "title": {{"font_size": "2.5em", "color": "#1F4E79", "font_weight": "bold", "text_align": "center", "margin": "0 0 1em 0"}},
- "heading1": {{"font_size": "2em", "color": "#2F2F2F", "font_weight": "bold", "text_align": "left", "margin": "1.5em 0 0.5em 0"}},
- "heading2": {{"font_size": "1.5em", "color": "#4F4F4F", "font_weight": "bold", "text_align": "left", "margin": "1em 0 0.5em 0"}},
- "paragraph": {{"font_size": "1em", "color": "#2F2F2F", "font_weight": "normal", "text_align": "left", "margin": "0 0 1em 0", "line_height": "1.6"}},
- "table": {{"border": "1px solid #ddd", "border_collapse": "collapse", "width": "100%", "margin": "1em 0"}},
- "table_header": {{"background": "#4F4F4F", "color": "#FFFFFF", "font_weight": "bold", "text_align": "center", "padding": "12px"}},
- "table_cell": {{"background": "#FFFFFF", "color": "#2F2F2F", "font_weight": "normal", "text_align": "left", "padding": "8px", "border": "1px solid #ddd"}},
- "bullet_list": {{"font_size": "1em", "color": "#2F2F2F", "margin": "0 0 1em 0", "padding_left": "20px"}},
- "code_block": {{"font_family": "Courier New, monospace", "font_size": "0.9em", "color": "#2F2F2F", "background": "#F5F5F5", "padding": "1em", "border": "1px solid #ddd", "border_radius": "4px", "margin": "1em 0"}},
- "image": {{"max_width": "100%", "height": "auto", "margin": "1em 0", "border_radius": "4px"}},
- "body": {{"font_family": "Arial, sans-serif", "background": "#FFFFFF", "color": "#2F2F2F", "margin": "0", "padding": "20px"}}
-}}
-
-NO TEXT. NO EXPLANATIONS. NO MARKDOWN. NO WRAPPER OBJECTS. ONLY THE JSON ABOVE."""
-
- from modules.datamodels.datamodelAi import AiCallRequest, AiCallOptions, OperationType
-
- request_options = AiCallOptions()
- request_options.operationType = OperationType.GENERAL
-
- request = AiCallRequest(prompt=prompt, context="", options=request_options)
- response = await ai_service.aiObjects.call(request)
-
- import json
- import re
-
- # Clean and parse JSON
- result = response.content.strip() if response and response.content else ""
-
- # Check if result is empty
- if not result:
- self.logger.warning("AI styling returned empty response, using defaults")
- return self._get_default_html_styles()
-
- # Extract JSON from markdown code blocks
- json_match = re.search(r'```json\s*\n(.*?)\n```', result, re.DOTALL)
- if json_match:
- result = json_match.group(1).strip()
- elif result.startswith('```json'):
- result = re.sub(r'^```json\s*', '', result)
- result = re.sub(r'\s*```$', '', result)
- elif result.startswith('```'):
- result = re.sub(r'^```\s*', '', result)
- result = re.sub(r'\s*```$', '', result)
-
- # Try to parse JSON
- try:
- styles = json.loads(result)
- except json.JSONDecodeError as json_error:
- self.logger.warning(f"AI styling returned invalid JSON: {json_error}, using defaults")
- return self._get_default_html_styles()
-
- # Validate and fix contrast issues
- styles = self._validate_html_styles_contrast(styles)
-
- return styles
-
- except Exception as e:
- self.logger.warning(f"AI styling failed: {str(e)}, using defaults")
- return self._get_default_html_styles()
+ style_template = self._create_ai_style_template("html", user_prompt, style_schema)
+ styles = await self._get_ai_styles(ai_service, style_template, self._get_default_html_styles())
+
+ # Validate and fix contrast issues
+ return self._validate_html_styles_contrast(styles)
def _validate_html_styles_contrast(self, styles: Dict[str, Any]) -> Dict[str, Any]:
"""Validate and fix contrast issues in AI-generated styles."""