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

✨ NEW: Add myst_title_to_header configuration #492

Merged
merged 5 commits into from
Jan 9, 2022
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
3 changes: 3 additions & 0 deletions docs/sphinx/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ To do so, use the keywords beginning `myst_`.
* - `myst_linkify_fuzzy_links`
- `True`
- If `False`, only links that contain a scheme (such as `http`) will be recognised as external links.
* - `myst_title_to_header`
- `False`
- If `True`, the `title` key of a document front-matter is converted to a header at the top of the document.
* - `myst_heading_anchors`
- `None`
- Enable auto-generated heading anchors, up to a maximum level, [see here](syntax/header-anchors) for details.
Expand Down
20 changes: 19 additions & 1 deletion docs/syntax/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -398,9 +398,27 @@ This is a YAML block at the start of the document, as used for example in

:::{seealso}
Top-matter is also used for the [substitution syntax extension](syntax/substitutions),
and can be used to store information for blog posting (see [ablog's myst-parser support](https://ablog.readthedocs.io/manual/markdown/)).
and can be used to store information for blog posting (see [ablog's myst-parser support](https://ablog.readthedocs.io/en/latest/manual/markdown/)).
:::

### Setting a title

If `myst_title_to_header` is set to `True`, and a `title` key is present in the front matter,
then the title will be used as the document's header (parsed as Markdown.
For example:

```md
---
title: My Title with *emphasis*
---
```

would be equivalent to:

```md
# My Title with *emphasis*
```

(syntax/html_meta)=

### Setting HTML Metadata
Expand Down
3 changes: 3 additions & 0 deletions myst_parser/docutils_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,9 @@ def render_front_matter(self, token: SyntaxTreeNode) -> None:
)
)

if data.get("title") and self.md_config.title_to_header:
self.nested_render_text(f"# {data['title']}", 0)

def dict_to_fm_field_list(
self, data: Dict[str, Any], language_code: str, line: int = 0
) -> nodes.field_list:
Expand Down
9 changes: 9 additions & 0 deletions myst_parser/main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
"""This module holds the global configuration for the parser ``MdParserConfig``,
and the ``create_md_parser`` function, which creates a parser from the config.
"""
from typing import Any, Callable, Dict, Iterable, Optional, Sequence, Tuple, Union, cast

import attr
Expand Down Expand Up @@ -146,6 +149,12 @@ def check_extensions(self, attribute, value):
metadata={"help": "Add line numbers to code blocks with these languages"},
)

title_to_header: bool = attr.ib(
default=False,
validator=instance_of(bool),
metadata={"help": "Convert a `title` field in the top-matter to a H1 header"},
)

heading_anchors: Optional[int] = attr.ib(
default=None,
validator=optional(in_([1, 2, 3, 4, 5, 6, 7])),
Expand Down
26 changes: 26 additions & 0 deletions tests/test_renderers/fixtures/myst-config.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[title-to-header] --myst-title-to-header="yes"
.
---
title: "The title *nested syntax*"
---

# Other header
.
<document source="<string>">
<docinfo>
<field classes="title">
<field_name>
title
<field_body>
<paragraph>
<literal>
The title *nested syntax*
<section ids="the-title-nested-syntax" names="the\ title\ nested\ syntax">
<title>
The title
<emphasis>
nested syntax
<section ids="other-header" names="other\ header">
<title>
Other header
.
1 change: 1 addition & 0 deletions tests/test_renderers/test_error_reporting.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Tests of the warning reporting for different MyST Markdown inputs."""
from io import StringIO
from pathlib import Path

Expand Down
34 changes: 34 additions & 0 deletions tests/test_renderers/test_myst_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Test (docutils) parsing with different ``MdParserConfig`` options set."""
import shlex
from io import StringIO
from pathlib import Path

from docutils.core import Publisher, publish_doctree
from pytest_param_files import with_parameters

from myst_parser.docutils_ import Parser

FIXTURE_PATH = Path(__file__).parent.joinpath("fixtures")


@with_parameters(FIXTURE_PATH / "myst-config.txt")
def test_cmdline(file_params):
"""The description is parsed as a docutils commandline"""
pub = Publisher(parser=Parser())
option_parser = pub.setup_option_parser()
try:
settings = option_parser.parse_args(
shlex.split(file_params.description)
).__dict__
except Exception as err:
raise AssertionError(
f"Failed to parse commandline: {file_params.description}\n{err}"
)
report_stream = StringIO()
settings["warning_stream"] = report_stream
doctree = publish_doctree(
file_params.content,
parser=Parser(),
settings_overrides=settings,
)
file_params.assert_expected(doctree.pformat(), rstrip_lines=True)