Skip to content

Commit 4ce57f9

Browse files
authored
👌 Stop directive-option parsing at colon fences (#1133)
In order to determine a directive option block, we look for all lines at the top of the directive that begin with `:`. However, this failed for a nested colon fence like: ``` ::::{note} :class: abc :::{note} content ::: :::: ``` This adds a check to terminate the option block when a line starts with 3 or more colons. closes #963
1 parent cfcc327 commit 4ce57f9

2 files changed

Lines changed: 11 additions & 1 deletion

File tree

myst_parser/parsers/directives.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,10 @@ def _parse_directive_options(
192192
content_lines = content.splitlines()
193193
yaml_lines = []
194194
while content_lines:
195-
if not content_lines[0].lstrip().startswith(":"):
195+
stripped = content_lines[0].lstrip()
196+
# Stop at lines that don't start with a colon or have 3+ colons, which are colon fences
197+
# (e.g. nested directives like `::::{other}`)
198+
if not stripped.startswith(":") or stripped.startswith(":::"):
196199
break
197200
yaml_lines.append(content_lines.pop(0).lstrip()[1:])
198201
options_block = "\n".join(yaml_lines)

tests/test_renderers/test_parse_directives.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,10 @@ def test_additional_options():
120120
)
121121
assert len(result.warnings) == 1
122122
assert "Unknown option" in result.warnings[0].msg
123+
124+
125+
def test_colon_options_stop_at_colon_fence():
126+
"""Options parsing should stop when encountering a colon fence (3+ colons)."""
127+
result = parse_directive_text(Note, "", ":class: xxx\n::::{other}\ncontent\n::::")
128+
assert result.options == {"class": ["xxx"]}
129+
assert result.body == ["::::{other}", "content", "::::"]

0 commit comments

Comments
 (0)