Skip to content

Commit 3c3d21a

Browse files
committed
Allow characters like # and % in section links
1 parent bb43ca1 commit 3c3d21a

File tree

1 file changed

+25
-22
lines changed

1 file changed

+25
-22
lines changed

src/nbsphinx.py

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,7 +1025,7 @@ class ProcessLocalLinks(docutils.transforms.Transform):
10251025

10261026
default_priority = 400 # Should probably be adjusted?
10271027

1028-
_subsection_re = re.compile(r'^(.+)(\..+#.+)$')
1028+
_subsection_re = re.compile(r'^([^#]+)((\.[^#]+)#.+)$')
10291029

10301030
def apply(self):
10311031
env = self.document.settings.env
@@ -1038,27 +1038,30 @@ def apply(self):
10381038
elif uri.startswith('#') or uri.startswith('mailto:'):
10391039
continue # Nothing to be done
10401040

1041-
unquoted_uri = unquote(uri)
1041+
# NB: We look for "fragment identifier" before unquoting
1042+
fragment = self._subsection_re.match(uri)
1043+
uri = unquote(uri)
10421044
for suffix in env.config.source_suffix:
1043-
if unquoted_uri.lower().endswith(suffix.lower()):
1044-
target = unquoted_uri[:-len(suffix)]
1045-
break
1046-
else:
1047-
target = ''
1048-
1049-
subsection_matches = self._subsection_re.match(uri)
1050-
if target:
1051-
target_ext = ''
1052-
reftype = 'doc'
1053-
refdomain = None
1054-
elif subsection_matches:
1055-
target = subsection_matches.group(1)
1056-
target_ext = subsection_matches.group(2)
1057-
reftype = 'ref'
1058-
refdomain = 'std'
1045+
if fragment:
1046+
if fragment.group(3).lower() == suffix.lower():
1047+
target = unquote(fragment.group(1))
1048+
# NB: The "fragment identifier" is not unquoted
1049+
target_ext = fragment.group(2)
1050+
reftype = 'ref'
1051+
refdomain = 'std'
1052+
break
1053+
else:
1054+
if uri.lower().endswith(suffix.lower()):
1055+
target = uri[:-len(suffix)]
1056+
target_ext = ''
1057+
reftype = 'doc'
1058+
refdomain = None
1059+
break
10591060
else:
1061+
if fragment:
1062+
uri = unquote(fragment.group(1)) + fragment.group(3)
10601063
file = os.path.normpath(
1061-
os.path.join(os.path.dirname(env.docname), unquoted_uri))
1064+
os.path.join(os.path.dirname(env.docname), uri))
10621065
if not os.path.isfile(os.path.join(env.srcdir, file)):
10631066
env.app.warn('file not found: {!r}'.format(file),
10641067
env.doc2path(env.docname))
@@ -1076,11 +1079,11 @@ def apply(self):
10761079
target_docname = nbconvert.filters.posix_path(os.path.normpath(
10771080
os.path.join(os.path.dirname(env.docname), target)))
10781081
if target_docname in env.found_docs:
1079-
target = target_docname + target_ext
1080-
target = '/' + target.lower()
1082+
reftarget = target_docname + target_ext
1083+
reftarget = '/' + reftarget.lower()
10811084
linktext = node.astext()
10821085
xref = sphinx.addnodes.pending_xref(
1083-
reftype=reftype, reftarget=target, refdomain=refdomain,
1086+
reftype=reftype, reftarget=reftarget, refdomain=refdomain,
10841087
refwarn=True, refexplicit=True, refdoc=env.docname)
10851088
xref += docutils.nodes.Text(linktext, linktext)
10861089
node.replace_self(xref)

0 commit comments

Comments
 (0)