sphinx-doc / sphinx

The Sphinx documentation generator
https://www.sphinx-doc.org/
Other
6.63k stars 2.13k forks source link

Broken HTML rendering of index entry that contains a semicolon #8904

Open pmoura opened 3 years ago

pmoura commented 3 years ago

Describe the bug I'm generating documentation for a Prolog system implementation using Sphinx. The Prolog language includes conjunction and disjunction control constructs that are represented by, respectively, the compound terms (';')/2, (,)/2, and !/0. The index entries for these control constructs must contain this exact text.

But the following index directives don't generate correct entries due to the presence of the comma, semicolon, and exclamation mark:

.. index:: (;)/2

.. index:: (',')/2

.. index:: !/0

For the first two cases, a solution was mentioned in StackOverflow related question (https://stackoverflow.com/questions/66229133/escaping-special-characters-in-index-directives) :

.. index:: single: (',')/2

.. index:: single: !/0

But this solution doesn't work for the (';')/2. Instead, I get (using the HTML render):

      <li>
    (

      <ul>
        <li><a href="my_index.html#index-1">)/2</a>
</li>
      </ul></li>

Also tried to use a backslash for escaping the semicolon to no avail. As mentioned in the SO answer, the use of single: work if the text that follows consists only of the semicolon.

To Reproduce The bug handling text that include a semicolon as an index entry can be reproduced using either:

.. index:: (;)/2

or:

.. index:: single: (;)/2

Expected behavior A well formatted index entry showing as text (';')/2.

Your project The bug is found in a private company project.

Screenshots (none)

Environment info

Additional context StackOverflow related question and answer with further discussion: https://stackoverflow.com/questions/66229133/escaping-special-characters-in-index-directives

KaKkouo commented 3 years ago

It seems to depend on split_into function

sphinx/util/init.py ( Sphinx 4.2.0 )

365
366 def split_into(n: int, type: str, value: str) -> List[str]:
367     """Split an index entry into a given number of parts at semicolons."""
368     parts = [x.strip() for x in value.split(';', n - 1)]
369     if sum(1 for part in parts if part) < n:
370         raise ValueError('invalid %s index entry %r' % (type, value))
371     return parts
372

sphinx/environment/adapters/indexentries.py ( Sphinx 4.2.0 )

 58             for type, value, tid, main, index_key in entries:
 59                 try:
 60                     if type == 'single':
 61                         try:
 62                             entry, subentry = split_into(2, 'single', value)
 63                         except ValueError:
 64                             entry, = split_into(1, 'single', value)
 65                             subentry = ''
 66                         add_entry(entry, subentry, main, key=index_key)
 67                     elif type == 'pair':
 68                         first, second = split_into(2, 'pair', value)
 69                         add_entry(first, second, main, key=index_key)
 70                         add_entry(second, first, main, key=index_key)
 71                     elif type == 'triple':
 72                         first, second, third = split_into(3, 'triple', value)
 73                         add_entry(first, second + ' ' + third, main, key=index_key)
 74                         add_entry(second, third + ', ' + first, main, key=index_key)
 75                         add_entry(third, first + ' ' + second, main, key=index_key)
 76                     elif type == 'see':
 77                         first, second = split_into(2, 'see', value)
 78                         add_entry(first, _('see %s') % second, None,
 79                                   link=False, key=index_key)
 80                     elif type == 'seealso':

a sample code

#!/usr/bin/python

a = "aaa; (;)/2; bbb"

b = a.split(';')
c = a.split('; ')

for e in b: print(e)
for e in c: print(e)

the result of execution

aaa
 (
)/2
 bbb
aaa
(;)/2
bbb
KaKkouo commented 3 years ago

https://www.sphinx-doc.org/en/master/internals/contributing.html

KaKkouo commented 3 years ago

what I did

  1. update the code, and commit.
  2. pip install 4.3.0.dev20211018.
  3. create a new sphinx project and two rst files.
  4. make html and check

rst files

index.rst

.. issue8904 documentation master file, created by
   sphinx-quickstart on Mon Oct 18 12:49:05 2021.
   You can adapt this file completely to your liking, but it should at least
   contain the root `toctree` directive.

Welcome to issue8904's documentation!
=====================================

.. toctree::
   :maxdepth: 2
   :caption: Contents:

   issue8904

Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

issue8904.rst

split_into
==========

.. index::
   single: prolog; (;)/2
   pair: bash; (;)/2
   triple: python; (;)/2; perl

This is a samle rst file.

result('bizstyle')

#8904

KaKkouo commented 3 years ago