diff --git a/CHANGES b/CHANGES
index 3115ad944..78bc97b23 100644
--- a/CHANGES
+++ b/CHANGES
@@ -37,6 +37,7 @@ Bugs fixed
possibility to use original meaning in place of Sphinx custom one
* #5834: apidoc: wrong help for ``--tocfile``
* #5800: todo: crashed if todo is defined in TextElement
+* #5846: htmlhelp: convert hex escaping to decimal escaping in .hhc/.hhk files
Testing
--------
diff --git a/sphinx/builders/htmlhelp.py b/sphinx/builders/htmlhelp.py
index 49d48361e..42ee05c4a 100644
--- a/sphinx/builders/htmlhelp.py
+++ b/sphinx/builders/htmlhelp.py
@@ -13,6 +13,7 @@ from __future__ import print_function
import codecs
import os
+import re
from os import path
from docutils import nodes
@@ -27,7 +28,7 @@ from sphinx.util.pycompat import htmlescape
if False:
# For type annotation
- from typing import Any, Dict, IO, List, Tuple # NOQA
+ from typing import Any, Dict, IO, List, Match, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
@@ -169,6 +170,24 @@ chm_locales = {
}
+def chm_htmlescape(*args, **kwargs):
+ # type: (*Any, **Any) -> unicode
+ """
+ chm_htmlescape() is a wrapper of htmlescape().
+ .hhc/.hhk files don't recognize hex escaping, we need convert
+ hex escaping to decimal escaping. for example: `'` -> `'`
+ htmlescape() may generates a hex escaping `'` for single
+ quote `'`, this wrapper fixes this.
+ """
+ def convert(matchobj):
+ # type: (Match[unicode]) -> unicode
+ codepoint = int(matchobj.group(1), 16)
+ return '%d;' % codepoint
+ return re.sub(r'[xX]([0-9a-fA-F]+);',
+ convert,
+ htmlescape(*args, **kwargs))
+
+
class HTMLHelpBuilder(StandaloneHTMLBuilder):
"""
Builder that also outputs Windows HTML help project, contents and
@@ -278,7 +297,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
write_toc(subnode, ullevel)
elif isinstance(node, nodes.reference):
link = node['refuri']
- title = htmlescape(node.astext()).replace('"', '"')
+ title = chm_htmlescape(node.astext()).replace('"', '"')
f.write(object_sitemap % (title, link))
elif isinstance(node, nodes.bullet_list):
if ullevel != 0:
@@ -311,7 +330,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
item = ' \n' % \
(name, value)
f.write(item)
- title = htmlescape(title)
+ title = chm_htmlescape(title)
f.write('