diff --git a/gslides_api/agnostic/element.py b/gslides_api/agnostic/element.py
index 163a93b..e0c7484 100644
--- a/gslides_api/agnostic/element.py
+++ b/gslides_api/agnostic/element.py
@@ -1,8 +1,9 @@
+import html
import json
import re
from abc import ABC, abstractmethod
from enum import Enum
-from typing import Any, List, Literal
+from typing import Any, List, Literal, Optional
import marko
from pydantic import BaseModel, Field, field_validator, model_validator
@@ -53,6 +54,32 @@ def to_markdown(self) -> str:
return "\n".join(lines)
+ def to_html(self, css_class: Optional[str] = None) -> str:
+ """Convert table data to an HTML
element.
+
+ Args:
+ css_class: Optional CSS class to apply to the element.
+
+ Returns:
+ HTML string with , , and elements.
+ """
+ if not self.headers:
+ return ""
+
+ cls_attr = f' class="{html.escape(css_class)}"' if css_class else ""
+ parts = [f"", ""]
+ for header in self.headers:
+ parts.append(f"| {html.escape(str(header))} | ")
+ parts.append("
")
+ for row in self.rows:
+ parts.append("")
+ for i in range(len(self.headers)):
+ cell = str(row[i]) if i < len(row) else ""
+ parts.append(f"| {html.escape(cell)} | ")
+ parts.append("
")
+ parts.append("
")
+ return "".join(parts)
+
def to_dataframe(self):
"""Convert table data to pandas DataFrame.
diff --git a/pyproject.toml b/pyproject.toml
index 4d4b615..625cca7 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "gslides-api"
-version = "0.3.5"
+version = "0.3.6"
description = "A Python library for working with Google Slides API using Pydantic domain objects"
authors = ["motley.ai "]
license = "MIT"
diff --git a/tests/test_table_data_to_html.py b/tests/test_table_data_to_html.py
new file mode 100644
index 0000000..727dc10
--- /dev/null
+++ b/tests/test_table_data_to_html.py
@@ -0,0 +1,69 @@
+"""Tests for TableData.to_html() method."""
+
+import pytest
+
+from gslides_api.agnostic.element import TableData
+
+
+class TestTableDataToHtml:
+ def test_basic_table(self):
+ td = TableData(headers=["Name", "Value"], rows=[["Alice", "100"], ["Bob", "200"]])
+ result = td.to_html()
+ assert "" in result
+ assert "" in result
+ assert "" in result
+ assert "| Name | " in result
+ assert "Value | " in result
+ assert "Alice | " in result
+ assert "100 | " in result
+ assert "Bob | " in result
+ assert "200 | " in result
+
+ def test_with_css_class(self):
+ td = TableData(headers=["A"], rows=[["1"]])
+ result = td.to_html(css_class="dtbl")
+ assert '' in result
+
+ def test_without_css_class(self):
+ td = TableData(headers=["A"], rows=[["1"]])
+ result = td.to_html()
+ assert "" in result
+ assert "class=" not in result
+
+ def test_empty_headers(self):
+ td = TableData(headers=[], rows=[])
+ assert td.to_html() == ""
+
+ def test_html_escaping(self):
+ td = TableData(
+ headers=["