Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

👌 IMPROVE: Directive option parsing #796

Merged
merged 1 commit into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,5 @@ _archive/

.vscode/
.DS_Store

docs/apidocs
3 changes: 2 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ exclude: >
\.vscode/settings\.json|
tests/test_commonmark/commonmark\.json|
.*\.xml|
tests/.*/.*\.md
tests/.*/.*\.md|
tests/.*/.*\.yaml
)$

repos:
Expand Down
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
nitpick_ignore_regex = [
(r"py:.*", r"docutils\..*"),
(r"py:.*", r"pygments\..*"),
(r"py:.*", r"typing\.Literal\[.*"),
]
nitpick_ignore = [
("py:obj", "myst_parser._docs._ConfigBase"),
Expand Down
51 changes: 33 additions & 18 deletions docs/syntax/roles-and-directives.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ It is effectively a Markdown code fence with curly brackets around the language,
Here is the basic structure:

`````{list-table}
---
header-rows: 1
---
:header-rows: 1

* - MyST
- reStructuredText
* - ````md
Expand Down Expand Up @@ -55,16 +54,13 @@ This is my note
```
:::

#### Parameterizing directives
#### Parameterizing directives (options)

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

**Short-hand options with `:` characters**. If you only need one or two options for your
directive and wish to save lines, you may also specify directive options as a collection
of lines just after the first line of the directive, each preceding with `:`. Then the
leading `:` is removed from each line, and the rest is parsed as YAML.
The option block starts on the first line of the directive body and is defined by a set of lines prefixed with `:`.

The block then follows a YAML-like mapping syntax, where the key (string) and value (string) are separated by a colon (`:`):

:::{myst-example}
```{code-block} python
Expand All @@ -77,10 +73,28 @@ print(f'my {a}nd line')
```
:::

**Using YAML frontmatter**. A block of YAML front-matter just after the
first line of the directive will be parsed as options for the directive. This needs to be
surrounded by `---` lines. Everything in between will be parsed by YAML and
passed as keyword arguments to your directive. For example:
Comments, starting `#`, are also allowed in between options or at the end of values, and are ignored.
The values can be enclosed in quotes (`"` or `'`) and span multiple lines.
Newline behaviour can be controlled by starting the value with `|` (preserve newlines) or `>` (collapse newlines):

:::{myst-example}
```{code-block} python
:lineno-start: 10 # this is a comment
: # this is also a comment
:emphasize-lines: "1, 3"
:caption: |
: This is my
: multi-line caption. It is *pretty nifty* ;-)

a = 2
print('my 1st line')
print(f'my {a}nd line')
```
:::

::::{dropdown} Old-style options block

Option blocks can also be enclosed by `---`, with no `:` prefix, for example:

:::{myst-example}
```{code-block} python
Expand All @@ -97,6 +111,8 @@ print(f'my {a}nd line')
```
:::

::::

(syntax/directives/parsing)=

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

````{list-table}
---
header-rows: 1
---
:header-rows: 1

* - MyST
- reStructuredText
* - ````md
Expand Down
8 changes: 4 additions & 4 deletions myst_parser/mdit_to_docutils/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1741,6 +1741,7 @@ def run_directive(
directive_class,
first_line,
content,
line=position,
additional_options=additional_options,
)
except MarkupError as error:
Expand All @@ -1750,12 +1751,11 @@ def run_directive(
)
return [error]

if parsed.warnings:
_errors = ",\n".join(parsed.warnings)
for warning_msg, warning_line in parsed.warnings:
self.create_warning(
f"{name!r}: {_errors}",
f"{name!r}: {warning_msg}",
MystWarnings.DIRECTIVE_PARSING,
line=position,
line=warning_line if warning_line is not None else position,
append_to=self.current_node,
)

Expand Down
2 changes: 1 addition & 1 deletion myst_parser/mocking.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@
# TODO should argument_str always be ""?
parsed = parse_directive_text(directive, "", "\n".join(content))
if parsed.warnings:
raise MarkupError(",".join(parsed.warnings))
raise MarkupError(",".join(w for w, _ in parsed.warnings))
return (

Check warning on line 144 in myst_parser/mocking.py

View check run for this annotation

Codecov / codecov/patch

myst_parser/mocking.py#L143-L144

Added lines #L143 - L144 were not covered by tests
parsed.arguments,
parsed.options,
StringList(parsed.body, source=content.source),
Expand Down
Loading