Skip to content

Commit 86dc085

Browse files
committed
👌 Directive option parsing
1 parent 1f61fa0 commit 86dc085

File tree

14 files changed

+1078
-83
lines changed

14 files changed

+1078
-83
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,5 @@ _archive/
133133

134134
.vscode/
135135
.DS_Store
136+
137+
docs/apidocs

.pre-commit-config.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ exclude: >
66
\.vscode/settings\.json|
77
tests/test_commonmark/commonmark\.json|
88
.*\.xml|
9-
tests/.*/.*\.md
9+
tests/.*/.*\.md|
10+
tests/.*/.*\.yaml
1011
)$
1112
1213
repos:

docs/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
nitpick_ignore_regex = [
8686
(r"py:.*", r"docutils\..*"),
8787
(r"py:.*", r"pygments\..*"),
88+
(r"py:.*", r"typing\.Literal\[.*"),
8889
]
8990
nitpick_ignore = [
9091
("py:obj", "myst_parser._docs._ConfigBase"),

docs/syntax/roles-and-directives.md

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ It is effectively a Markdown code fence with curly brackets around the language,
2323
Here is the basic structure:
2424

2525
`````{list-table}
26-
---
27-
header-rows: 1
28-
---
26+
:header-rows: 1
27+
2928
* - MyST
3029
- reStructuredText
3130
* - ````md
@@ -55,16 +54,13 @@ This is my note
5554
```
5655
:::
5756

58-
#### Parameterizing directives
57+
#### Parameterizing directives (options)
5958

60-
For directives that take parameters as input, there are two ways to parameterize them.
61-
In each case, the options themselves are given as `key: value` pairs. An example of
62-
each is shown below:
59+
Many directives can take key/value pairs, in an optional *option block* at the start of the directive.
6360

64-
**Short-hand options with `:` characters**. If you only need one or two options for your
65-
directive and wish to save lines, you may also specify directive options as a collection
66-
of lines just after the first line of the directive, each preceding with `:`. Then the
67-
leading `:` is removed from each line, and the rest is parsed as YAML.
61+
The option block starts on the first line of the directive body and is defined by a set of lines prefixed with `:`.
62+
63+
The block then follows a YAML-like mapping syntax, where the key (string) and value (string) are separated by a colon (`:`):
6864

6965
:::{myst-example}
7066
```{code-block} python
@@ -77,10 +73,28 @@ print(f'my {a}nd line')
7773
```
7874
:::
7975

80-
**Using YAML frontmatter**. A block of YAML front-matter just after the
81-
first line of the directive will be parsed as options for the directive. This needs to be
82-
surrounded by `---` lines. Everything in between will be parsed by YAML and
83-
passed as keyword arguments to your directive. For example:
76+
Comments, starting `#`, are also allowed in between options or at the end of values, and are ignored.
77+
The values can be enclosed in quotes (`"` or `'`) and span multiple lines.
78+
Newline behaviour can be controlled by starting the value with `|` (preserve newlines) or `>` (collapse newlines):
79+
80+
:::{myst-example}
81+
```{code-block} python
82+
:lineno-start: 10 # this is a comment
83+
: # this is also a comment
84+
:emphasize-lines: "1, 3"
85+
:caption: |
86+
: This is my
87+
: multi-line caption. It is *pretty nifty* ;-)
88+
89+
a = 2
90+
print('my 1st line')
91+
print(f'my {a}nd line')
92+
```
93+
:::
94+
95+
::::{dropdown} Old-style options block
96+
97+
Option blocks can also be enclosed by `---`, with no `:` prefix, for example:
8498

8599
:::{myst-example}
86100
```{code-block} python
@@ -97,6 +111,8 @@ print(f'my {a}nd line')
97111
```
98112
:::
99113

114+
::::
115+
100116
(syntax/directives/parsing)=
101117

102118
#### How directives parse content
@@ -209,9 +225,8 @@ Roles are similar to directives - they allow you to define arbitrary new functio
209225
To define an in-line role, use the following form:
210226

211227
````{list-table}
212-
---
213-
header-rows: 1
214-
---
228+
:header-rows: 1
229+
215230
* - MyST
216231
- reStructuredText
217232
* - ````md

myst_parser/mdit_to_docutils/base.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1741,6 +1741,7 @@ def run_directive(
17411741
directive_class,
17421742
first_line,
17431743
content,
1744+
line=position,
17441745
additional_options=additional_options,
17451746
)
17461747
except MarkupError as error:
@@ -1750,12 +1751,11 @@ def run_directive(
17501751
)
17511752
return [error]
17521753

1753-
if parsed.warnings:
1754-
_errors = ",\n".join(parsed.warnings)
1754+
for warning_msg, warning_line in parsed.warnings:
17551755
self.create_warning(
1756-
f"{name!r}: {_errors}",
1756+
f"{name!r}: {warning_msg}",
17571757
MystWarnings.DIRECTIVE_PARSING,
1758-
line=position,
1758+
line=warning_line if warning_line is not None else position,
17591759
append_to=self.current_node,
17601760
)
17611761

myst_parser/mocking.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def parse_directive_block(
140140
# TODO should argument_str always be ""?
141141
parsed = parse_directive_text(directive, "", "\n".join(content))
142142
if parsed.warnings:
143-
raise MarkupError(",".join(parsed.warnings))
143+
raise MarkupError(",".join(w for w, _ in parsed.warnings))
144144
return (
145145
parsed.arguments,
146146
parsed.options,

0 commit comments

Comments
 (0)