From a95c713d814d19e998d2d821d6a72f3dc661c783 Mon Sep 17 00:00:00 2001 From: Kazuya Takei Date: Fri, 17 Jul 2026 18:22:20 +0900 Subject: [PATCH 1/6] feat: support font-paths from arguments and environment variavles --- src/rst2typst/pdf.py | 15 ++++++++++++- tests/test_pdf.py | 52 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 tests/test_pdf.py diff --git a/src/rst2typst/pdf.py b/src/rst2typst/pdf.py index 269e526..09598a8 100644 --- a/src/rst2typst/pdf.py +++ b/src/rst2typst/pdf.py @@ -1,5 +1,6 @@ """PDF handler.""" +import os import typst from docutils.frontend import validate_boolean @@ -25,6 +26,15 @@ class Writer(BaseWriter): "validator": validate_boolean, }, ), + ( + "List of directories stored custom fonts.", + ["--font-paths"], + { + "action": "store", + "dest": "font_paths", + "default": [], + }, + ), ), ) @@ -36,7 +46,10 @@ def translate(self): "rst2typst", force=self.document.settings.force_install_package, ) - self.output = typst.compile(self.output.encode()) + font_paths = list(self.document.settings.font_paths) + if "TYPST_FONT_PATHS" in os.environ: + font_paths += os.environ["TYPST_FONT_PATHS"].split(os.pathsep) + self.output = typst.compile(self.output.encode(), font_paths=font_paths) def display_warnings(self): pass diff --git a/tests/test_pdf.py b/tests/test_pdf.py new file mode 100644 index 0000000..fcf7e0e --- /dev/null +++ b/tests/test_pdf.py @@ -0,0 +1,52 @@ +import os +from unittest.mock import patch, MagicMock + +import pytest +from docutils.core import publish_string + +from rst2typst import pdf + + +@pytest.fixture(autouse=True) +def _clear_font_paths_env(monkeypatch: pytest.MonkeyPatch): + monkeypatch.delenv("TYPST_FONT_PATHS", raising=False) + + +def _publish(**settings_overrides) -> MagicMock: + with patch.object(pdf.typst, "compile") as mock: + publish_string( + "", + writer=pdf.Writer(), + settings_overrides=settings_overrides, + ) + return mock + + +def test_font_paths_is_not_set(): + mock = _publish() + assert mock.call_args.kwargs["font_paths"] == [] + + +def test_font_paths_from_args(): + mock = _publish(font_paths=["/tmp/fonts"]) + assert mock.call_args.kwargs["font_paths"] == ["/tmp/fonts"] + + +def test_font_paths_from_env(monkeypatch: pytest.MonkeyPatch): + monkeypatch.setenv( + "TYPST_FONT_PATHS", os.pathsep.join(["/opt/fonts", "/tmp/fonts"]) + ) + mock = _publish() + assert mock.call_args.kwargs["font_paths"] == [ + "/opt/fonts", + "/tmp/fonts", + ] + + +def test_font_paths_from_args_and_env(monkeypatch: pytest.MonkeyPatch): + monkeypatch.setenv("TYPST_FONT_PATHS", "/opt/fonts") + mock = _publish(font_paths=["/tmp/fonts"]) + assert mock.call_args.kwargs["font_paths"] == [ + "/tmp/fonts", + "/opt/fonts", + ] From b4e720136f52e64808f714b2e3629aa471776bae Mon Sep 17 00:00:00 2001 From: Kazuya Takei Date: Fri, 17 Jul 2026 23:56:16 +0900 Subject: [PATCH 2/6] docs: add description about added option --- docs/cli.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/cli.rst b/docs/cli.rst index bf32dd2..d498f46 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -74,6 +74,15 @@ Options These are same from options for :ref:`cli-rst2typst` command. +--font-paths + List of directories stored custom fonts. + + :Type: List of string + :Default: Empty list ( ``[]`` ) + + This option sets folders that have font files beside folder installing system fonts. + You should pass folder path if you want to use extra fonts when generating pdf. + Examples ======== From 33197c95eea837481f1443eb70dc9efa3ca87acf Mon Sep 17 00:00:00 2001 From: Kazuya Takei Date: Sat, 18 Jul 2026 02:26:32 +0900 Subject: [PATCH 3/6] docs: fix text for CodeRabbit --- docs/cli.rst | 6 +++--- src/rst2typst/pdf.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/cli.rst b/docs/cli.rst index d498f46..a61d5bf 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -75,13 +75,13 @@ Options These are same from options for :ref:`cli-rst2typst` command. --font-paths - List of directories stored custom fonts. + List of directories where custom fonts are stored. :Type: List of string :Default: Empty list ( ``[]`` ) - This option sets folders that have font files beside folder installing system fonts. - You should pass folder path if you want to use extra fonts when generating pdf. + This option specifies folders that contain custom font files in addition to the system font folders. + You should pass a folder path if you want to use extra fonts when generating a PDF. Examples ======== diff --git a/src/rst2typst/pdf.py b/src/rst2typst/pdf.py index 09598a8..09a493e 100644 --- a/src/rst2typst/pdf.py +++ b/src/rst2typst/pdf.py @@ -27,7 +27,7 @@ class Writer(BaseWriter): }, ), ( - "List of directories stored custom fonts.", + "List of directories where custom fonts are stored.", ["--font-paths"], { "action": "store", From 74d93dde6d7898bf5670f05dbf88484676f5a3a3 Mon Sep 17 00:00:00 2001 From: Kazuya Takei Date: Sat, 18 Jul 2026 02:33:33 +0900 Subject: [PATCH 4/6] fix: ignore empty TYPST_FONT_PATHS environment variable --- src/rst2typst/pdf.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/rst2typst/pdf.py b/src/rst2typst/pdf.py index 09a493e..c952f49 100644 --- a/src/rst2typst/pdf.py +++ b/src/rst2typst/pdf.py @@ -47,8 +47,9 @@ def translate(self): force=self.document.settings.force_install_package, ) font_paths = list(self.document.settings.font_paths) - if "TYPST_FONT_PATHS" in os.environ: - font_paths += os.environ["TYPST_FONT_PATHS"].split(os.pathsep) + env_font_paths = os.environ.get("TYPST_FONT_PATHS") + if env_font_paths: + font_paths += env_font_paths.split(os.pathsep) self.output = typst.compile(self.output.encode(), font_paths=font_paths) def display_warnings(self): From aebc162be88d8ef48c1e2e337df95e788ec30a18 Mon Sep 17 00:00:00 2001 From: Kazuya Takei Date: Sat, 18 Jul 2026 02:41:18 +0900 Subject: [PATCH 5/6] fix: parse --font-paths as a list instead of a raw string --- src/rst2typst/pdf.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/rst2typst/pdf.py b/src/rst2typst/pdf.py index c952f49..ed832ee 100644 --- a/src/rst2typst/pdf.py +++ b/src/rst2typst/pdf.py @@ -3,7 +3,7 @@ import os import typst -from docutils.frontend import validate_boolean +from docutils.frontend import validate_boolean, validate_comma_separated_list from .package import install_package, package_dir from .writer import Writer as BaseWriter @@ -30,9 +30,11 @@ class Writer(BaseWriter): "List of directories where custom fonts are stored.", ["--font-paths"], { - "action": "store", + "action": "append", "dest": "font_paths", + "metavar": "", "default": [], + "validator": validate_comma_separated_list, }, ), ), @@ -46,7 +48,7 @@ def translate(self): "rst2typst", force=self.document.settings.force_install_package, ) - font_paths = list(self.document.settings.font_paths) + font_paths = self.document.settings.font_paths env_font_paths = os.environ.get("TYPST_FONT_PATHS") if env_font_paths: font_paths += env_font_paths.split(os.pathsep) From c24f7662a251558d3818f45d0721bfd96a9e5027 Mon Sep 17 00:00:00 2001 From: Kazuya Takei Date: Sat, 18 Jul 2026 03:11:29 +0900 Subject: [PATCH 6/6] fix: normalize font_paths to a list regardless of input source --- src/rst2typst/pdf.py | 4 ++++ tests/test_pdf.py | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/src/rst2typst/pdf.py b/src/rst2typst/pdf.py index ed832ee..d56dea3 100644 --- a/src/rst2typst/pdf.py +++ b/src/rst2typst/pdf.py @@ -49,6 +49,10 @@ def translate(self): force=self.document.settings.force_install_package, ) font_paths = self.document.settings.font_paths + if isinstance(font_paths, str): + font_paths = [font_paths] + else: + font_paths = list(font_paths) env_font_paths = os.environ.get("TYPST_FONT_PATHS") if env_font_paths: font_paths += env_font_paths.split(os.pathsep) diff --git a/tests/test_pdf.py b/tests/test_pdf.py index fcf7e0e..99952e7 100644 --- a/tests/test_pdf.py +++ b/tests/test_pdf.py @@ -32,6 +32,11 @@ def test_font_paths_from_args(): assert mock.call_args.kwargs["font_paths"] == ["/tmp/fonts"] +def test_font_paths_from_args_str(): + mock = _publish(font_paths="/tmp/fonts") + assert mock.call_args.kwargs["font_paths"] == ["/tmp/fonts"] + + def test_font_paths_from_env(monkeypatch: pytest.MonkeyPatch): monkeypatch.setenv( "TYPST_FONT_PATHS", os.pathsep.join(["/opt/fonts", "/tmp/fonts"])