Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions great_tables/_formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@
TypeVar,
Union,
cast,
overload,
overload
)

import babel
import faicons
from babel.dates import format_date, format_datetime, format_time
from typing_extensions import TypeAlias

from ._gt_data import FormatFn, FormatFns, FormatInfo, FormatterSkipElement, GTData, PFrameData
from ._gt_data import (FormatFn, FormatFns, FormatInfo, FormatterSkipElement,
GTData, PFrameData)
from ._helpers import px
from ._locale import (
_get_currencies_data,
Expand All @@ -44,7 +45,7 @@
is_series,
to_list,
)
from ._text import _md_html, escape_pattern_str_latex
from ._text import _md_html, _md_latex, escape_pattern_str_latex
from ._utils import _str_detect, _str_replace, is_valid_http_schema
from ._utils_nanoplots import _generate_nanoplot

Expand Down Expand Up @@ -2668,7 +2669,7 @@ def fmt_markdown_context(
context: str,
) -> str:
if context == "latex":
raise NotImplementedError("fmt_markdown() is not supported in LaTeX.")
return _md_latex(x)

if is_na(data._tbl_data, x):
return x
Expand Down
43 changes: 32 additions & 11 deletions great_tables/_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
from typing import Callable

import commonmark
from docutils.core import publish_parts
from markdownify import markdownify as mdify
from myst_parser.docutils_ import Parser


class BaseText:
Expand Down Expand Up @@ -48,13 +51,7 @@ def to_html(self) -> str:
return self.text

def to_latex(self) -> str:
from ._utils_render_latex import _not_implemented

_not_implemented(
"Using the `html()` helper function won't convert HTML to LaTeX. Escaping HTML string instead."
)

return _latex_escape(self.text)
return _html_latex(self.text)


def _md_html(x: str) -> str:
Expand All @@ -63,10 +60,34 @@ def _md_html(x: str) -> str:


def _md_latex(x: str) -> str:
# TODO: Implement commonmark to LaTeX conversion (through a different library as
# commonmark-py does not support it)
raise NotImplementedError("Markdown to LaTeX conversion is not supported yet")

# USE REGEX TO CONVERT <sub> AND <sup> TO MYST MARKDOWN
input = re.sub(r'<sub>(.*?)</sub>', r'{sub}`\1`', x)
input = re.sub(r'<sup>(.*?)</sup>', r'{sup}`\1`', input)

# Use Myst-Parser to convert Markdown to LaTeX
raw_output = publish_parts(
source=input,
writer_name="latex",
settings_overrides={
"myst_enable_extensions": ['strikethrough'],
"embed_stylesheet": False,
"legacy_column_widths": True,
"use_latex_citations": False,
},
parser=Parser(),
)

output = raw_output['body'].strip()

return output


def _html_latex(x: str) -> str:
# Turn HTML to Markdown first
input = mdify(x, strip=['br'], sub_symbol="<sub>", sup_symbol="<sup>")

# Then render Markdown to LaTeX
return _md_latex(input)

def _process_text(x: str | BaseText | None, context: str = "html") -> str:
if x is None:
Expand Down
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ dependencies = [
"importlib-metadata",
"typing_extensions>=3.10.0.0",
"Babel>=2.13.1",
"importlib-resources"
"importlib-resources",
"markdownify>=1.2.2",
"myst_parser>=4.0.1"
]
requires-python = ">=3.9"

Expand Down
15 changes: 8 additions & 7 deletions tests/test_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
_latex_escape,
escape_pattern_str_latex,
_process_text,
_md_latex,
)


Expand All @@ -30,7 +31,7 @@ def test_md_class():

def test_html_class():
assert Html("<strong>text</strong>").to_html() == "<strong>text</strong>"
assert Html("<strong>text</strong>").to_latex() == "<strong>text</strong>"
assert Html("<strong>text</strong>").to_latex() == "\\textbf{text}"


def test_latex_escape():
Expand All @@ -56,17 +57,17 @@ def test_process_text_html():
def test_process_text_latex():
assert _process_text("a & _b_", context="latex") == "a \\& \\_b\\_"
assert _process_text(Text("\\_\\$"), context="latex") == "\\_\\$"
assert _process_text(Html("**a** & <b>"), context="latex") == "**a** \\& <b>"
assert _process_text(Html("**a** & <b>bold</b>"), context="latex") == "**a** \\& \\textbf{bold}"
assert _process_text(Md("**a**"), context="latex") == "\\textbf{a}"
assert _process_text(None, context="latex") == ""

with pytest.raises(NotImplementedError) as exc_info:
_process_text(Md("**a** & <b>"), context="latex")

assert "Markdown to LaTeX conversion is not supported yet" in exc_info.value.args[0]


def test_process_text_raises():
with pytest.raises(TypeError) as exc_info:
_process_text(1, context="html") # type: ignore

assert "Invalid type: <class 'int'>" in exc_info.value.args[0]


def test_md_latex():
assert _md_latex("Testing **bold** text") == "Testing \\textbf{bold} text"