uEdition 1.3.2__py3-none-any.whl → 2.0.0a2__py3-none-any.whl

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.

Potentially problematic release.


This version of uEdition might be problematic. Click here for more details.

uedition/__about__.py CHANGED
@@ -2,4 +2,5 @@
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
4
  """About this package."""
5
- __version__ = "1.3.2"
5
+
6
+ __version__ = "2.0.0a2"
uedition/cli/__init__.py CHANGED
@@ -7,7 +7,6 @@ from rich import print as print_cli
7
7
 
8
8
  from uedition.__about__ import __version__
9
9
  from uedition.cli import build as build_module
10
- from uedition.cli import check as check_module
11
10
  from uedition.cli import create as create_module
12
11
  from uedition.cli import language as language_module
13
12
  from uedition.cli import serve as serve_module
@@ -37,12 +36,6 @@ def serve() -> None:
37
36
  serve_module.run()
38
37
 
39
38
 
40
- @app.command()
41
- def check() -> None:
42
- """Check that the μEdition is set up correctly."""
43
- check_module.run()
44
-
45
-
46
39
  @app.command()
47
40
  def update() -> None:
48
41
  """Update the μEdition."""
uedition/cli/build.py CHANGED
@@ -2,15 +2,15 @@
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
4
  """Build functionality."""
5
+
5
6
  import json
6
7
  import subprocess
7
- from copy import deepcopy
8
8
  from os import makedirs, path
9
9
  from shutil import copytree, ignore_patterns, rmtree
10
10
 
11
11
  from yaml import safe_dump, safe_load
12
12
 
13
- from uedition.settings import reload_settings, settings
13
+ from uedition.settings import NoConfigError, reload_settings, settings
14
14
 
15
15
  LANDING_PAGE_TEMPLATE = """\
16
16
  <!DOCTYPE html>
@@ -103,41 +103,50 @@ def toc_build(lang: dict) -> None:
103
103
 
104
104
 
105
105
  def config_build(lang: dict) -> None:
106
- """Build the language-specific JupyterBook config based on the main config."""
107
- config = deepcopy(settings["jb_config"])
108
- config["author"] = settings["author"]["name"]
109
- # Set the language-specific title
106
+ """Build the language-specific Sphinx config based on the main config."""
107
+ with open("toc.yml") as in_f:
108
+ toc = safe_load(in_f)
109
+ # Build the default configuration
110
+ config = {
111
+ "needs_sphinx": "8",
112
+ "language": lang["code"],
113
+ "root_doc": toc["root"],
114
+ "html_theme": "sphinx_book_theme",
115
+ "html_theme_options": {},
116
+ "extensions": ["myst_parser", "sphinx_external_toc", "uedition"],
117
+ "myst_enable_extensions": [
118
+ "amsmath",
119
+ "attrs_inline",
120
+ "colon_fence",
121
+ "deflist",
122
+ "dollarmath",
123
+ "fieldlist",
124
+ "html_admonition",
125
+ "html_image",
126
+ "replacements",
127
+ "smartquotes",
128
+ "strikethrough",
129
+ "substitution",
130
+ "tasklist",
131
+ ],
132
+ }
133
+ # Load in any sphinx configuration
134
+ config.update(settings["sphinx_config"])
135
+ # Set settings-based
110
136
  if lang["code"] in settings["title"]:
111
- config["title"] = settings["title"][lang["code"]]
137
+ config["project"] = settings["title"][lang["code"]]
112
138
  elif len(settings["languages"]) > 0 and settings["languages"][0]["code"] in settings["title"]:
113
- config["title"] = settings["title"][settings["languages"][0]["code"]]
139
+ config["project"] = settings["title"][settings["languages"][0]["code"]]
114
140
  else:
115
- config["title"] = f"Missing title for {lang['label']}"
116
- # Set the repository information
117
- if settings["repository"]["url"] and "repository" not in config:
118
- config["repository"] = {
119
- "url": settings["repository"]["url"],
120
- "path": lang["path"],
121
- "branch": settings["repository"]["branch"],
122
- }
123
- if "html" not in config:
124
- config["html"] = {}
125
- if "use_repository_button" not in config["html"]:
126
- config["html"]["use_repository_button"] = True
127
- # Set the Sphinx language
128
- if "sphinx" not in config:
129
- config["sphinx"] = {}
130
- if "config" not in config["sphinx"]:
131
- config["sphinx"]["config"] = {}
132
- config["sphinx"]["config"]["language"] = lang["code"]
133
- # Add the uEdition extension
134
- if "extra_extensions" not in config["sphinx"]:
135
- config["sphinx"]["extra_extensions"] = []
136
- if "uedition" not in config["sphinx"]["extra_extensions"]:
137
- config["sphinx"]["extra_extensions"].append("uedition")
138
-
139
- with open(path.join(lang["path"], "_config.yml"), "w") as out_f:
140
- safe_dump(config, out_f, encoding="utf-8")
141
+ config["project"] = f"Missing title for {lang['label']}"
142
+ config["author"] = settings["author"]["name"]
143
+ if settings["repository"]["url"]:
144
+ config["html_theme_options"]["repository_url"] = f"{settings['repository']['url']}"
145
+ config["html_theme_options"]["use_repository_button"] = True
146
+
147
+ with open(path.join(lang["path"], "conf.py"), "w") as out_f:
148
+ for name, value in config.items():
149
+ out_f.write(f"{name} = {value!a}\n")
141
150
 
142
151
 
143
152
  def static_build(lang: dict) -> None:
@@ -153,41 +162,39 @@ def full_build(lang: dict) -> None:
153
162
  toc_build(lang)
154
163
  config_build(lang)
155
164
  static_build(lang)
156
- subprocess.run(
157
- [ # noqa: S603, S607
158
- "jupyter-book",
159
- "build",
160
- "--all",
161
- "--path-output",
162
- path.join("_build", lang["path"]),
165
+ subprocess.run( # noqa:S603
166
+ [ # noqa: S607
167
+ "sphinx-build",
168
+ "--builder",
169
+ "html",
170
+ "--fresh-env",
163
171
  lang["path"],
172
+ path.join("_build", lang["path"], "html"),
164
173
  ],
165
174
  check=False,
175
+ shell=False,
166
176
  )
167
177
  if settings["output"]["tei"]:
168
- subprocess.run(
169
- [ # noqa: S603, S607
170
- "jupyter-book",
171
- "build",
172
- "--all",
173
- "--path-output",
174
- path.join("_build", lang["path"]),
178
+ subprocess.run( # noqa: S603
179
+ [ # noqa:S607
180
+ "sphinx-build",
175
181
  "--builder",
176
- "custom",
177
- "--custom-builder",
178
182
  "tei",
183
+ "--fresh-env",
179
184
  lang["path"],
185
+ path.join("_build", lang["path"], "tei"),
180
186
  ],
181
187
  check=False,
188
+ shell=False,
182
189
  )
183
190
  copytree(
184
- path.join("_build", lang["path"], "_build", "html"),
191
+ path.join("_build", lang["path"], "html"),
185
192
  path.join(settings["output"]["path"], lang["path"]),
186
193
  dirs_exist_ok=True,
187
194
  )
188
195
  if settings["output"]["tei"]:
189
196
  copytree(
190
- path.join("_build", lang["path"], "_build", "tei"),
197
+ path.join("_build", lang["path"], "tei"),
191
198
  path.join(settings["output"]["path"], lang["path"]),
192
199
  ignore=ignore_patterns("_sphinx_design_static"),
193
200
  dirs_exist_ok=True,
@@ -197,39 +204,37 @@ def full_build(lang: dict) -> None:
197
204
  def partial_build(lang: dict) -> None:
198
205
  """Run the as-needed build process for a single language."""
199
206
  landing_build()
200
- subprocess.run(
201
- [ # noqa: S603, S607
202
- "jupyter-book",
203
- "build",
204
- "--path-output",
205
- path.join("_build", lang["path"]),
207
+ subprocess.run( # noqa: S603
208
+ [ # noqa: S607
209
+ "sphinx-build",
210
+ "--builder",
211
+ "html",
206
212
  lang["path"],
213
+ path.join("_build", lang["path"], "html"),
207
214
  ],
208
215
  check=False,
216
+ shell=False,
209
217
  )
210
218
  if settings["output"]["tei"]:
211
- subprocess.run(
212
- [ # noqa: S603, S607
213
- "jupyter-book",
214
- "build",
215
- "--path-output",
216
- path.join("_build", lang["path"]),
219
+ subprocess.run( # noqa:S603
220
+ [ # noqa: S607
221
+ "sphinx-build",
217
222
  "--builder",
218
- "custom",
219
- "--custom-builder",
220
223
  "tei",
221
224
  lang["path"],
225
+ path.join("_build", lang["path"], "tei"),
222
226
  ],
223
227
  check=False,
228
+ shell=False,
224
229
  )
225
230
  copytree(
226
- path.join("_build", lang["path"], "_build", "html"),
231
+ path.join("_build", lang["path"], "html"),
227
232
  path.join(settings["output"]["path"], lang["path"]),
228
233
  dirs_exist_ok=True,
229
234
  )
230
235
  if settings["output"]["tei"]:
231
236
  copytree(
232
- path.join("_build", lang["path"], "_build", "tei"),
237
+ path.join("_build", lang["path"], "tei"),
233
238
  path.join(settings["output"]["path"], lang["path"]),
234
239
  ignore=ignore_patterns("_sphinx_design_static"),
235
240
  dirs_exist_ok=True,
@@ -238,6 +243,8 @@ def partial_build(lang: dict) -> None:
238
243
 
239
244
  def run() -> None:
240
245
  """Build the full uEdition."""
246
+ if not path.exists("uEdition.yml") and not path.exists("uEdition.yaml"):
247
+ raise NoConfigError()
241
248
  if path.exists(settings["output"]["path"]):
242
249
  rmtree(settings["output"]["path"])
243
250
  for lang in settings["languages"]:
uedition/cli/language.py CHANGED
@@ -7,9 +7,13 @@ import os
7
7
  from copier import run_copy, run_update
8
8
  from yaml import dump, safe_load
9
9
 
10
+ from uedition.settings import NoConfigError
11
+
10
12
 
11
13
  def add(path: str) -> None:
12
14
  """Add a language to the μEdition using Copier."""
15
+ if not os.path.exists("uEdition.yml") and not os.path.exists("uEdition.yaml"):
16
+ raise NoConfigError()
13
17
  run_copy("gh:uEdition/uEdition-language-template", path, data={"path": path})
14
18
  with open(os.path.join(path, ".uEdition.answers")) as in_f:
15
19
  answers = safe_load(in_f)
@@ -32,6 +36,8 @@ def add(path: str) -> None:
32
36
 
33
37
  def update(path: str) -> None:
34
38
  """Update a language to the latest template."""
39
+ if not os.path.exists("uEdition.yml") and not os.path.exists("uEdition.yaml"):
40
+ raise NoConfigError()
35
41
  run_update(path, answers_file=".uEdition.answers", overwrite=True, data={"path": path})
36
42
  with open(os.path.join(path, ".uEdition.answers")) as in_f:
37
43
  answers = safe_load(in_f)
uedition/cli/serve.py CHANGED
@@ -8,7 +8,7 @@ from typing import Callable
8
8
  from livereload import Server
9
9
 
10
10
  from uedition.cli.build import full_build, partial_build
11
- from uedition.settings import settings
11
+ from uedition.settings import NoConfigError, settings
12
12
 
13
13
 
14
14
  def build_cmd(lang: dict, full: bool = True) -> Callable[[], None]: # noqa: FBT001, FBT002
@@ -29,6 +29,8 @@ def build_cmd(lang: dict, full: bool = True) -> Callable[[], None]: # noqa: FBT
29
29
 
30
30
  def run() -> None:
31
31
  """Run the development server."""
32
+ if not path.exists("uEdition.yml") and not path.exists("uEdition.yaml"):
33
+ raise NoConfigError()
32
34
  full_rebuilds = [build_cmd(lang, full=True) for lang in settings["languages"]]
33
35
  partial_rebuilds = [build_cmd(lang, full=False) for lang in settings["languages"]]
34
36
  for cmd in full_rebuilds:
uedition/cli/update.py CHANGED
@@ -2,9 +2,15 @@
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
4
  """The μEdition check functionality for validating a μEdition and its files."""
5
+ from os import path
6
+
5
7
  from copier import run_update
6
8
 
9
+ from uedition.settings import NoConfigError
10
+
7
11
 
8
12
  def run() -> None:
9
13
  """Update the μEdition using Copier."""
14
+ if not path.exists("uEdition.yml") and not path.exists("uEdition.yaml"):
15
+ raise NoConfigError()
10
16
  run_update(".", answers_file=".uEdition.answers", overwrite=True, skip_answered=True)
uedition/ext/config.py CHANGED
@@ -1,197 +1,31 @@
1
1
  # SPDX-FileCopyrightText: 2023-present Mark Hall <mark.hall@work.room3b.eu>
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
- """uEdition configuration handling.
4
+ """
5
+ uEdition configuration handling.
5
6
 
6
7
  This module handles reading the uEdition-specific configuration settings, validating them and
7
8
  adding any required default values.
8
9
  """
9
- from typing import Annotated, Any, Literal, Optional, Union
10
10
 
11
- from pydantic import BaseModel, ValidationError
12
- from pydantic.functional_validators import BeforeValidator
13
11
  from sphinx.application import Sphinx
12
+ from sphinx.config import Config
14
13
  from sphinx.util import logging
15
14
 
16
- logger = logging.getLogger(__name__)
17
-
18
-
19
- class RuleSelectorAttribute(BaseModel):
20
- """Validation rule for selecting based on an attribute with a given value."""
21
-
22
- attr: str
23
- value: str
24
-
25
-
26
- def expand_tei_namespace(value: str) -> str:
27
- """Expand any ```tei:``` namespace prefixes."""
28
- return value.replace("tei:", "{http://www.tei-c.org/ns/1.0}")
29
-
30
-
31
- def force_list(value: Any) -> list: # noqa: ANN401
32
- """Force the value into a list form."""
33
- if isinstance(value, list):
34
- return value
35
- return [value]
36
-
37
-
38
- class RuleSelector(BaseModel):
39
- """Validation rule for the selector for matching a TEI tag."""
40
-
41
- tag: Annotated[str, BeforeValidator(expand_tei_namespace)]
42
- attributes: Annotated[list[RuleSelectorAttribute], BeforeValidator(force_list)] = []
43
-
44
-
45
- class RuleText(BaseModel):
46
- """Validation rule for retrieving the text content from an attribute."""
47
-
48
- action: Literal["from-attribute"]
49
- attr: str
50
-
51
-
52
- class RuleAttributeCopy(BaseModel):
53
- """Validation rule for copying and attribute."""
54
-
55
- action: Literal["copy"] = "copy"
56
- attr: str
57
- source: str
58
-
59
-
60
- class RuleAttributeSet(BaseModel):
61
- """Validation rule for settings an attribute to a specific value."""
62
-
63
- action: Literal["set"]
64
- attr: str
65
- value: str
66
-
67
-
68
- class RuleAttributeDelete(BaseModel):
69
- """Validation rule for deleting an attribute."""
70
-
71
- action: Literal["delete"]
72
- attr: str
73
-
74
-
75
- def convert_string_to_selector_dict(value: str | dict) -> dict:
76
- """Convert a simple string selector into the dictionary representation."""
77
- if isinstance(value, str):
78
- return {"tag": value}
79
- return value
15
+ from uedition.ext.settings import TEISettings
80
16
 
81
-
82
- class Rule(BaseModel):
83
- """Validation model for a rule transforming a TEI tag into a HTML tag."""
84
-
85
- selector: Annotated[RuleSelector, BeforeValidator(convert_string_to_selector_dict)]
86
- tag: Union[str, None] = "div"
87
- text: Union[RuleText, None] = None
88
- attributes: list[Union[RuleAttributeCopy, RuleAttributeSet, RuleAttributeDelete]] = []
89
-
90
-
91
- class TextSection(BaseModel):
92
- """Validation model for a TEI text section."""
93
-
94
- title: str
95
- type: Literal["text"] = "text"
96
- content: str
97
- sort: str | None = None
98
- mappings: list[Rule] = []
99
-
100
-
101
- class SingleFieldRule(BaseModel):
102
- """Validation model for a TEI field rule with a single value."""
103
-
104
- title: str
105
- type: Literal["single"] = "single"
106
- content: str
107
-
108
-
109
- class ListFieldRule(BaseModel):
110
- """Validation model for a TEI field rule with a list of values."""
111
-
112
- title: str
113
- type: Literal["list"]
114
- content: str
115
-
116
-
117
- class DownloadFieldRule(BaseModel):
118
- """Validation model for a TEI field rule that creates a download link."""
119
-
120
- title: str
121
- type: Literal["download"]
122
- content: str
123
- target: str
124
-
125
-
126
- class FieldsSection(BaseModel):
127
- """Validation model for a TEI fields section."""
128
-
129
- title: str
130
- type: Literal["fields"]
131
- fields: list[SingleFieldRule | ListFieldRule | DownloadFieldRule]
132
-
133
-
134
- class TEIConfig(BaseModel):
135
- """Validation model for the TEI-specific settings."""
136
-
137
- text_only_in_leaf_nodes: bool = False
138
- mappings: list[Rule] = []
139
- sections: list[TextSection | FieldsSection] = []
140
-
141
-
142
- class Config(BaseModel):
143
- """Configuration validation model."""
144
-
145
- tei: Optional[TEIConfig]
146
-
147
-
148
- BASE_RULES = [
149
- {"selector": "tei:body", "tag": "section"},
150
- {"selector": "tei:head", "tag": "h1"},
151
- {"selector": "tei:p", "tag": "p"},
152
- {"selector": "tei:seg", "tag": "span"},
153
- {"selector": "tei:pb", "tag": "span"},
154
- {"selector": "tei:hi", "tag": "span"},
155
- {
156
- "selector": "tei:ref",
157
- "tag": "a",
158
- "attributes": [{"attr": "href", "source": "target"}],
159
- },
160
- {"selector": "tei:citedRange", "tag": "span"},
161
- {"selector": "tei:q", "tag": "span"},
162
- {"selector": "tei:hi", "tag": "span"},
163
- {"selector": "tei:foreign", "tag": "span"},
164
- {"selector": "tei:speaker", "tag": "span"},
165
- {"selector": "tei:stage", "tag": "span"},
166
- {"selector": "tei:lem", "tag": "span"},
167
- {"selector": "tei:sic", "tag": "span"},
168
- ]
169
- """Base mapping rules for mapping TEI tags to default HTML elements."""
17
+ logger = logging.getLogger(__name__)
170
18
 
171
19
 
172
20
  def validate_config(app: Sphinx, config: Config) -> None: # noqa: ARG001
173
21
  """Validate the configuration and add any default values."""
174
- if config.uEdition:
175
- if "tei" in config.uEdition:
176
- if "sections" in config.uEdition["tei"] and isinstance(config.uEdition["tei"]["sections"], list):
177
- if "mappings" in config.uEdition["tei"] and isinstance(config.uEdition["tei"]["mappings"], list):
178
- for section in config.uEdition["tei"]["sections"]:
179
- if "mappings" in section and isinstance(section["mappings"], list):
180
- section["mappings"] = section["mappings"] + config.uEdition["tei"]["mappings"] + BASE_RULES
181
- else:
182
- section["mappings"] = config.uEdition["tei"]["mappings"] + BASE_RULES
183
- try:
184
- config.uEdition = Config(**config.uEdition).dict()
185
- except ValidationError as e:
186
- for error in e.errors():
187
- logger.error(" -> ".join([str(loc) for loc in error["loc"]]))
188
- logger.error(f' {error["msg"]}')
189
- config.uEdition = {}
22
+ if config.tei:
23
+ config.tei = TEISettings(**config.tei).model_dump()
190
24
  else:
191
- config.uEdition = {}
25
+ config.tei = {"blocks": [], "marks": "", "sections": []}
192
26
 
193
27
 
194
28
  def setup(app: Sphinx) -> None:
195
29
  """Set up the Sphinx configuration handling for the uEdition."""
196
- app.add_config_value("uEdition", default=None, rebuild="html", types=[dict])
30
+ app.add_config_value("tei", default=None, rebuild="html", types=[dict])
197
31
  app.connect("config-inited", validate_config)
@@ -0,0 +1,131 @@
1
+ # SPDX-FileCopyrightText: 2023-present Mark Hall <mark.hall@work.room3b.eu>
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ """Additional settings validation."""
5
+
6
+ from typing import Literal
7
+
8
+ from pydantic import BaseModel
9
+
10
+
11
+ class ValueTitlePair(BaseModel):
12
+ """A simple pair of value and title."""
13
+
14
+ value: str
15
+ """The value for the pair."""
16
+ title: str
17
+ """The title to show for the pair."""
18
+
19
+
20
+ class TEINodeAttribute(BaseModel):
21
+ """Single attribute for a TEINode."""
22
+
23
+ name: str
24
+ """The name of the attribute."""
25
+ value: str | None = None
26
+ """A fixed value to use for the attribute."""
27
+ type: Literal["string"] | Literal["static"] | Literal["id-ref"] | Literal["text"] | Literal["html-attribute"] = (
28
+ "string"
29
+ )
30
+ """The type of attribute this is."""
31
+ default: str = ""
32
+ """The default value to use if none is set."""
33
+ target: str | None = None
34
+ """The target HTML attribute."""
35
+
36
+
37
+ class TEINode(BaseModel):
38
+ """A single node in a TEI document."""
39
+
40
+ name: str
41
+ """The name to use to address this node."""
42
+ selector: str
43
+ """The selector to identify this node."""
44
+ attributes: list[TEINodeAttribute] = []
45
+ """A list of attributes that are used on this node."""
46
+ tag: str | None = None
47
+ """The HTML tag to use to render the node."""
48
+ text: str | None = None
49
+ """Where to get the text from."""
50
+ content: str | None = None
51
+ """Allowed child nodes. Only relevant for block nodes."""
52
+
53
+
54
+ class TEIMetadataSectionSingleFieldRule(BaseModel):
55
+ """Validation model for a TEI field rule with a single value."""
56
+
57
+ title: str
58
+ type: Literal["single"] = "single"
59
+ selector: str
60
+
61
+
62
+ class TEIMetadataSectionListFieldRule(BaseModel):
63
+ """Validation model for a TEI field rule with a list of values."""
64
+
65
+ title: str
66
+ type: Literal["list"]
67
+ selector: str
68
+
69
+
70
+ class TEIMetadataSectionDownloadFieldRule(BaseModel):
71
+ """Validation model for a TEI field rule that creates a download link."""
72
+
73
+ title: str
74
+ type: Literal["download"]
75
+ selector: str
76
+ target: str
77
+
78
+
79
+ class TEIMetadataSection(BaseModel):
80
+ """A metadata section in the TEI document."""
81
+
82
+ name: str
83
+ """The name of the section."""
84
+ title: str | None = None
85
+ """The title to show in the UI."""
86
+ type: Literal["metadata"]
87
+ """The type must be set to metadata."""
88
+ selector: str
89
+ """The XPath selector to retrieve this section."""
90
+ fields: list[
91
+ TEIMetadataSectionSingleFieldRule | TEIMetadataSectionListFieldRule | TEIMetadataSectionDownloadFieldRule
92
+ ]
93
+ """Fields to display."""
94
+
95
+
96
+ class TEITextSection(BaseModel):
97
+ """A section in the TEI document containing a single text."""
98
+
99
+ name: str
100
+ """The name of the section."""
101
+ title: str | None = None
102
+ """The title to show in the UI."""
103
+ type: Literal["text"]
104
+ """The type must be set to text."""
105
+ selector: str
106
+ """The XPath selector to retrieve this section."""
107
+
108
+
109
+ class TEITextListSection(BaseModel):
110
+ """A section in the TEI document containing multiple texts."""
111
+
112
+ name: str
113
+ """The name of the section."""
114
+ title: str | None = None
115
+ """The title to show in the UI."""
116
+ type: Literal["textlist"]
117
+ """The type must be set to textlist."""
118
+ selector: str
119
+ """The XPath selector to retrieve the texts in this section."""
120
+ sort: str | None = None
121
+
122
+
123
+ class TEISettings(BaseModel):
124
+ """Settings for the TEI processing."""
125
+
126
+ blocks: list[TEINode] = []
127
+ """List of blocks supported in the TEI document."""
128
+ marks: list[TEINode] = []
129
+ """List of inline marks supported in the TEI document."""
130
+ sections: list[TEIMetadataSection | TEITextSection | TEITextListSection] = []
131
+ """List of sections within the TEI document."""
@@ -6,7 +6,6 @@ import xml.sax.saxutils
6
6
  from collections.abc import Iterator
7
7
 
8
8
  import sphinx
9
- import sphinx_jupyterbook_latex
10
9
  from docutils import nodes
11
10
  from docutils.io import StringOutput
12
11
  from sphinx.application import Sphinx
@@ -37,6 +36,7 @@ MAPPINGS = [
37
36
  "attrs": [{"target": "type", "value": "literal-block"}, {"source": "language", "target": "subtype"}],
38
37
  },
39
38
  {"cls": nodes.compound, "tagname": "div", "type": "block"},
39
+ {"cls": nodes.admonition, "tagname": "div", "type": "block"},
40
40
  {"cls": sphinx.addnodes.toctree},
41
41
  {
42
42
  "cls": nodes.footnote,
@@ -47,7 +47,6 @@ MAPPINGS = [
47
47
  {"target": "target", "source": "backrefs", "format": "#{value}", "join": " "},
48
48
  ],
49
49
  },
50
- {"cls": sphinx_jupyterbook_latex.nodes.HiddenCellNode},
51
50
  {
52
51
  "cls": nodes.transition,
53
52
  "tagname": "div",
@@ -204,7 +203,7 @@ class TEITranslator(nodes.GenericNodeVisitor):
204
203
  else:
205
204
  self.output.append(text)
206
205
  else:
207
- self.output.append(f"{self.indent*self.level}<tei:span>{text}</tei:span>\n")
206
+ self.output.append(f"{self.indent * self.level}<tei:span>{text}</tei:span>\n")
208
207
 
209
208
  def depart_Text(self, node: nodes.TextElement) -> None: # noqa: N802
210
209
  """Unused."""