From d1990c5c2f4d5a1281924582f7a8ca4744d70c12 Mon Sep 17 00:00:00 2001 From: James Knight Date: Fri, 19 Jul 2024 21:57:06 -0400 Subject: [PATCH] Support building line blocks with markdown-it hardbreaks Provides the ability to build docutils' line-block nodes if an inline element contains hardbreaks. When a hardbreak is detected as a child of an inline token, a line-block will be created and child tokens will be rendered into a prepared line node. Child nodes are placed into a line node until the next hardbreak is detected, where a new line node is created to hold the next child set. The process repeats until all children are processed. Signed-off-by: James Knight --- myst_parser/mdit_to_docutils/base.py | 53 +++++++++++++++---- .../fixtures/docutil_syntax_elements.md | 11 ++-- .../fixtures/sphinx_syntax_elements.md | 11 ++-- 3 files changed, 53 insertions(+), 22 deletions(-) diff --git a/myst_parser/mdit_to_docutils/base.py b/myst_parser/mdit_to_docutils/base.py index 520a3c80..8bfcd912 100644 --- a/myst_parser/mdit_to_docutils/base.py +++ b/myst_parser/mdit_to_docutils/base.py @@ -392,15 +392,19 @@ def current_node_context( def render_children(self, token: SyntaxTreeNode) -> None: """Render the children of a token.""" for child in token.children or []: - if f"render_{child.type}" in self.rules: - self.rules[f"render_{child.type}"](child) - else: - self.create_warning( - f"No render method for: {child.type}", - MystWarnings.RENDER_METHOD, - line=token_line(child, default=0), - append_to=self.current_node, - ) + self.render_token(child) + + def render_token(self, token: SyntaxTreeNode) -> None: + """Render a token.""" + if f"render_{token.type}" in self.rules: + self.rules[f"render_{token.type}"](token) + else: + self.create_warning( + f"No render method for: {token.type}", + MystWarnings.RENDER_METHOD, + line=token_line(token, default=0), + append_to=self.current_node, + ) def add_line_and_source_path(self, node, token: SyntaxTreeNode) -> None: """Copy the line number and document source path to the docutils node.""" @@ -526,7 +530,36 @@ def render_paragraph(self, token: SyntaxTreeNode) -> None: self.render_children(token) def render_inline(self, token: SyntaxTreeNode) -> None: - self.render_children(token) + needs_lineblock = False + for child in token.children or []: + if child.type == "hardbreak": + needs_lineblock = True + break + + if not needs_lineblock: + self.render_children(token) + return + + # if we have any hard breaks, we will build a line block and + # prepare line nodes for each group of children between these + # breaks + lineblock = nodes.line_block() + self.add_line_and_source_path(lineblock, token) + self.current_node.append(lineblock) + + current_line = nodes.line() + self.add_line_and_source_path(current_line, token) + lineblock.append(current_line) + + for child in token.children or []: + if child.type == "hardbreak": + current_line = nodes.line() + self.add_line_and_source_path(current_line, token) + lineblock.append(current_line) + continue + + with self.current_node_context(current_line): + self.render_token(child) def render_text(self, token: SyntaxTreeNode) -> None: self.current_node.append(nodes.Text(token.content)) diff --git a/tests/test_renderers/fixtures/docutil_syntax_elements.md b/tests/test_renderers/fixtures/docutil_syntax_elements.md index 6badaa4c..42ab3b10 100644 --- a/tests/test_renderers/fixtures/docutil_syntax_elements.md +++ b/tests/test_renderers/fixtures/docutil_syntax_elements.md @@ -14,12 +14,11 @@ bar . - foo - -
- - \\ - bar + + + foo + + bar . Strong: diff --git a/tests/test_renderers/fixtures/sphinx_syntax_elements.md b/tests/test_renderers/fixtures/sphinx_syntax_elements.md index cdc72b77..756c7183 100644 --- a/tests/test_renderers/fixtures/sphinx_syntax_elements.md +++ b/tests/test_renderers/fixtures/sphinx_syntax_elements.md @@ -14,12 +14,11 @@ bar . - foo - -
- - \\ - bar + + + foo + + bar . Strong: