Repository: executablebooks/MyST-Parser

Issue:
Add support for the keys "target" and "rel" in inline_attrs 
### Describe the feature you'd like to request

I would like to be able to create a link that, when clicked, opens in a new tab.

I found that [in the documentation](https://myst-parser.readthedocs.io/en/latest/syntax/optional.html#syntax-attributes), "only certain key-value attributes are supported for each syntax".

### Describe the solution you'd like

I would like `[here](example.md){target="_blank" rel="noreferer noopener"}` to work.

### Describe alternatives you've considered

My workaround is to directly use `<a href="example.html" target="_blank" rel="noreferer noopener">`

Discussion:
welcome[bot]: Thanks for submitting your first pull request! You are awesome! :hugs:
<br>If you haven't done so already, check out [EBP's Code of Conduct](https://github.com/executablebooks/.github/blob/master/CODE_OF_CONDUCT.md) and our [Contributing Guide](https://github.com/executablebooks/.github/blob/master/CONTRIBUTING.md), as this will greatly help the review process.
<br>Welcome to the EBP community! :tada:

marjus45: Thanks a lot for the pointer @chrisjsewell . I updated my commit with a couple of tests for these features. Please let me know if that will suffice!
codecov-commenter: ## [Codecov](https://app.codecov.io/gh/executablebooks/MyST-Parser/pull/857?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 90.10%. Comparing base [(`abcc087`)](https://app.codecov.io/gh/executablebooks/MyST-Parser/commit/abcc0877733f8c8a85106082033b59c531e7539c?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks) to head [(`06a63f3`)](https://app.codecov.io/gh/executablebooks/MyST-Parser/pull/857?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks).


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master     #857      +/-   ##
==========================================
+ Coverage   90.09%   90.10%   +0.01%     
==========================================
  Files          24       24              
  Lines        3372     3377       +5     
==========================================
+ Hits         3038     3043       +5     
  Misses        334      334              
```

| [Flag](https://app.codecov.io/gh/executablebooks/MyST-Parser/pull/857/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks) | Coverage Δ | |
|---|---|---|
| [pytests](https://app.codecov.io/gh/executablebooks/MyST-Parser/pull/857/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks) | `90.10% <100.00%> (+0.01%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks#carryforward-flags-in-the-pull-request-comment) to find out more.


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/executablebooks/MyST-Parser/pull/857?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks).


Patch:
diff --git a/myst_parser/config/main.py b/myst_parser/config/main.py
index aa36193..f5174f2 100644
--- a/myst_parser/config/main.py
+++ b/myst_parser/config/main.py
@@ -234,6 +234,14 @@ class MdParserConfig:
         },
     )
 
+    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 2b3cbd2..4733dea 100644
--- a/myst_parser/mdit_to_docutils/base.py
+++ b/myst_parser/mdit_to_docutils/base.py
@@ -953,8 +953,12 @@ class DocutilsRenderer(RendererProtocol):
         """
         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


Test patch:
diff --git a/tests/test_renderers/fixtures/myst-config.txt b/tests/test_renderers/fixtures/myst-config.txt
index 52f5487..765b010 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"}
 .
 <document source="<string>">
     <paragraph>
@@ -319,6 +323,12 @@ a
     <paragraph>
         <reference classes="e f" ids="id3" names="id3" refuri="https://example.com">
             ref
+    <paragraph>
+        <reference refuri="https://example.com" target="g">
+            text3
+    <paragraph>
+        <reference refuri="https://example.com" rel="h">
+            text4
 .
 
 [attrs_inline_image] --myst-enable-extensions=attrs_inline
@@ -507,3 +517,13 @@ content
 <string>:1: (WARNING/2) Unknown directive type: 'unknown' [myst.directive_unknown]
 <string>: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)
+.
+<document source="<string>">
+    <paragraph>
+        <reference refuri="https://example.com" rel="noreferer noopener" target="_blank">
+            text
+.