Repository: executablebooks/mdit-py-plugins

Issue:
Support spaces in labels
### Describe the enhancement you'd like

It would be useful if it were possible to use spaces in labels, like so:

```md
(my label)=
# My header

Ref for [](my label).
```

In https://github.com/executablebooks/meta/discussions/467#discussioncomment-1223602 we discovered that, while reStructuredText supports spaces in labels, like `.. _my label:`, the MyST parser does not.

### Benefit

This would be useful for people who are coming from the rST / Sphinx ecosystem, since this is already supported in rST. However it's probably not a huge number of people using labels this way because most seem to use `-` or `_` for this kind of thing.

### Implementation

The fix for this would probably somewhere around here:

https://github.com/executablebooks/mdit-py-plugins/blob/a0f7ffac84b2eb768a508c2e7a1c286df0c2b56a/mdit_py_plugins/myst_blocks/index.py#L116

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/executablebooks/mdit-py-plugins/pull/31?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks) Report
> Merging [#31](https://codecov.io/gh/executablebooks/mdit-py-plugins/pull/31?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks) (1bd859a) into [master](https://codecov.io/gh/executablebooks/mdit-py-plugins/commit/bb061190339e6e2083e8c192ef8b089bece72c3f?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks) (bb06119) will **decrease** coverage by `0.05%`.
> The diff coverage is `90.90%`.

[![Impacted file tree graph](https://codecov.io/gh/executablebooks/mdit-py-plugins/pull/31/graphs/tree.svg?width=650&height=150&src=pr&token=x2hkFrk2rb&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks)](https://codecov.io/gh/executablebooks/mdit-py-plugins/pull/31?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks)

```diff
@@            Coverage Diff             @@
##           master      #31      +/-   ##
==========================================
- Coverage   93.26%   93.20%   -0.06%     
==========================================
  Files          24       24              
  Lines        1233     1237       +4     
==========================================
+ Hits         1150     1153       +3     
- Misses         83       84       +1     
```

| Flag | Coverage Δ | |
|---|---|---|
| pytests | `93.20% <90.90%> (-0.06%)` | :arrow_down: |

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.

| [Impacted Files](https://codecov.io/gh/executablebooks/mdit-py-plugins/pull/31?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks) | Coverage Δ | |
|---|---|---|
| [mdit\_py\_plugins/myst\_blocks/index.py](https://codecov.io/gh/executablebooks/mdit-py-plugins/pull/31/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks#diff-bWRpdF9weV9wbHVnaW5zL215c3RfYmxvY2tzL2luZGV4LnB5) | `95.55% <90.90%> (-0.96%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/executablebooks/mdit-py-plugins/pull/31?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/executablebooks/mdit-py-plugins/pull/31?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks). Last update [bb06119...1bd859a](https://codecov.io/gh/executablebooks/mdit-py-plugins/pull/31?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks).


Patch:
diff --git a/mdit_py_plugins/myst_blocks/index.py b/mdit_py_plugins/myst_blocks/index.py
index 16baaaa..d0e4cf6 100644
--- a/mdit_py_plugins/myst_blocks/index.py
+++ b/mdit_py_plugins/myst_blocks/index.py
@@ -1,12 +1,9 @@
 import itertools
-import re
 
 from markdown_it import MarkdownIt
 from markdown_it.common.utils import escapeHtml, isSpace
 from markdown_it.rules_block import StateBlock
 
-TARGET_PATTERN = re.compile(r"^\(([a-zA-Z0-9\|\@\<\>\*\.\/\_\-\+\:]{1,100})\)\=\s*$")
-
 
 def myst_block_plugin(md: MarkdownIt):
     """Parse MyST targets (``(name)=``), blockquotes (``% comment``) and block breaks (``+++``)."""
@@ -122,8 +119,12 @@ def target(state: StateBlock, startLine: int, endLine: int, silent: bool):
     if state.sCount[startLine] - state.blkIndent >= 4:
         return False
 
-    match = TARGET_PATTERN.match(state.src[pos:maximum])
-    if not match:
+    text = state.src[pos:maximum].strip()
+    if not text.startswith("("):
+        return False
+    if not text.endswith(")="):
+        return False
+    if not text[1:-2]:
         return False
 
     if silent:
@@ -133,17 +134,17 @@ def target(state: StateBlock, startLine: int, endLine: int, silent: bool):
 
     token = state.push("myst_target", "", 0)
     token.attrSet("class", "myst-target")
-    token.content = match.group(1)
+    token.content = text[1:-2]
     token.map = [startLine, state.line]
 
     return True
 
 
 def render_myst_target(self, tokens, idx, options, env):
-    content = tokens[idx].content
-    return (
-        '<div class="myst-target">' f"target = <code>{escapeHtml(content)}</code></div>"
-    )
+    label = tokens[idx].content
+    class_name = "myst-target"
+    target = f'<a href="#{label}">({label})=</a>'
+    return f'<div class="{class_name}">{target}</div>'
 
 
 def render_myst_line_comment(self, tokens, idx, options, env):


Test patch:
diff --git a/tests/fixtures/myst_block.md b/tests/fixtures/myst_block.md
index 38d0771..90bf9d3 100644
--- a/tests/fixtures/myst_block.md
+++ b/tests/fixtures/myst_block.md
@@ -41,32 +41,58 @@ a
 <hr class="myst-block">
 .
 
-
 Target:
 .
 (a)=
 .
-<div class="myst-target">target = <code>a</code></div>
+<div class="myst-target"><a href="#a">(a)=</a></div>
+.
+
+Target characters:
+.
+(a bc   |@<>*./_-+:)=
+.
+<div class="myst-target"><a href="#a bc   |@<>*./_-+:">(a bc   |@<>*./_-+:)=</a></div>
+.
+
+Empty target:
+.
+()=
+.
+<p>()=</p>
 .
 
+Escaped target:
+.
+\(a)=
+.
+<p>(a)=</p>
+.
+
+Indented target:
+.
+  (a)= 
+.
+<div class="myst-target"><a href="#a">(a)=</a></div>
+.
 
 Target terminates other blocks:
 .
 a
-(a)=
+(a-b)=
 - b
-(a)=
+(a b)=
 > c
 (a)=
 .
 <p>a</p>
-<div class="myst-target">target = <code>a</code></div><ul>
+<div class="myst-target"><a href="#a-b">(a-b)=</a></div><ul>
 <li>b</li>
 </ul>
-<div class="myst-target">target = <code>a</code></div><blockquote>
+<div class="myst-target"><a href="#a b">(a b)=</a></div><blockquote>
 <p>c</p>
 </blockquote>
-<div class="myst-target">target = <code>a</code></div>
+<div class="myst-target"><a href="#a">(a)=</a></div>
 .
 
 Comment: