Skip to content

Commit 3046e13

Browse files
committed
Made initial changes towards handling list sanity
1 parent 5ffcce9 commit 3046e13

File tree

4 files changed

+133
-54
lines changed

4 files changed

+133
-54
lines changed

mxtoai/agents/email_agent.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,6 @@ def _create_task_template(
378378
output_template,
379379
RESPONSE_GUIDELINES,
380380
MARKDOWN_STYLE_GUIDE,
381-
LIST_FORMATTING_REQUIREMENTS,
382381
]
383382
return "\n\n".join(filter(None, sections))
384383

mxtoai/prompts/base_prompts.py

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,6 @@
2222
- DO NOT add any signature - it will be added automatically
2323
"""
2424

25-
# Formatting requirements for HTML conversion
26-
LIST_FORMATTING_REQUIREMENTS = """
27-
NESTED LIST OUTPUT FORMAT GUIDELINES (for Markdown to HTML conversion):
28-
29-
1. Always begin with a **numbered list** (use `1.`).
30-
2. **Alternate between numbered and bullet lists** at each level of nesting:
31-
- Level 1: `1.`, `2.`, `3.` (numbered)
32-
1. Level 2: `-` (bullet)
33-
- Level 3: `1.`, `2.`, `3.` (numbered)
34-
1. Level 4: `-` (bullet)
35-
- And so on...
36-
3. Use **blank lines** between paragraphs and between different list levels.
37-
38-
Example:
39-
40-
1. Main point
41-
- Sub-point
42-
1. Sub-sub-point
43-
- Sub-sub-sub-point
44-
45-
All list sections **must follow this structure exactly**. Improper nesting or use of list styles will break the HTML conversion.
46-
"""
47-
4825
# Research guidelines
4926
RESEARCH_GUIDELINES = {
5027
"mandatory": """

mxtoai/scripts/report_formatter.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ def _to_html(self, markdown_content: str, theme: str = "default") -> str:
245245
from markdown.extensions.tables import TableExtension
246246
from markdown.extensions.toc import TocExtension
247247

248+
processed_content = self._preprocess_lists(markdown_content)
249+
248250
# Configure extensions with specific settings
249251
extensions = [
250252
TableExtension(), # Support for tables
@@ -266,6 +268,8 @@ def _to_html(self, markdown_content: str, theme: str = "default") -> str:
266268
output_format="html5", # Use html5 for better compatibility
267269
)
268270

271+
html_content = self._postprocess_html_lists(html_content)
272+
269273
if self.template_env:
270274
try:
271275
theme_settings = self.themes.get(theme, self.themes["default"])
@@ -283,6 +287,64 @@ def _to_html(self, markdown_content: str, theme: str = "default") -> str:
283287
logger.error("Markdown package not available - this should never happen as it's a required dependency")
284288
raise # We should always have markdown package available
285289

290+
def _preprocess_lists(self, markdown: str) -> str:
291+
"""
292+
Pre-process markdown to ensure consistent list formatting.
293+
294+
Args:
295+
markdown: Raw markdown content
296+
297+
Returns:
298+
Processed markdown with consistent list formatting
299+
"""
300+
lines = markdown.split('\n')
301+
processed_lines = []
302+
303+
for i, line in enumerate(lines):
304+
# Ensure proper spacing before lists
305+
if (line.strip().startswith(('- ', '* ', '+ ')) or
306+
re.match(r'^\s*\d+\.\s', line.strip())):
307+
308+
# Check if previous line exists and isn't empty or another list item
309+
if (i > 0 and
310+
processed_lines and
311+
processed_lines[-1].strip() and
312+
not processed_lines[-1].strip().startswith(('- ', '* ', '+ ')) and
313+
not re.match(r'^\s*\d+\.\s', processed_lines[-1].strip())):
314+
315+
# Add empty line before list if there isn't one
316+
processed_lines.append('')
317+
318+
processed_lines.append(line)
319+
320+
return '\n'.join(processed_lines)
321+
322+
def _postprocess_html_lists(self, html: str) -> str:
323+
"""
324+
Post-process HTML to ensure consistent list structure.
325+
326+
Args:
327+
html: HTML content with lists
328+
329+
Returns:
330+
HTML with consistent list formatting
331+
"""
332+
import re
333+
334+
# Ensure proper spacing around lists
335+
# Add space before lists that immediately follow paragraphs
336+
html = re.sub(r'</p>\s*<ul>', '</p>\n<ul>', html)
337+
html = re.sub(r'</p>\s*<ol>', '</p>\n<ol>', html)
338+
339+
# Add space after lists that are followed by paragraphs
340+
html = re.sub(r'</ul>\s*<p>', '</ul>\n<p>', html)
341+
html = re.sub(r'</ol>\s*<p>', '</ol>\n<p>', html)
342+
343+
# Clean up excessive whitespace
344+
html = re.sub(r'\n\s*\n\s*\n', '\n\n', html)
345+
346+
return html
347+
286348
def _basic_html_render(self, html_content: str) -> str:
287349
"""
288350
Fallback HTML rendering when templates aren't available.

mxtoai/scripts/templates/email_template.html

Lines changed: 71 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -76,55 +76,82 @@
7676
text-decoration: underline;
7777
}
7878
79+
/* FIXED LIST STYLES - Consistent indentation and spacing */
7980
ul, ol {
80-
margin: 0 0 1rem 0.5rem;
81-
padding-left: 2rem;
81+
margin: 1rem 0;
82+
padding: 0;
8283
list-style-position: outside;
8384
}
8485
85-
/* Base list styles */
86-
ul { list-style-type: disc; }
87-
ol { list-style-type: decimal; }
86+
/* Top-level lists */
87+
ul {
88+
list-style-type: disc;
89+
margin-left: 2rem;
90+
}
91+
92+
ol {
93+
list-style-type: decimal;
94+
margin-left: 2rem;
95+
}
8896
89-
ul ul,
90-
ol ul {
91-
list-style-type: circle;
97+
/* Nested lists - consistent indentation */
98+
ul ul {
99+
list-style-type: circle;
92100
margin: 0.5rem 0;
93-
padding-left: 3rem;
101+
margin-left: 1.5rem;
94102
}
95103
96-
ul ul ul,
97-
ol ul ul {
98-
list-style-type: square;
104+
ol ol {
105+
list-style-type: lower-alpha;
106+
margin: 0.5rem 0;
107+
margin-left: 1.5rem;
99108
}
100109
101-
ol ol,
102-
ul ol {
103-
list-style-type: lower-alpha;
110+
ul ol {
111+
list-style-type: lower-alpha;
104112
margin: 0.5rem 0;
105-
padding-left: 4rem;
113+
margin-left: 1.5rem;
106114
}
107115
108-
ol ol ol,
109-
ul ol ol {
110-
list-style-type: lower-roman;
116+
ol ul {
117+
list-style-type: circle;
118+
margin: 0.5rem 0;
119+
margin-left: 1.5rem;
120+
}
121+
122+
/* Third level nesting */
123+
ul ul ul,
124+
ol ol ol,
125+
ul ol ol,
126+
ol ul ul {
127+
list-style-type: square;
128+
margin-left: 1.5rem;
111129
}
112130
131+
/* List items */
113132
li {
114-
margin: 0.5rem 0.5rem;
115-
line-height: 1.5;
116-
display: list-item;
117-
position: relative;
133+
margin: 0.5rem 0;
134+
line-height: 1.6;
135+
padding-left: 0.25rem;
118136
}
119137
138+
/* Handle paragraphs within list items */
120139
li p {
121-
margin: 0.5rem 0;
122-
display: inline-block;
140+
margin: 0.25rem 0 0.5rem 0;
123141
}
124142
125-
li > ul,
126-
li > ol {
127-
margin-bottom: 0.5rem;
143+
/* Ensure lists after paragraphs have proper spacing */
144+
p + ul,
145+
p + ol {
146+
margin-top: 0.5rem;
147+
}
148+
149+
/* Ensure consistent spacing between different elements */
150+
ul + p,
151+
ol + p,
152+
ul + h1, ul + h2, ul + h3, ul + h4, ul + h5, ul + h6,
153+
ol + h1, ol + h2, ol + h3, ol + h4, ol + h5, ol + h6 {
154+
margin-top: 1rem;
128155
}
129156
130157
code {
@@ -230,7 +257,7 @@
230257

231258
.toc ul {
232259
list-style-type: none;
233-
padding-left: 1rem;
260+
margin-left: 1rem;
234261
}
235262

236263
.toc li {
@@ -306,6 +333,11 @@
306333
h2, h3 {
307334
page-break-after: avoid;
308335
}
336+
337+
/* Print-specific list adjustments */
338+
ul, ol {
339+
margin-left: 1.5rem;
340+
}
309341
}
310342

311343
/* Responsive adjustments */
@@ -325,6 +357,15 @@
325357
pre {
326358
padding: 0.75rem;
327359
}
360+
361+
/* Mobile list adjustments */
362+
ul, ol {
363+
margin-left: 1.5rem;
364+
}
365+
366+
ul ul, ol ol, ul ol, ol ul {
367+
margin-left: 1.2rem;
368+
}
328369
}
329370
</style>
330371
</head>
@@ -333,4 +374,4 @@
333374
{{ content|safe }}
334375
</div>
335376
</body>
336-
</html>
377+
</html>

0 commit comments

Comments
 (0)