Skip to content

Commit 37a830d

Browse files
committed
👌 Add heading-offset option to include directive
1 parent de00c89 commit 37a830d

File tree

2 files changed

+28
-14
lines changed

2 files changed

+28
-14
lines changed

myst_parser/mdit_to_docutils/base.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ def __getattr__(self, name: str):
118118
"current_node",
119119
"reporter",
120120
"language_module_rst",
121+
"_heading_offset",
121122
"_level_to_section",
122123
):
123124
raise AttributeError(
@@ -142,6 +143,7 @@ def setup_render(
142143
self.language_module_rst: ModuleType = get_language_rst(
143144
self.document.settings.language_code
144145
)
146+
self._heading_offset: int = 0
145147
# a mapping of heading levels to its currently associated node
146148
self._level_to_section: dict[int, nodes.document | nodes.section] = {
147149
0: self.document
@@ -324,13 +326,15 @@ def nested_render_text(
324326
lineno: int,
325327
inline: bool = False,
326328
temp_root_node: None | nodes.Element = None,
329+
heading_offset: int = 0,
327330
) -> None:
328331
"""Render unparsed text (appending to the current node).
329332
330333
:param text: the text to render
331334
:param lineno: the starting line number of the text, within the full source
332335
:param inline: whether the text is inline or block
333336
:param temp_root_node: If set, allow sections to be created as children of this node
337+
:param heading_offset: offset heading levels by this amount
334338
"""
335339
tokens = (
336340
self.md.parseInline(text, self.md_env)
@@ -347,22 +351,27 @@ def nested_render_text(
347351
if token.map:
348352
token.map = [token.map[0] + lineno, token.map[1] + lineno]
349353

350-
if temp_root_node is None:
351-
self._render_tokens(tokens)
352-
else:
353-
# we need to temporarily set the root node,
354-
# and we also want to restore the level_to_section mapping at the end
355-
current_level_to_section = {
356-
i: node for i, node in self._level_to_section.items()
357-
}
358-
current_root_node = self.md_env.get("temp_root_node", None)
359-
try:
354+
@contextmanager
355+
def _restore():
356+
current_heading_offset = self._heading_offset
357+
self._heading_offset = heading_offset
358+
if temp_root_node is not None:
359+
# we need to temporarily set the root node,
360+
# and we also want to restore the level_to_section mapping at the end
361+
current_level_to_section = {
362+
i: node for i, node in self._level_to_section.items()
363+
}
364+
current_root_node = self.md_env.get("temp_root_node", None)
360365
self.md_env["temp_root_node"] = temp_root_node
361-
self._render_tokens(tokens)
362-
finally:
366+
yield
367+
self._heading_offset = current_heading_offset
368+
if temp_root_node is not None:
363369
self.md_env["temp_root_node"] = current_root_node
364370
self._level_to_section = current_level_to_section
365371

372+
with _restore():
373+
self._render_tokens(tokens)
374+
366375
@contextmanager
367376
def current_node_context(
368377
self, node: nodes.Element, append: bool = False
@@ -826,7 +835,7 @@ def generate_heading_target(
826835
def render_heading(self, token: SyntaxTreeNode) -> None:
827836
"""Render a heading, e.g. `# Heading`."""
828837

829-
level = int(token.tag[1])
838+
level = int(token.tag[1]) + self._heading_offset
830839

831840
# sections are only allowed as a parent of a document or another section
832841
# the only exception to this, is if a directive has called a nested parse,
@@ -1667,6 +1676,7 @@ def run_directive(
16671676
# to allow for altering relative image reference links
16681677
directive_class.option_spec["relative-images"] = directives.flag
16691678
directive_class.option_spec["relative-docs"] = directives.path
1679+
directive_class.option_spec["heading-offset"] = directives.nonnegative_int
16701680

16711681
try:
16721682
parsed = parse_directive_text(directive_class, first_line, content)

myst_parser/mocking.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,11 @@ def run(self) -> list[nodes.Element]:
469469
source_dir,
470470
path.parent,
471471
)
472-
self.renderer.nested_render_text(file_content, startline + 1)
472+
self.renderer.nested_render_text(
473+
file_content,
474+
startline + 1,
475+
heading_offset=self.options.get("heading-offset", 0),
476+
)
473477
finally:
474478
self.renderer.document["source"] = source
475479
self.renderer.reporter.source = rsource

0 commit comments

Comments
 (0)