From cc48a08abf622b3500c27c9ce6320bc695870d6a Mon Sep 17 00:00:00 2001 From: ftnext Date: Tue, 19 Aug 2025 00:08:10 +0900 Subject: [PATCH 1/9] ]refactor] Extract module --- src/sphinx_notion/nodes/__init__.py | 0 src/sphinx_notion/nodes/literal_block.py | 7 +++++++ src/sphinx_notion/writers.py | 9 +-------- 3 files changed, 8 insertions(+), 8 deletions(-) create mode 100644 src/sphinx_notion/nodes/__init__.py create mode 100644 src/sphinx_notion/nodes/literal_block.py diff --git a/src/sphinx_notion/nodes/__init__.py b/src/sphinx_notion/nodes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/sphinx_notion/nodes/literal_block.py b/src/sphinx_notion/nodes/literal_block.py new file mode 100644 index 0000000..a4cad03 --- /dev/null +++ b/src/sphinx_notion/nodes/literal_block.py @@ -0,0 +1,7 @@ +def to_notion_language(pygments_language: str) -> str: + if pygments_language == "default": + # default means "not specified" + return "plain text" + if pygments_language == "text": + return "plain text" + return pygments_language diff --git a/src/sphinx_notion/writers.py b/src/sphinx_notion/writers.py index dbe77d3..c908fe0 100644 --- a/src/sphinx_notion/writers.py +++ b/src/sphinx_notion/writers.py @@ -7,14 +7,7 @@ from sphinx.builders.text import TextBuilder from sphinx.writers.text import TextTranslator - -def to_notion_language(pygments_language: str) -> str: - if pygments_language == "default": - # default means "not specified" - return "plain text" - if pygments_language == "text": - return "plain text" - return pygments_language +from sphinx_notion.nodes.literal_block import to_notion_language class NotionTranslator(TextTranslator): From b12c9677dc4f87ac977f1a59799ef878df336d57 Mon Sep 17 00:00:00 2001 From: ftnext Date: Tue, 19 Aug 2025 00:10:15 +0900 Subject: [PATCH 2/9] [test] Write parametrized tests --- tests/nodes/__init__.py | 0 tests/nodes/test_literal_block.py | 15 +++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 tests/nodes/__init__.py create mode 100644 tests/nodes/test_literal_block.py diff --git a/tests/nodes/__init__.py b/tests/nodes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/nodes/test_literal_block.py b/tests/nodes/test_literal_block.py new file mode 100644 index 0000000..8422887 --- /dev/null +++ b/tests/nodes/test_literal_block.py @@ -0,0 +1,15 @@ +import pytest + +from sphinx_notion.nodes.literal_block import to_notion_language + + +@pytest.mark.parametrize( + "pygments_language, expected", + [ + ("python", "python"), + ("default", "plain text"), + ("text", "plain text"), + ], +) +def test_to_notion_language(pygments_language, expected): + assert to_notion_language(pygments_language) == expected From b6afc2e06c71a0edb7f8806a362821d7a099dcb7 Mon Sep 17 00:00:00 2001 From: ftnext Date: Tue, 19 Aug 2025 00:14:02 +0900 Subject: [PATCH 3/9] [feat] Additional python-related language support --- src/sphinx_notion/nodes/literal_block.py | 7 +++++++ tests/nodes/test_literal_block.py | 3 +++ 2 files changed, 10 insertions(+) diff --git a/src/sphinx_notion/nodes/literal_block.py b/src/sphinx_notion/nodes/literal_block.py index a4cad03..a5889b1 100644 --- a/src/sphinx_notion/nodes/literal_block.py +++ b/src/sphinx_notion/nodes/literal_block.py @@ -4,4 +4,11 @@ def to_notion_language(pygments_language: str) -> str: return "plain text" if pygments_language == "text": return "plain text" + if pygments_language == "pytb": + return "plain text" + if pygments_language == "output": + return "plain text" + if pygments_language == "pycon": + return "python" + # TODO: Support for other languages return pygments_language diff --git a/tests/nodes/test_literal_block.py b/tests/nodes/test_literal_block.py index 8422887..ea7f21d 100644 --- a/tests/nodes/test_literal_block.py +++ b/tests/nodes/test_literal_block.py @@ -8,7 +8,10 @@ [ ("python", "python"), ("default", "plain text"), + ("pycon", "python"), + ("pytb", "plain text"), ("text", "plain text"), + ("output", "plain text"), ], ) def test_to_notion_language(pygments_language, expected): From 00186d540e087e375531ebfa14c9023e401ab711 Mon Sep 17 00:00:00 2001 From: ftnext Date: Tue, 19 Aug 2025 00:18:31 +0900 Subject: [PATCH 4/9] [refactor] Simplify language handling --- src/sphinx_notion/nodes/literal_block.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/sphinx_notion/nodes/literal_block.py b/src/sphinx_notion/nodes/literal_block.py index a5889b1..aff02f2 100644 --- a/src/sphinx_notion/nodes/literal_block.py +++ b/src/sphinx_notion/nodes/literal_block.py @@ -1,14 +1,14 @@ -def to_notion_language(pygments_language: str) -> str: - if pygments_language == "default": - # default means "not specified" - return "plain text" - if pygments_language == "text": - return "plain text" - if pygments_language == "pytb": - return "plain text" - if pygments_language == "output": - return "plain text" - if pygments_language == "pycon": +PygmentsLanguage = str + +_as_python: set[PygmentsLanguage] = {"python", "pycon"} +# default means "not specified" +_as_plain_text: set[PygmentsLanguage] = {"default", "pytb", "text", "output"} + + +def to_notion_language(pygments_language: PygmentsLanguage) -> str: + if pygments_language in _as_plain_text: + return "plain text" + if pygments_language in _as_python: return "python" # TODO: Support for other languages return pygments_language From de9af52addcc603cd2359577abbdd863371ae99a Mon Sep 17 00:00:00 2001 From: ftnext Date: Tue, 19 Aug 2025 00:21:04 +0900 Subject: [PATCH 5/9] [refactor] Delegate to unit test case --- tests/roots/test-code/expected.json | 15 --------------- tests/roots/test-code/source/index.rst | 4 ---- 2 files changed, 19 deletions(-) diff --git a/tests/roots/test-code/expected.json b/tests/roots/test-code/expected.json index 7a7ef5e..4dd90c3 100644 --- a/tests/roots/test-code/expected.json +++ b/tests/roots/test-code/expected.json @@ -14,21 +14,6 @@ "language": "python" } }, - { - "object": "block", - "type": "code", - "code": { - "rich_text": [ - { - "type": "text", - "text": { - "content": "print(3 * 4)" - } - } - ], - "language": "plain text" - } - }, { "object": "block", "type": "code", diff --git a/tests/roots/test-code/source/index.rst b/tests/roots/test-code/source/index.rst index 342cd89..18598ac 100644 --- a/tests/roots/test-code/source/index.rst +++ b/tests/roots/test-code/source/index.rst @@ -3,10 +3,6 @@ print(1 + 2) print("Hello") -.. code-block:: - - print(3 * 4) - .. code-block:: text print(5 - 6) From a71f273e09665d30b1127041aaf534e3c134a540 Mon Sep 17 00:00:00 2001 From: ftnext Date: Wed, 20 Aug 2025 19:55:11 +0900 Subject: [PATCH 6/9] [bugfix] Get standard language name with Pygments --- pyproject.toml | 1 + src/sphinx_notion/nodes/literal_block.py | 11 +++++++++++ src/sphinx_notion/writers.py | 12 ++++++++---- tests/roots/test-code/expected.json | 15 +++++++++++++++ tests/roots/test-code/source/index.rst | 5 +++++ 5 files changed, 40 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9e8feda..20304e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,7 @@ dev = [ "flake8", "mypy", "types-docutils", + "types-Pygments", ] [tool.taskipy.tasks] diff --git a/src/sphinx_notion/nodes/literal_block.py b/src/sphinx_notion/nodes/literal_block.py index aff02f2..71f2b0e 100644 --- a/src/sphinx_notion/nodes/literal_block.py +++ b/src/sphinx_notion/nodes/literal_block.py @@ -1,5 +1,16 @@ +from pygments.lexers import get_lexer_by_name + PygmentsLanguage = str + +def get_standard_pygments_language(language: str) -> PygmentsLanguage: + lexer = get_lexer_by_name(language) + # Lexer has aliases but mypy raises this error: + # >error: "Lexer" has no attribute "aliases" [attr-defined] + # https://github.com/pygments/pygments/blob/2.19.2/pygments/lexer.py#L111-L113 + return lexer.aliases[0] # type: ignore[attr-defined] + + _as_python: set[PygmentsLanguage] = {"python", "pycon"} # default means "not specified" _as_plain_text: set[PygmentsLanguage] = {"default", "pytb", "text", "output"} diff --git a/src/sphinx_notion/writers.py b/src/sphinx_notion/writers.py index c908fe0..5497fea 100644 --- a/src/sphinx_notion/writers.py +++ b/src/sphinx_notion/writers.py @@ -7,7 +7,10 @@ from sphinx.builders.text import TextBuilder from sphinx.writers.text import TextTranslator -from sphinx_notion.nodes.literal_block import to_notion_language +from sphinx_notion.nodes.literal_block import ( + get_standard_pygments_language, + to_notion_language, +) class NotionTranslator(TextTranslator): @@ -118,6 +121,9 @@ def visit_bullet_list(self, node: nodes.Element) -> None: def visit_literal_block(self, node: nodes.Element) -> None: super().visit_literal_block(node) + pygments_language = get_standard_pygments_language( + node.attributes["language"] + ) self._json.append( { "object": "block", @@ -126,9 +132,7 @@ def visit_literal_block(self, node: nodes.Element) -> None: "rich_text": [ {"type": "text", "text": {"content": node.astext()}} ], - "language": to_notion_language( - node.attributes["language"] - ), + "language": to_notion_language(pygments_language), }, } ) diff --git a/tests/roots/test-code/expected.json b/tests/roots/test-code/expected.json index 4dd90c3..416375c 100644 --- a/tests/roots/test-code/expected.json +++ b/tests/roots/test-code/expected.json @@ -28,5 +28,20 @@ ], "language": "plain text" } + }, + { + "object": "block", + "type": "code", + "code": { + "rich_text": [ + { + "type": "text", + "text": { + "content": ">>> print(\"Hello, World!\")\nHello, World!" + } + } + ], + "language": "python" + } } ] diff --git a/tests/roots/test-code/source/index.rst b/tests/roots/test-code/source/index.rst index 18598ac..6f5ef03 100644 --- a/tests/roots/test-code/source/index.rst +++ b/tests/roots/test-code/source/index.rst @@ -6,3 +6,8 @@ .. code-block:: text print(5 - 6) + +.. code-block:: python-console + + >>> print("Hello, World!") + Hello, World! From 2eaf304e421dda38d2f225ea3614fd125a4c668a Mon Sep 17 00:00:00 2001 From: ftnext Date: Wed, 20 Aug 2025 19:58:48 +0900 Subject: [PATCH 7/9] [test] get_standard_pygments_language --- tests/nodes/test_literal_block.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/nodes/test_literal_block.py b/tests/nodes/test_literal_block.py index ea7f21d..3974e43 100644 --- a/tests/nodes/test_literal_block.py +++ b/tests/nodes/test_literal_block.py @@ -1,6 +1,24 @@ import pytest -from sphinx_notion.nodes.literal_block import to_notion_language +from sphinx_notion.nodes.literal_block import ( + get_standard_pygments_language, + to_notion_language, +) + + +@pytest.mark.parametrize( + "language, expected", + [ + ("python", "python"), + ("python3", "python"), + ("pycon", "pycon"), + ("python-console", "pycon"), + ("pytb", "pytb"), + ("py3tb", "pytb"), + ], +) +def test_get_standard_pygments_language(language, expected): + assert get_standard_pygments_language(language) == expected @pytest.mark.parametrize( From 3bd325f34261862c877d901bd41f6bec1384bf7e Mon Sep 17 00:00:00 2001 From: ftnext Date: Wed, 20 Aug 2025 20:10:57 +0900 Subject: [PATCH 8/9] [bugfix] Support "default" --- src/sphinx_notion/nodes/literal_block.py | 3 +++ tests/nodes/test_literal_block.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/sphinx_notion/nodes/literal_block.py b/src/sphinx_notion/nodes/literal_block.py index 71f2b0e..56dbc1e 100644 --- a/src/sphinx_notion/nodes/literal_block.py +++ b/src/sphinx_notion/nodes/literal_block.py @@ -4,6 +4,9 @@ def get_standard_pygments_language(language: str) -> PygmentsLanguage: + # "default" language means "not specified" + if language == "default": + return "default" lexer = get_lexer_by_name(language) # Lexer has aliases but mypy raises this error: # >error: "Lexer" has no attribute "aliases" [attr-defined] diff --git a/tests/nodes/test_literal_block.py b/tests/nodes/test_literal_block.py index 3974e43..79d7379 100644 --- a/tests/nodes/test_literal_block.py +++ b/tests/nodes/test_literal_block.py @@ -15,6 +15,9 @@ ("python-console", "pycon"), ("pytb", "pytb"), ("py3tb", "pytb"), + ("text", "text"), + ("output", "output"), + ("default", "default"), ], ) def test_get_standard_pygments_language(language, expected): From ff5998c91266003728c519063b53dd2b6cbb270c Mon Sep 17 00:00:00 2001 From: ftnext Date: Wed, 20 Aug 2025 20:12:49 +0900 Subject: [PATCH 9/9] [refactor] Make inline (no need to extend these sets) --- src/sphinx_notion/nodes/literal_block.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/sphinx_notion/nodes/literal_block.py b/src/sphinx_notion/nodes/literal_block.py index 56dbc1e..157654f 100644 --- a/src/sphinx_notion/nodes/literal_block.py +++ b/src/sphinx_notion/nodes/literal_block.py @@ -14,15 +14,10 @@ def get_standard_pygments_language(language: str) -> PygmentsLanguage: return lexer.aliases[0] # type: ignore[attr-defined] -_as_python: set[PygmentsLanguage] = {"python", "pycon"} -# default means "not specified" -_as_plain_text: set[PygmentsLanguage] = {"default", "pytb", "text", "output"} - - def to_notion_language(pygments_language: PygmentsLanguage) -> str: - if pygments_language in _as_plain_text: + if pygments_language in {"default", "pytb", "text", "output"}: return "plain text" - if pygments_language in _as_python: + if pygments_language in {"python", "pycon"}: return "python" # TODO: Support for other languages return pygments_language