diff --git a/langextract/visualization.py b/langextract/visualization.py
index 725757cb..b7e7cd06 100644
--- a/langextract/visualization.py
+++ b/langextract/visualization.py
@@ -175,6 +175,8 @@ def _is_jupyter() -> bool:
.lx-gif-optimized .lx-current-highlight { text-decoration-thickness: 4px; }
""")
+_HTML_CHARSET_META = '\n'
+
def _assign_colors(extractions: list[data.Extraction]) -> dict[str, str]:
"""Assigns a background colour to each extraction class.
@@ -600,7 +602,7 @@ def visualize(
'
No valid extractions to'
' animate.
'
)
- full_html = _VISUALIZATION_CSS + empty_html
+ full_html = _HTML_CHARSET_META + _VISUALIZATION_CSS + empty_html
if HTML is not None and _is_jupyter():
return HTML(full_html)
return full_html
@@ -615,7 +617,7 @@ def visualize(
show_legend,
)
- full_html = _VISUALIZATION_CSS + visualization_html
+ full_html = _HTML_CHARSET_META + _VISUALIZATION_CSS + visualization_html
# Apply GIF optimizations if requested
if gif_optimized:
diff --git a/tests/visualization_test.py b/tests/visualization_test.py
index 43f42759..6fb48268 100644
--- a/tests/visualization_test.py
+++ b/tests/visualization_test.py
@@ -22,6 +22,7 @@
from langextract.core import data
_PALETTE = visualization._PALETTE
+_HTML_CHARSET_META = visualization._HTML_CHARSET_META
_VISUALIZATION_CSS = visualization._VISUALIZATION_CSS
@@ -134,6 +135,7 @@ def test_visualize_basic_document_renders_correctly(self):
actual_html = visualization.visualize(doc)
+ self.assertTrue(actual_html.startswith(_HTML_CHARSET_META))
# Verify expected components appear in output
for component in expected_components:
self.assertIn(component, actual_html)
@@ -149,7 +151,7 @@ def test_visualize_no_extractions_renders_text_and_empty_legend(self):
" animate."
)
css_html = _VISUALIZATION_CSS
- expected_html = css_html + body_html
+ expected_html = _HTML_CHARSET_META + css_html + body_html
actual_html = visualization.visualize(doc)