typsphinx 0.4.3__tar.gz → 0.4.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. {typsphinx-0.4.3/typsphinx.egg-info → typsphinx-0.4.4}/PKG-INFO +17 -15
  2. {typsphinx-0.4.3 → typsphinx-0.4.4}/README.md +3 -2
  3. {typsphinx-0.4.3 → typsphinx-0.4.4}/pyproject.toml +19 -18
  4. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_config_other_options.py +20 -40
  5. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_config_toctree_defaults.py +4 -8
  6. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_entry_points.py +2 -13
  7. typsphinx-0.4.4/tests/test_preview_version_sync.py +105 -0
  8. {typsphinx-0.4.3 → typsphinx-0.4.4}/typsphinx/builder.py +3 -3
  9. {typsphinx-0.4.3 → typsphinx-0.4.4}/typsphinx/pdf.py +3 -4
  10. {typsphinx-0.4.3 → typsphinx-0.4.4}/typsphinx/template_engine.py +12 -12
  11. {typsphinx-0.4.3 → typsphinx-0.4.4}/typsphinx/translator.py +8 -8
  12. {typsphinx-0.4.3 → typsphinx-0.4.4/typsphinx.egg-info}/PKG-INFO +17 -15
  13. {typsphinx-0.4.3 → typsphinx-0.4.4}/typsphinx.egg-info/SOURCES.txt +1 -0
  14. typsphinx-0.4.4/typsphinx.egg-info/requires.txt +24 -0
  15. typsphinx-0.4.3/typsphinx.egg-info/requires.txt +0 -21
  16. {typsphinx-0.4.3 → typsphinx-0.4.4}/LICENSE +0 -0
  17. {typsphinx-0.4.3 → typsphinx-0.4.4}/setup.cfg +0 -0
  18. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_admonitions.py +0 -0
  19. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_builder.py +0 -0
  20. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_builder_requirement13.py +0 -0
  21. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_config.py +0 -0
  22. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_config_template_mapping.py +0 -0
  23. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_documentation_configuration.py +0 -0
  24. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_documentation_installation.py +0 -0
  25. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_documentation_usage.py +0 -0
  26. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_examples_basic.py +0 -0
  27. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_extension.py +0 -0
  28. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_inline_references.py +0 -0
  29. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_integration_advanced.py +0 -0
  30. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_integration_basic.py +0 -0
  31. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_integration_multi_doc.py +0 -0
  32. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_integration_nested_toctree.py +0 -0
  33. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_math_fallback.py +0 -0
  34. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_math_mitex.py +0 -0
  35. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_math_native.py +0 -0
  36. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_nested_toctree_paths.py +0 -0
  37. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_pdf_generation.py +0 -0
  38. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_template_assets.py +0 -0
  39. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_template_codly.py +0 -0
  40. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_template_engine.py +0 -0
  41. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_template_mitex.py +0 -0
  42. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_toctree_requirement13.py +0 -0
  43. {typsphinx-0.4.3 → typsphinx-0.4.4}/tests/test_translator.py +0 -0
  44. {typsphinx-0.4.3 → typsphinx-0.4.4}/typsphinx/__init__.py +0 -0
  45. {typsphinx-0.4.3 → typsphinx-0.4.4}/typsphinx/templates/base.typ +0 -0
  46. {typsphinx-0.4.3 → typsphinx-0.4.4}/typsphinx/writer.py +0 -0
  47. {typsphinx-0.4.3 → typsphinx-0.4.4}/typsphinx.egg-info/dependency_links.txt +0 -0
  48. {typsphinx-0.4.3 → typsphinx-0.4.4}/typsphinx.egg-info/entry_points.txt +0 -0
  49. {typsphinx-0.4.3 → typsphinx-0.4.4}/typsphinx.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: typsphinx
3
- Version: 0.4.3
3
+ Version: 0.4.4
4
4
  Summary: Sphinx extension for Typst output
5
5
  Author-email: YuSabo <yusabo90002@gmail.com>
6
6
  License-Expression: MIT
@@ -13,27 +13,26 @@ Classifier: Development Status :: 5 - Production/Stable
13
13
  Classifier: Framework :: Sphinx :: Extension
14
14
  Classifier: Intended Audience :: Developers
15
15
  Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.9
17
16
  Classifier: Programming Language :: Python :: 3.10
18
17
  Classifier: Programming Language :: Python :: 3.11
19
18
  Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
20
  Classifier: Topic :: Documentation :: Sphinx
21
21
  Classifier: Topic :: Software Development :: Documentation
22
- Requires-Python: >=3.9
22
+ Requires-Python: >=3.10
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
- Requires-Dist: sphinx>=5.0
26
- Requires-Dist: docutils>=0.18
27
- Requires-Dist: typst>=0.14.1
25
+ Requires-Dist: sphinx<9,>=5.0
26
+ Requires-Dist: docutils<0.22,>=0.18
27
+ Requires-Dist: typst<0.15,>=0.14.1
28
28
  Provides-Extra: dev
29
- Requires-Dist: pytest>=7.0; extra == "dev"
29
+ Requires-Dist: pytest<10,>=8.4; extra == "dev"
30
30
  Requires-Dist: pytest-cov>=4.0; extra == "dev"
31
- Requires-Dist: tox>=4.0; extra == "dev"
32
- Requires-Dist: tox-uv>=1.0; extra == "dev"
33
- Requires-Dist: black>=23.0; extra == "dev"
34
- Requires-Dist: ruff>=0.1.0; extra == "dev"
35
- Requires-Dist: mypy>=1.0; extra == "dev"
36
- Requires-Dist: sphinx-testing>=1.0; extra == "dev"
31
+ Requires-Dist: tox<5,>=4.56; extra == "dev"
32
+ Requires-Dist: tox-uv<2,>=1.35; extra == "dev"
33
+ Requires-Dist: black<27,>=26; extra == "dev"
34
+ Requires-Dist: ruff<0.16,>=0.15; extra == "dev"
35
+ Requires-Dist: mypy<3.0,>=1.13; extra == "dev"
37
36
  Requires-Dist: pre-commit>=3.0; extra == "dev"
38
37
  Requires-Dist: types-docutils>=0.18; extra == "dev"
39
38
  Requires-Dist: twine>=5.0; extra == "dev"
@@ -41,10 +40,13 @@ Requires-Dist: build>=1.0; extra == "dev"
41
40
  Provides-Extra: docs
42
41
  Requires-Dist: furo>=2024.0; extra == "docs"
43
42
  Requires-Dist: sphinx-autodoc-typehints>=1.0; extra == "docs"
43
+ Requires-Dist: sphinx-intl>=2.0; extra == "docs"
44
+ Requires-Dist: tomli>=2.0; python_version < "3.11" and extra == "docs"
44
45
  Dynamic: license-file
45
46
 
46
47
  # typsphinx
47
48
 
49
+ [![CI](https://github.com/YuSabo90002/typsphinx/actions/workflows/ci.yml/badge.svg)](https://github.com/YuSabo90002/typsphinx/actions/workflows/ci.yml)
48
50
  [![PyPI version](https://badge.fury.io/py/typsphinx.svg)](https://badge.fury.io/py/typsphinx)
49
51
  [![Python Support](https://img.shields.io/pypi/pyversions/typsphinx.svg)](https://pypi.org/project/typsphinx/)
50
52
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -78,7 +80,7 @@ typsphinx is a Sphinx extension that enables generating Typst documents from reS
78
80
 
79
81
  ## Requirements
80
82
 
81
- - Python 3.9 or higher
83
+ - Python 3.10 or higher
82
84
  - Sphinx 5.0 or higher
83
85
  - typst-py 0.11.1 or higher
84
86
 
@@ -365,4 +367,4 @@ See [CHANGELOG.md](CHANGELOG.md) for detailed version history.
365
367
  ---
366
368
 
367
369
  **Status**: Stable (v0.4.2) - Production ready
368
- **Python**: 3.9+ | **Sphinx**: 5.0+ | **Typst**: 0.11.1+
370
+ **Python**: 3.10+ | **Sphinx**: 5.0+ | **Typst**: 0.11.1+
@@ -1,5 +1,6 @@
1
1
  # typsphinx
2
2
 
3
+ [![CI](https://github.com/YuSabo90002/typsphinx/actions/workflows/ci.yml/badge.svg)](https://github.com/YuSabo90002/typsphinx/actions/workflows/ci.yml)
3
4
  [![PyPI version](https://badge.fury.io/py/typsphinx.svg)](https://badge.fury.io/py/typsphinx)
4
5
  [![Python Support](https://img.shields.io/pypi/pyversions/typsphinx.svg)](https://pypi.org/project/typsphinx/)
5
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -33,7 +34,7 @@ typsphinx is a Sphinx extension that enables generating Typst documents from reS
33
34
 
34
35
  ## Requirements
35
36
 
36
- - Python 3.9 or higher
37
+ - Python 3.10 or higher
37
38
  - Sphinx 5.0 or higher
38
39
  - typst-py 0.11.1 or higher
39
40
 
@@ -320,4 +321,4 @@ See [CHANGELOG.md](CHANGELOG.md) for detailed version history.
320
321
  ---
321
322
 
322
323
  **Status**: Stable (v0.4.2) - Production ready
323
- **Python**: 3.9+ | **Sphinx**: 5.0+ | **Typst**: 0.11.1+
324
+ **Python**: 3.10+ | **Sphinx**: 5.0+ | **Typst**: 0.11.1+
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "typsphinx"
7
- version = "0.4.3"
7
+ version = "0.4.4"
8
8
  description = "Sphinx extension for Typst output"
9
9
  readme = "README.md"
10
- requires-python = ">=3.9"
10
+ requires-python = ">=3.10"
11
11
  license = "MIT"
12
12
  authors = [
13
13
  {name = "YuSabo", email = "yusabo90002@gmail.com"}
@@ -18,30 +18,29 @@ classifiers = [
18
18
  "Framework :: Sphinx :: Extension",
19
19
  "Intended Audience :: Developers",
20
20
  "Programming Language :: Python :: 3",
21
- "Programming Language :: Python :: 3.9",
22
21
  "Programming Language :: Python :: 3.10",
23
22
  "Programming Language :: Python :: 3.11",
24
23
  "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
25
  "Topic :: Documentation :: Sphinx",
26
26
  "Topic :: Software Development :: Documentation",
27
27
  ]
28
28
 
29
29
  dependencies = [
30
- "sphinx>=5.0",
31
- "docutils>=0.18",
32
- "typst>=0.14.1",
30
+ "sphinx>=5.0,<9",
31
+ "docutils>=0.18,<0.22",
32
+ "typst>=0.14.1,<0.15",
33
33
  ]
34
34
 
35
35
  [project.optional-dependencies]
36
36
  dev = [
37
- "pytest>=7.0",
37
+ "pytest>=8.4,<10",
38
38
  "pytest-cov>=4.0",
39
- "tox>=4.0",
40
- "tox-uv>=1.0",
41
- "black>=23.0",
42
- "ruff>=0.1.0",
43
- "mypy>=1.0",
44
- "sphinx-testing>=1.0",
39
+ "tox>=4.56,<5",
40
+ "tox-uv>=1.35,<2",
41
+ "black>=26,<27",
42
+ "ruff>=0.15,<0.16",
43
+ "mypy>=1.13,<3.0",
45
44
  "pre-commit>=3.0",
46
45
  "types-docutils>=0.18",
47
46
  "twine>=5.0",
@@ -50,6 +49,8 @@ dev = [
50
49
  docs = [
51
50
  "furo>=2024.0",
52
51
  "sphinx-autodoc-typehints>=1.0",
52
+ "sphinx-intl>=2.0",
53
+ "tomli>=2.0; python_version < '3.11'",
53
54
  ]
54
55
 
55
56
  [project.urls]
@@ -84,7 +85,7 @@ markers = [
84
85
 
85
86
  [tool.black]
86
87
  line-length = 88
87
- target-version = ["py39", "py310", "py311", "py312"]
88
+ target-version = ["py310", "py311", "py312", "py313"]
88
89
  include = '\.pyi?$'
89
90
  exclude = '''
90
91
  /(
@@ -99,7 +100,7 @@ exclude = '''
99
100
 
100
101
  [tool.ruff]
101
102
  line-length = 88
102
- target-version = "py39"
103
+ target-version = "py310"
103
104
 
104
105
  [tool.ruff.lint]
105
106
  select = ["E", "F", "W", "I", "N", "UP", "B", "A", "C4", "T20"]
@@ -107,8 +108,8 @@ ignore = [
107
108
  "E501", # Line too long (handled by black)
108
109
  "T201", # print found (used in tests for debugging)
109
110
  "B017", # asserting blind exception in tests
110
- "UP035", # typing.Dict/List/Set deprecation (Python 3.9+ support)
111
- "UP006", # Use dict instead of Dict (Python 3.9+ support)
111
+ "UP035", # typing.Dict/List/Set deprecation (Python 3.10+ support)
112
+ "UP006", # Use dict instead of Dict (Python 3.10+ support)
112
113
  "UP028", # yield from (minor optimization)
113
114
  "N802", # Function naming (docutils visitor pattern uses PascalCase)
114
115
  "A001", # Shadowing builtins (copyright in conf.py is Sphinx convention)
@@ -116,7 +117,7 @@ ignore = [
116
117
  ]
117
118
 
118
119
  [tool.mypy]
119
- python_version = "3.9"
120
+ python_version = "3.10"
120
121
  warn_return_any = false
121
122
  warn_unused_configs = true
122
123
  disallow_untyped_defs = false
@@ -12,12 +12,10 @@ def test_typst_package_config_registered(make_app, tmp_path):
12
12
  """Test that typst_package is registered as a config value"""
13
13
  # Arrange: Create conf.py with typst_package setting
14
14
  conf_py = tmp_path / "conf.py"
15
- conf_py.write_text(
16
- """
15
+ conf_py.write_text("""
17
16
  extensions = ['typsphinx']
18
17
  typst_package = "@preview/diagraph:0.2.5"
19
- """
20
- )
18
+ """)
21
19
 
22
20
  # Create minimal index.rst
23
21
  index_rst = tmp_path / "index.rst"
@@ -35,15 +33,13 @@ def test_typst_package_imports_config_registered(make_app, tmp_path):
35
33
  """Test that typst_package_imports is registered as a config value"""
36
34
  # Arrange: Create conf.py with typst_package_imports setting
37
35
  conf_py = tmp_path / "conf.py"
38
- conf_py.write_text(
39
- """
36
+ conf_py.write_text("""
40
37
  extensions = ['typsphinx']
41
38
  typst_package_imports = [
42
39
  '#import "@preview/diagraph:0.2.5": *',
43
40
  '#import "@preview/tablex:0.1.0": *',
44
41
  ]
45
- """
46
- )
42
+ """)
47
43
 
48
44
  # Create minimal index.rst
49
45
  index_rst = tmp_path / "index.rst"
@@ -65,12 +61,10 @@ def test_typst_template_function_config_registered(make_app, tmp_path):
65
61
  """Test that typst_template_function is registered as a config value"""
66
62
  # Arrange: Create conf.py with typst_template_function setting
67
63
  conf_py = tmp_path / "conf.py"
68
- conf_py.write_text(
69
- """
64
+ conf_py.write_text("""
70
65
  extensions = ['typsphinx']
71
66
  typst_template_function = "custom_template"
72
- """
73
- )
67
+ """)
74
68
 
75
69
  # Create minimal index.rst
76
70
  index_rst = tmp_path / "index.rst"
@@ -88,11 +82,9 @@ def test_typst_package_default_none(make_app, tmp_path):
88
82
  """Test that typst_package defaults to None when not set"""
89
83
  # Arrange: Create conf.py without typst_package
90
84
  conf_py = tmp_path / "conf.py"
91
- conf_py.write_text(
92
- """
85
+ conf_py.write_text("""
93
86
  extensions = ['typsphinx']
94
- """
95
- )
87
+ """)
96
88
 
97
89
  # Create minimal index.rst
98
90
  index_rst = tmp_path / "index.rst"
@@ -110,11 +102,9 @@ def test_typst_package_imports_default_none(make_app, tmp_path):
110
102
  """Test that typst_package_imports defaults to None when not set"""
111
103
  # Arrange: Create conf.py without typst_package_imports
112
104
  conf_py = tmp_path / "conf.py"
113
- conf_py.write_text(
114
- """
105
+ conf_py.write_text("""
115
106
  extensions = ['typsphinx']
116
- """
117
- )
107
+ """)
118
108
 
119
109
  # Create minimal index.rst
120
110
  index_rst = tmp_path / "index.rst"
@@ -132,11 +122,9 @@ def test_typst_template_function_default_none(make_app, tmp_path):
132
122
  """Test that typst_template_function defaults to None when not set"""
133
123
  # Arrange: Create conf.py without typst_template_function
134
124
  conf_py = tmp_path / "conf.py"
135
- conf_py.write_text(
136
- """
125
+ conf_py.write_text("""
137
126
  extensions = ['typsphinx']
138
- """
139
- )
127
+ """)
140
128
 
141
129
  # Create minimal index.rst
142
130
  index_rst = tmp_path / "index.rst"
@@ -154,12 +142,10 @@ def test_typst_output_dir_config_registered(make_app, tmp_path):
154
142
  """Test that typst_output_dir is registered as a config value"""
155
143
  # Arrange: Create conf.py with typst_output_dir setting
156
144
  conf_py = tmp_path / "conf.py"
157
- conf_py.write_text(
158
- """
145
+ conf_py.write_text("""
159
146
  extensions = ['typsphinx']
160
147
  typst_output_dir = '_custom/typst'
161
- """
162
- )
148
+ """)
163
149
 
164
150
  # Create minimal index.rst
165
151
  index_rst = tmp_path / "index.rst"
@@ -177,11 +163,9 @@ def test_typst_output_dir_default_value(make_app, tmp_path):
177
163
  """Test that typst_output_dir defaults to '_build/typst' when not set"""
178
164
  # Arrange: Create conf.py without typst_output_dir
179
165
  conf_py = tmp_path / "conf.py"
180
- conf_py.write_text(
181
- """
166
+ conf_py.write_text("""
182
167
  extensions = ['typsphinx']
183
- """
184
- )
168
+ """)
185
169
 
186
170
  # Create minimal index.rst
187
171
  index_rst = tmp_path / "index.rst"
@@ -199,12 +183,10 @@ def test_typst_debug_config_registered(make_app, tmp_path):
199
183
  """Test that typst_debug is registered as a config value"""
200
184
  # Arrange: Create conf.py with typst_debug setting
201
185
  conf_py = tmp_path / "conf.py"
202
- conf_py.write_text(
203
- """
186
+ conf_py.write_text("""
204
187
  extensions = ['typsphinx']
205
188
  typst_debug = True
206
- """
207
- )
189
+ """)
208
190
 
209
191
  # Create minimal index.rst
210
192
  index_rst = tmp_path / "index.rst"
@@ -222,11 +204,9 @@ def test_typst_debug_default_false(make_app, tmp_path):
222
204
  """Test that typst_debug defaults to False when not set"""
223
205
  # Arrange: Create conf.py without typst_debug
224
206
  conf_py = tmp_path / "conf.py"
225
- conf_py.write_text(
226
- """
207
+ conf_py.write_text("""
227
208
  extensions = ['typsphinx']
228
- """
229
- )
209
+ """)
230
210
 
231
211
  # Create minimal index.rst
232
212
  index_rst = tmp_path / "index.rst"
@@ -77,8 +77,7 @@ typst_toctree_defaults = {
77
77
  typst_documents = [('index', 'index', 'Test', 'Author')]
78
78
  """
79
79
  (srcdir / "conf.py").write_text(conf_content)
80
- (srcdir / "index.rst").write_text(
81
- """
80
+ (srcdir / "index.rst").write_text("""
82
81
  Test Document
83
82
  =============
84
83
 
@@ -86,8 +85,7 @@ Test Document
86
85
  :maxdepth: 2
87
86
 
88
87
  chapter1
89
- """
90
- )
88
+ """)
91
89
  (srcdir / "chapter1.rst").write_text("Chapter 1\n=========\n")
92
90
 
93
91
  app = make_app(srcdir=srcdir, buildername="typst")
@@ -123,8 +121,7 @@ typst_documents = [('index', 'index', 'Test', 'Author')]
123
121
  (srcdir / "conf.py").write_text(conf_content)
124
122
 
125
123
  # toctree with explicit maxdepth:2 (should override default maxdepth:4)
126
- (srcdir / "index.rst").write_text(
127
- """
124
+ (srcdir / "index.rst").write_text("""
128
125
  Test
129
126
  ====
130
127
 
@@ -133,8 +130,7 @@ Test
133
130
  :numbered:
134
131
 
135
132
  chapter1
136
- """
137
- )
133
+ """)
138
134
  (srcdir / "chapter1.rst").write_text("Chapter\n=======\n")
139
135
 
140
136
  app = make_app(srcdir=srcdir, buildername="typst")
@@ -2,20 +2,13 @@
2
2
  Tests for entry points configuration.
3
3
  """
4
4
 
5
- import sys
6
5
  from importlib.metadata import entry_points
7
6
 
8
7
 
9
8
  def test_entry_point_registration():
10
9
  """Test that entry points are defined in pyproject.toml."""
11
10
  # Get entry points for sphinx.builders group
12
- if sys.version_info >= (3, 10):
13
- # Python 3.10+ uses select() method
14
- eps = entry_points(group="sphinx.builders")
15
- else:
16
- # Python 3.9 uses dict-like access
17
- all_eps = entry_points()
18
- eps = all_eps.get("sphinx.builders", [])
11
+ eps = entry_points(group="sphinx.builders")
19
12
 
20
13
  # Convert to list of names
21
14
  ep_names = [ep.name for ep in eps]
@@ -32,11 +25,7 @@ def test_entry_point_registration():
32
25
  def test_entry_point_value():
33
26
  """Test that the entry points point to the correct module."""
34
27
  # Get entry points for sphinx.builders group
35
- if sys.version_info >= (3, 10):
36
- eps = entry_points(group="sphinx.builders")
37
- else:
38
- all_eps = entry_points()
39
- eps = all_eps.get("sphinx.builders", [])
28
+ eps = entry_points(group="sphinx.builders")
40
29
 
41
30
  # Find the entry points
42
31
  typst_ep = None
@@ -0,0 +1,105 @@
1
+ """
2
+ Tests guarding the 3-way `@preview` version-sync hazard.
3
+
4
+ typsphinx declares the same four Typst Universe `@preview` package versions
5
+ (codly, codly-languages, mitex, gentle-clues) in three separate places:
6
+ `typsphinx/writer.py`, `typsphinx/template_engine.py`, and
7
+ `typsphinx/templates/base.typ`. These must stay in lockstep, or generated
8
+ Typst documents can end up importing mismatched package versions depending
9
+ on which code path produced them. This module asserts the three declaration
10
+ sites agree, so a future single-file edit fails CI loudly instead of
11
+ silently (D-03).
12
+ """
13
+
14
+ import re
15
+ from pathlib import Path
16
+
17
+ REPO_ROOT = Path(__file__).resolve().parents[1]
18
+
19
+ WRITER_PATH = REPO_ROOT / "typsphinx" / "writer.py"
20
+ TEMPLATE_ENGINE_PATH = REPO_ROOT / "typsphinx" / "template_engine.py"
21
+ BASE_TYP_PATH = REPO_ROOT / "typsphinx" / "templates" / "base.typ"
22
+
23
+ EXPECTED_PACKAGES = {"codly", "codly-languages", "mitex", "gentle-clues"}
24
+
25
+ # Matches an actual Typst `#import "@preview/<name>:<version>"` statement
26
+ # (not a bare mention in a comment or docstring example). name is
27
+ # letters/digits/underscore/hyphen; version is a three-part semver.
28
+ _PREVIEW_IMPORT_RE = re.compile(
29
+ r'#import\s+"@preview/(?P<name>[A-Za-z0-9_-]+):(?P<version>\d+\.\d+\.\d+)"'
30
+ )
31
+
32
+
33
+ def _extract_preview_versions(path):
34
+ """Parse a file's raw text for `#import "@preview/<name>:<version>"` lines.
35
+
36
+ Only matches actual Typst import statements, not bare `@preview/...`
37
+ text appearing in comments or docstring examples (e.g. a docstring
38
+ illustrating the `typst_package` config option format). Returns a dict
39
+ mapping package name to version string. If a package name appears more
40
+ than once in a file, the last occurrence wins (mirrors how a human
41
+ reading the file top-to-bottom would resolve it).
42
+ """
43
+ text = path.read_text()
44
+ versions = {}
45
+ for match in _PREVIEW_IMPORT_RE.finditer(text):
46
+ versions[match.group("name")] = match.group("version")
47
+ return versions
48
+
49
+
50
+ def test_preview_versions_identical_across_declaration_sites():
51
+ """The three declaration sites must agree on every @preview version.
52
+
53
+ This compares the files against each other (not against a hardcoded
54
+ expected mapping) so the test stays correct if the whole set is
55
+ intentionally rebumped in lockstep — it only fails on a *divergence*.
56
+ """
57
+ writer_versions = _extract_preview_versions(WRITER_PATH)
58
+ template_engine_versions = _extract_preview_versions(TEMPLATE_ENGINE_PATH)
59
+ base_typ_versions = _extract_preview_versions(BASE_TYP_PATH)
60
+
61
+ all_files = {
62
+ "writer.py": writer_versions,
63
+ "template_engine.py": template_engine_versions,
64
+ "base.typ": base_typ_versions,
65
+ }
66
+
67
+ all_packages = set()
68
+ for versions in all_files.values():
69
+ all_packages.update(versions.keys())
70
+
71
+ divergences = []
72
+ for package in sorted(all_packages):
73
+ per_file_versions = {
74
+ filename: versions.get(package, "<missing>")
75
+ for filename, versions in all_files.items()
76
+ }
77
+ if len(set(per_file_versions.values())) > 1:
78
+ divergences.append((package, per_file_versions))
79
+
80
+ assert (
81
+ not divergences
82
+ ), "@preview version desync detected across declaration sites: " + "; ".join(
83
+ f"{package}: {per_file_versions}" for package, per_file_versions in divergences
84
+ )
85
+
86
+
87
+ def test_all_four_packages_declared():
88
+ """Each declaration site must declare all four expected packages.
89
+
90
+ Without this, a dropped import in one file could make the identity
91
+ check above vacuously pass (an empty dict equals another empty dict).
92
+ """
93
+ files = {
94
+ "writer.py": WRITER_PATH,
95
+ "template_engine.py": TEMPLATE_ENGINE_PATH,
96
+ "base.typ": BASE_TYP_PATH,
97
+ }
98
+
99
+ for filename, path in files.items():
100
+ declared = set(_extract_preview_versions(path).keys())
101
+ missing = EXPECTED_PACKAGES - declared
102
+ assert not missing, (
103
+ f"{filename} is missing expected @preview packages: {missing} "
104
+ f"(declared: {declared})"
105
+ )
@@ -8,7 +8,7 @@ building Typst output from Sphinx documentation.
8
8
  import shutil
9
9
  from collections.abc import Iterator
10
10
  from os import path
11
- from typing import Optional, Set
11
+ from typing import Set
12
12
 
13
13
  from docutils import nodes
14
14
  from sphinx.builders import Builder
@@ -57,7 +57,7 @@ class TypstBuilder(Builder):
57
57
  for docname in self.env.found_docs:
58
58
  yield docname
59
59
 
60
- def get_target_uri(self, docname: str, typ: Optional[str] = None) -> str:
60
+ def get_target_uri(self, docname: str, typ: str | None = None) -> str:
61
61
  """
62
62
  Return the target URI for a document.
63
63
 
@@ -88,7 +88,7 @@ class TypstBuilder(Builder):
88
88
 
89
89
  def write(
90
90
  self,
91
- build_docnames: Optional[Set[str]],
91
+ build_docnames: Set[str] | None,
92
92
  updated_docnames: Set[str],
93
93
  method: str = "update",
94
94
  ) -> None:
@@ -8,7 +8,6 @@ using the typst Python package (Requirement 9).
8
8
  import logging
9
9
  import os
10
10
  import tempfile
11
- from typing import Optional
12
11
 
13
12
  logger = logging.getLogger(__name__)
14
13
 
@@ -32,8 +31,8 @@ class TypstCompilationError(Exception):
32
31
  def __init__(
33
32
  self,
34
33
  message: str,
35
- typst_error: Optional[Exception] = None,
36
- source_location: Optional[str] = None,
34
+ typst_error: Exception | None = None,
35
+ source_location: str | None = None,
37
36
  ):
38
37
  """
39
38
  Initialize TypstCompilationError.
@@ -108,7 +107,7 @@ def get_typst_version() -> str:
108
107
  return "not installed"
109
108
 
110
109
 
111
- def compile_typst_to_pdf(typst_content: str, root_dir: Optional[str] = None) -> bytes:
110
+ def compile_typst_to_pdf(typst_content: str, root_dir: str | None = None) -> bytes:
112
111
  """
113
112
  Compile Typst content to PDF bytes.
114
113
 
@@ -7,7 +7,7 @@ for Typst documents (Requirement 8).
7
7
 
8
8
  import logging
9
9
  from pathlib import Path
10
- from typing import Any, Dict, List, Optional
10
+ from typing import Any, Dict, List
11
11
 
12
12
  logger = logging.getLogger(__name__)
13
13
 
@@ -40,15 +40,15 @@ class TemplateEngine:
40
40
 
41
41
  def __init__(
42
42
  self,
43
- template_path: Optional[str] = None,
44
- template_name: Optional[str] = None,
45
- search_paths: Optional[List[str]] = None,
46
- parameter_mapping: Optional[Dict[str, str]] = None,
47
- typst_package: Optional[str] = None,
48
- typst_template_function: Optional[Any] = None,
49
- typst_package_imports: Optional[List[str]] = None,
50
- typst_authors: Optional[Dict[str, Dict[str, Any]]] = None,
51
- typst_author_params: Optional[Dict[str, Dict[str, Any]]] = None,
43
+ template_path: str | None = None,
44
+ template_name: str | None = None,
45
+ search_paths: List[str] | None = None,
46
+ parameter_mapping: Dict[str, str] | None = None,
47
+ typst_package: str | None = None,
48
+ typst_template_function: Any | None = None,
49
+ typst_package_imports: List[str] | None = None,
50
+ typst_authors: Dict[str, Dict[str, Any]] | None = None,
51
+ typst_author_params: Dict[str, Dict[str, Any]] | None = None,
52
52
  ):
53
53
  """
54
54
  Initialize TemplateEngine.
@@ -404,7 +404,7 @@ class TemplateEngine:
404
404
  else:
405
405
  return (str(author_value),)
406
406
 
407
- def _try_load_file(self, file_path: str) -> Optional[str]:
407
+ def _try_load_file(self, file_path: str) -> str | None:
408
408
  """
409
409
  Try to load content from file.
410
410
 
@@ -420,7 +420,7 @@ class TemplateEngine:
420
420
  except (FileNotFoundError, OSError):
421
421
  return None
422
422
 
423
- def _format_authors_with_details(self, authors: Optional[tuple] = None) -> str:
423
+ def _format_authors_with_details(self, authors: tuple | None = None) -> str:
424
424
  """
425
425
  Format authors with detailed information as Typst dict tuple.
426
426
 
@@ -6,7 +6,7 @@ nodes to Typst markup.
6
6
  """
7
7
 
8
8
  import re
9
- from typing import Any, List, Optional, Union
9
+ from typing import Any, List
10
10
 
11
11
  from docutils import nodes
12
12
  from sphinx import addnodes
@@ -83,10 +83,10 @@ class TypstTranslator(SphinxTranslator):
83
83
 
84
84
  # Definition list state
85
85
  self.in_definition_list = False
86
- self.current_term_buffer: Union[str, List[str], None] = None
87
- self.current_definition_buffer: Optional[List[str]] = None
86
+ self.current_term_buffer: str | List[str] | None = None
87
+ self.current_definition_buffer: List[str] | None = None
88
88
  self.definition_list_items = [] # List of (term, definition) tuples
89
- self.saved_body: Optional[List[Any]] = (
89
+ self.saved_body: List[Any] | None = (
90
90
  None # Used by definition lists for body swapping
91
91
  )
92
92
 
@@ -1596,7 +1596,7 @@ class TypstTranslator(SphinxTranslator):
1596
1596
  self.add_text("]")
1597
1597
 
1598
1598
  def _compute_relative_include_path(
1599
- self, target_docname: str, current_docname: Optional[str]
1599
+ self, target_docname: str, current_docname: str | None
1600
1600
  ) -> str:
1601
1601
  """
1602
1602
  Compute relative path for toctree #include() directive.
@@ -1677,7 +1677,7 @@ class TypstTranslator(SphinxTranslator):
1677
1677
 
1678
1678
  # Find common parent by comparing path components
1679
1679
  common_length = 0
1680
- for i, (c, t) in enumerate(zip(current_parts, target_parts)):
1680
+ for i, (c, t) in enumerate(zip(current_parts, target_parts, strict=False)):
1681
1681
  if c == t:
1682
1682
  common_length = i + 1
1683
1683
  else:
@@ -1707,7 +1707,7 @@ class TypstTranslator(SphinxTranslator):
1707
1707
  return relative_path
1708
1708
 
1709
1709
  def _compute_relative_image_path(
1710
- self, image_uri: str, current_docname: Optional[str]
1710
+ self, image_uri: str, current_docname: str | None
1711
1711
  ) -> str:
1712
1712
  """
1713
1713
  Compute relative path for image() function.
@@ -1782,7 +1782,7 @@ class TypstTranslator(SphinxTranslator):
1782
1782
 
1783
1783
  # Find common parent by comparing path components
1784
1784
  common_length = 0
1785
- for i, (c, img) in enumerate(zip(current_parts, image_parts)):
1785
+ for i, (c, img) in enumerate(zip(current_parts, image_parts, strict=False)):
1786
1786
  if c == img:
1787
1787
  common_length = i + 1
1788
1788
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: typsphinx
3
- Version: 0.4.3
3
+ Version: 0.4.4
4
4
  Summary: Sphinx extension for Typst output
5
5
  Author-email: YuSabo <yusabo90002@gmail.com>
6
6
  License-Expression: MIT
@@ -13,27 +13,26 @@ Classifier: Development Status :: 5 - Production/Stable
13
13
  Classifier: Framework :: Sphinx :: Extension
14
14
  Classifier: Intended Audience :: Developers
15
15
  Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.9
17
16
  Classifier: Programming Language :: Python :: 3.10
18
17
  Classifier: Programming Language :: Python :: 3.11
19
18
  Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
20
  Classifier: Topic :: Documentation :: Sphinx
21
21
  Classifier: Topic :: Software Development :: Documentation
22
- Requires-Python: >=3.9
22
+ Requires-Python: >=3.10
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
- Requires-Dist: sphinx>=5.0
26
- Requires-Dist: docutils>=0.18
27
- Requires-Dist: typst>=0.14.1
25
+ Requires-Dist: sphinx<9,>=5.0
26
+ Requires-Dist: docutils<0.22,>=0.18
27
+ Requires-Dist: typst<0.15,>=0.14.1
28
28
  Provides-Extra: dev
29
- Requires-Dist: pytest>=7.0; extra == "dev"
29
+ Requires-Dist: pytest<10,>=8.4; extra == "dev"
30
30
  Requires-Dist: pytest-cov>=4.0; extra == "dev"
31
- Requires-Dist: tox>=4.0; extra == "dev"
32
- Requires-Dist: tox-uv>=1.0; extra == "dev"
33
- Requires-Dist: black>=23.0; extra == "dev"
34
- Requires-Dist: ruff>=0.1.0; extra == "dev"
35
- Requires-Dist: mypy>=1.0; extra == "dev"
36
- Requires-Dist: sphinx-testing>=1.0; extra == "dev"
31
+ Requires-Dist: tox<5,>=4.56; extra == "dev"
32
+ Requires-Dist: tox-uv<2,>=1.35; extra == "dev"
33
+ Requires-Dist: black<27,>=26; extra == "dev"
34
+ Requires-Dist: ruff<0.16,>=0.15; extra == "dev"
35
+ Requires-Dist: mypy<3.0,>=1.13; extra == "dev"
37
36
  Requires-Dist: pre-commit>=3.0; extra == "dev"
38
37
  Requires-Dist: types-docutils>=0.18; extra == "dev"
39
38
  Requires-Dist: twine>=5.0; extra == "dev"
@@ -41,10 +40,13 @@ Requires-Dist: build>=1.0; extra == "dev"
41
40
  Provides-Extra: docs
42
41
  Requires-Dist: furo>=2024.0; extra == "docs"
43
42
  Requires-Dist: sphinx-autodoc-typehints>=1.0; extra == "docs"
43
+ Requires-Dist: sphinx-intl>=2.0; extra == "docs"
44
+ Requires-Dist: tomli>=2.0; python_version < "3.11" and extra == "docs"
44
45
  Dynamic: license-file
45
46
 
46
47
  # typsphinx
47
48
 
49
+ [![CI](https://github.com/YuSabo90002/typsphinx/actions/workflows/ci.yml/badge.svg)](https://github.com/YuSabo90002/typsphinx/actions/workflows/ci.yml)
48
50
  [![PyPI version](https://badge.fury.io/py/typsphinx.svg)](https://badge.fury.io/py/typsphinx)
49
51
  [![Python Support](https://img.shields.io/pypi/pyversions/typsphinx.svg)](https://pypi.org/project/typsphinx/)
50
52
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -78,7 +80,7 @@ typsphinx is a Sphinx extension that enables generating Typst documents from reS
78
80
 
79
81
  ## Requirements
80
82
 
81
- - Python 3.9 or higher
83
+ - Python 3.10 or higher
82
84
  - Sphinx 5.0 or higher
83
85
  - typst-py 0.11.1 or higher
84
86
 
@@ -365,4 +367,4 @@ See [CHANGELOG.md](CHANGELOG.md) for detailed version history.
365
367
  ---
366
368
 
367
369
  **Status**: Stable (v0.4.2) - Production ready
368
- **Python**: 3.9+ | **Sphinx**: 5.0+ | **Typst**: 0.11.1+
370
+ **Python**: 3.10+ | **Sphinx**: 5.0+ | **Typst**: 0.11.1+
@@ -24,6 +24,7 @@ tests/test_math_mitex.py
24
24
  tests/test_math_native.py
25
25
  tests/test_nested_toctree_paths.py
26
26
  tests/test_pdf_generation.py
27
+ tests/test_preview_version_sync.py
27
28
  tests/test_template_assets.py
28
29
  tests/test_template_codly.py
29
30
  tests/test_template_engine.py
@@ -0,0 +1,24 @@
1
+ sphinx<9,>=5.0
2
+ docutils<0.22,>=0.18
3
+ typst<0.15,>=0.14.1
4
+
5
+ [dev]
6
+ pytest<10,>=8.4
7
+ pytest-cov>=4.0
8
+ tox<5,>=4.56
9
+ tox-uv<2,>=1.35
10
+ black<27,>=26
11
+ ruff<0.16,>=0.15
12
+ mypy<3.0,>=1.13
13
+ pre-commit>=3.0
14
+ types-docutils>=0.18
15
+ twine>=5.0
16
+ build>=1.0
17
+
18
+ [docs]
19
+ furo>=2024.0
20
+ sphinx-autodoc-typehints>=1.0
21
+ sphinx-intl>=2.0
22
+
23
+ [docs:python_version < "3.11"]
24
+ tomli>=2.0
@@ -1,21 +0,0 @@
1
- sphinx>=5.0
2
- docutils>=0.18
3
- typst>=0.14.1
4
-
5
- [dev]
6
- pytest>=7.0
7
- pytest-cov>=4.0
8
- tox>=4.0
9
- tox-uv>=1.0
10
- black>=23.0
11
- ruff>=0.1.0
12
- mypy>=1.0
13
- sphinx-testing>=1.0
14
- pre-commit>=3.0
15
- types-docutils>=0.18
16
- twine>=5.0
17
- build>=1.0
18
-
19
- [docs]
20
- furo>=2024.0
21
- sphinx-autodoc-typehints>=1.0
File without changes
File without changes
File without changes