diff --git a/EXAMPLES b/EXAMPLES index 0b2de95d9..6bf6d0e31 100644 --- a/EXAMPLES +++ b/EXAMPLES @@ -141,6 +141,7 @@ Documentation using the nature theme Documentation using another builtin theme ----------------------------------------- +* Arcade: http://arcade.academy/ (sphinx_rtd_theme) * Breathe: https://breathe.readthedocs.io/ (haiku) * MPipe: https://vmlaker.github.io/mpipe/ (sphinx13) * NLTK: http://www.nltk.org/ (agogo) diff --git a/doc/config.rst b/doc/config.rst index 62c4ccc73..2ca622211 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -1624,10 +1624,15 @@ These options influence LaTeX output. See further :doc:`latex`. .. confval:: latex_toplevel_sectioning This value determines the topmost sectioning unit. It should be chosen from - ``part``, ``chapter`` or ``section``. The default is ``None``; the topmost - sectioning unit is switched by documentclass. ``section`` is used if + ``'part'``, ``'chapter'`` or ``'section'``. The default is ``None``; + the topmost + sectioning unit is switched by documentclass: ``section`` is used if documentclass will be ``howto``, otherwise ``chapter`` will be used. + Note that if LaTeX uses ``\part`` command, then the numbering of sectioning + units one level deep gets off-sync with HTML numbering, because LaTeX + numbers continuously ``\chapter`` (or ``\section`` for ``howto``.) + .. versionadded:: 1.4 .. confval:: latex_appendices diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 751aabf4e..26a1b904e 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -49,6 +49,8 @@ BEGIN_DOC = r''' URI_SCHEMES = ('mailto:', 'http:', 'https:', 'ftp:') SECNUMDEPTH = 3 +LATEXSECTIONNAMES = ["part", "chapter", "section", "subsection", + "subsubsection", "paragraph", "subparagraph"] DEFAULT_SETTINGS = { 'latex_engine': 'pdflatex', @@ -501,8 +503,6 @@ def rstdim_to_latexdim(width_str): class LaTeXTranslator(nodes.NodeVisitor): - sectionnames = ["part", "chapter", "section", "subsection", - "subsubsection", "paragraph", "subparagraph"] ignore_missing_images = False @@ -532,16 +532,6 @@ class LaTeXTranslator(nodes.NodeVisitor): self.compact_list = 0 self.first_param = 0 - # determine top section level - if builder.config.latex_toplevel_sectioning: - self.top_sectionlevel = \ - self.sectionnames.index(builder.config.latex_toplevel_sectioning) - else: - if document.settings.docclass == 'howto': - self.top_sectionlevel = 2 - else: - self.top_sectionlevel = 1 - # sort out some elements self.elements = DEFAULT_SETTINGS.copy() self.elements.update(ADDITIONAL_SETTINGS.get(builder.config.latex_engine, {})) @@ -562,11 +552,32 @@ class LaTeXTranslator(nodes.NodeVisitor): self.elements.update({ 'releasename': _('Release'), }) + if builder.config.latex_keep_old_macro_names: + self.elements['sphinxpkgoptions'] = '' + + # we assume LaTeX class provides \chapter command except in case + # of non-Japanese 'howto' case + self.sectionnames = LATEXSECTIONNAMES[:] if document.settings.docclass == 'howto': docclass = builder.config.latex_docclass.get('howto', 'article') + if docclass[0] == 'j': # Japanese class... + pass + else: + self.sectionnames.remove('chapter') else: docclass = builder.config.latex_docclass.get('manual', 'report') self.elements['docclass'] = docclass + + # determine top section level + self.top_sectionlevel = 1 + if builder.config.latex_toplevel_sectioning: + try: + self.top_sectionlevel = \ + self.sectionnames.index(builder.config.latex_toplevel_sectioning) + except ValueError: + logger.warning('unknown %r toplevel_sectioning for class %r' % + (builder.config.latex_toplevel_sectioning, docclass)) + if builder.config.today: self.elements['date'] = builder.config.today else: @@ -629,21 +640,23 @@ class LaTeXTranslator(nodes.NodeVisitor): usepackages = (declare_package(*p) for p in builder.usepackages) self.elements['usepackages'] += "\n".join(usepackages) if document.get('tocdepth'): - # redece tocdepth if `part` or `chapter` is used for top_sectionlevel + # reduce tocdepth if `part` or `chapter` is used for top_sectionlevel # tocdepth = -1: show only parts # tocdepth = 0: show parts and chapters # tocdepth = 1: show parts, chapters and sections # tocdepth = 2: show parts, chapters, sections and subsections # ... + tocdepth = document['tocdepth'] + self.top_sectionlevel - 2 - maxdepth = len(self.sectionnames) - self.top_sectionlevel - if tocdepth > maxdepth: + if len(self.sectionnames) < 7 and self.top_sectionlevel > 0: + tocdepth += 1 # because top_sectionlevel is shifted by -1 + if tocdepth > 5: # 5 corresponds to subparagraph logger.warning('too large :maxdepth:, ignored.') - tocdepth = maxdepth + tocdepth = 5 self.elements['tocdepth'] = '\\setcounter{tocdepth}{%d}' % tocdepth if tocdepth >= SECNUMDEPTH: - # Increase secnumdepth if tocdepth is depther than default SECNUMDEPTH + # Increase secnumdepth if tocdepth is deeper than default SECNUMDEPTH self.elements['secnumdepth'] = '\\setcounter{secnumdepth}{%d}' % tocdepth if getattr(document.settings, 'contentsname', None): diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index b78bcf637..bf6082705 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -712,20 +712,16 @@ def test_latex_logo_if_not_found(app, status, warning): assert isinstance(exc, SphinxError) -@pytest.mark.sphinx('latex', testroot='toctree-maxdepth', - confoverrides={'latex_documents': [ - ('index', 'SphinxTests.tex', 'Sphinx Tests Documentation', - 'Georg Brandl', 'manual'), - ]}) +@pytest.mark.sphinx('latex', testroot='toctree-maxdepth') def test_toctree_maxdepth_manual(app, status, warning): app.builder.build_all() - result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8') + result = (app.outdir / 'Python.tex').text(encoding='utf8') print(result) print(status.getvalue()) print(warning.getvalue()) assert '\\setcounter{tocdepth}{1}' in result assert '\\setcounter{secnumdepth}' not in result - + assert '\\chapter{Foo}' in result @pytest.mark.sphinx( 'latex', testroot='toctree-maxdepth', @@ -741,7 +737,7 @@ def test_toctree_maxdepth_howto(app, status, warning): print(warning.getvalue()) assert '\\setcounter{tocdepth}{2}' in result assert '\\setcounter{secnumdepth}' not in result - + assert '\\section{Foo}' in result @pytest.mark.sphinx( 'latex', testroot='toctree-maxdepth', @@ -754,7 +750,7 @@ def test_toctree_not_found(app, status, warning): print(warning.getvalue()) assert '\\setcounter{tocdepth}' not in result assert '\\setcounter{secnumdepth}' not in result - + assert '\\chapter{Foo A}' in result @pytest.mark.sphinx( 'latex', testroot='toctree-maxdepth', @@ -804,6 +800,26 @@ def test_latex_toplevel_sectioning_is_part(app, status, warning): print(status.getvalue()) print(warning.getvalue()) assert '\\part{Foo}' in result + assert '\\chapter{Foo A}' in result + assert '\\chapter{Foo B}' in result + + +@pytest.mark.sphinx( + 'latex', testroot='toctree-maxdepth', + confoverrides={'latex_toplevel_sectioning': 'part', + 'latex_documents': [ + ('index', 'Python.tex', 'Sphinx Tests Documentation', + 'Georg Brandl', 'howto') + ]}) +def test_latex_toplevel_sectioning_is_part_with_howto(app, status, warning): + app.builder.build_all() + result = (app.outdir / 'Python.tex').text(encoding='utf8') + print(result) + print(status.getvalue()) + print(warning.getvalue()) + assert '\\part{Foo}' in result + assert '\\section{Foo A}' in result + assert '\\section{Foo B}' in result @pytest.mark.sphinx( @@ -818,6 +834,22 @@ def test_latex_toplevel_sectioning_is_chapter(app, status, warning): assert '\\chapter{Foo}' in result +@pytest.mark.sphinx( + 'latex', testroot='toctree-maxdepth', + confoverrides={'latex_toplevel_sectioning': 'chapter', + 'latex_documents': [ + ('index', 'Python.tex', 'Sphinx Tests Documentation', + 'Georg Brandl', 'howto') + ]}) +def test_latex_toplevel_sectioning_is_chapter_with_howto(app, status, warning): + app.builder.build_all() + result = (app.outdir / 'Python.tex').text(encoding='utf8') + print(result) + print(status.getvalue()) + print(warning.getvalue()) + assert '\\section{Foo}' in result + + @pytest.mark.sphinx( 'latex', testroot='toctree-maxdepth', confoverrides={'latex_toplevel_sectioning': 'section'})