From 1151bee6c679213619d57169692395ed61e24d67 Mon Sep 17 00:00:00 2001
From: Samson Umezulike
Date: Sat, 4 May 2024 15:42:26 +0200
Subject: [PATCH] :bug: FIX: Double encoding ampersand in query params
---
myst_parser/parsers/docutils_.py | 14 ++++++++++++++
tests/test_sphinx/sourcedirs/references/index.md | 2 ++
.../test_sphinx_builds/test_references.html | 5 +++++
.../test_references.resolved.xml | 3 +++
.../test_sphinx_builds/test_references.xml | 3 +++
5 files changed, 27 insertions(+)
diff --git a/myst_parser/parsers/docutils_.py b/myst_parser/parsers/docutils_.py
index 1b7a33bb..6d151067 100644
--- a/myst_parser/parsers/docutils_.py
+++ b/myst_parser/parsers/docutils_.py
@@ -1,5 +1,6 @@
"""MyST Markdown parser for docutils."""
+import re
from dataclasses import Field
from typing import (
Any,
@@ -268,6 +269,10 @@ def parse(self, inputstring: str, document: nodes.document) -> None:
HTMLTranslator.depart_rubric = depart_rubric_html
HTMLTranslator.visit_container = visit_container_html
HTMLTranslator.depart_container = depart_container_html
+ HTMLTranslator.special_chars_no_amp = { # needed by encode_fixed
+ k: v for k, v in HTMLTranslator.special_characters.items() if k != ord("&")
+ }
+ HTMLTranslator.encode = encode_fixed
self.setup_parse(inputstring, document)
@@ -515,3 +520,12 @@ def depart_container_html(self, node: nodes.Node):
See explanation in `visit_container_html`
"""
self.body.append("\n")
+
+
+def encode_fixed(self, text: str):
+ """Override the default encode method to prevent `&` characters from getting encoded
+ multiple times.
+ """
+ text = str(text)
+ translated = text.translate(self.special_chars_no_amp)
+ return re.sub(r"(&)(?!amp;)", "&", translated)
diff --git a/tests/test_sphinx/sourcedirs/references/index.md b/tests/test_sphinx/sourcedirs/references/index.md
index 5255b475..88bd5d8d 100644
--- a/tests/test_sphinx/sourcedirs/references/index.md
+++ b/tests/test_sphinx/sourcedirs/references/index.md
@@ -8,6 +8,8 @@
[nested *syntax*](https://example.com)
+[query params](https://example.com?foo=bar&a=1)
+
[](title)
[plain text](title)
diff --git a/tests/test_sphinx/test_sphinx_builds/test_references.html b/tests/test_sphinx/test_sphinx_builds/test_references.html
index 35d1aed7..bd869164 100644
--- a/tests/test_sphinx/test_sphinx_builds/test_references.html
+++ b/tests/test_sphinx/test_sphinx_builds/test_references.html
@@ -33,6 +33,11 @@
+
+
+ query params
+
+
diff --git a/tests/test_sphinx/test_sphinx_builds/test_references.resolved.xml b/tests/test_sphinx/test_sphinx_builds/test_references.resolved.xml
index f832d049..1ab7d58e 100644
--- a/tests/test_sphinx/test_sphinx_builds/test_references.resolved.xml
+++ b/tests/test_sphinx/test_sphinx_builds/test_references.resolved.xml
@@ -18,6 +18,9 @@
nested
syntax
+
+
+ query params
diff --git a/tests/test_sphinx/test_sphinx_builds/test_references.xml b/tests/test_sphinx/test_sphinx_builds/test_references.xml
index 4968ca2f..ac798aaa 100644
--- a/tests/test_sphinx/test_sphinx_builds/test_references.xml
+++ b/tests/test_sphinx/test_sphinx_builds/test_references.xml
@@ -18,6 +18,9 @@
nested
syntax
+
+
+ query params