diff --git a/myst_parser/config/main.py b/myst_parser/config/main.py index aa361931..f5174f2b 100644 --- a/myst_parser/config/main.py +++ b/myst_parser/config/main.py @@ -234,6 +234,14 @@ def __repr__(self) -> str: }, ) + links_external_new_tab: bool = dc.field( + default=False, + metadata={ + "validator": instance_of(bool), + "help": "Open all external links in a new tab", + }, + ) + url_schemes: Dict[str, Optional[UrlSchemeType]] = dc.field( default_factory=lambda: { "http": None, diff --git a/myst_parser/mdit_to_docutils/base.py b/myst_parser/mdit_to_docutils/base.py index 2b3cbd2a..4733dead 100644 --- a/myst_parser/mdit_to_docutils/base.py +++ b/myst_parser/mdit_to_docutils/base.py @@ -953,8 +953,12 @@ def render_link_url( """ ref_node = nodes.reference() self.add_line_and_source_path(ref_node, token) + attribute_keys = ["class", "id", "reftitle", "target", "rel"] + if self.md_config.links_external_new_tab: + token.attrs["target"] = "_blank" + token.attrs["rel"] = "noreferer noopener" self.copy_attributes( - token, ref_node, ("class", "id", "reftitle"), aliases={"title": "reftitle"} + token, ref_node, attribute_keys, aliases={"title": "reftitle"} ) uri = cast(str, token.attrGet("href") or "") implicit_text: str | None = None diff --git a/tests/test_renderers/fixtures/myst-config.txt b/tests/test_renderers/fixtures/myst-config.txt index 52f54878..765b0108 100644 --- a/tests/test_renderers/fixtures/myst-config.txt +++ b/tests/test_renderers/fixtures/myst-config.txt @@ -301,6 +301,10 @@ a [ref]{#id3 .e .f} [ref]: https://example.com + +[text3](https://example.com){target="g"} + +[text4](https://example.com){rel="h"} . @@ -319,6 +323,12 @@ a ref + + + text3 + + + text4 . [attrs_inline_image] --myst-enable-extensions=attrs_inline @@ -507,3 +517,13 @@ content :1: (WARNING/2) Unknown directive type: 'unknown' [myst.directive_unknown] :6: (WARNING/2) 'admonition': Unknown option keys: ['a'] (allowed: ['class', 'name']) [myst.directive_option] . + +[links-external-new-tab] --myst-links-external-new-tab="true" +. +[text](https://example.com) +. + + + + text +.