Doxygen with :gh:`doxygen/doxygen#623` applied, otherwise the codes will be
present in the rendered output in their raw form.
-`Custom styling`_
------------------
+`Theme-specific commands`_
+--------------------------
It's possible to insert custom m.css classes into the Doxygen output. Add the
following to your ``Doxyfile-mcss``:
"m_enddiv=@xmlonly</mcss:div>@endxmlonly" \
"m_span{1}=@xmlonly<mcss:span xmlns:mcss=\"http://mcss.mosra.cz/doxygen/\" mcss:class=\"\1\">@endxmlonly" \
"m_endspan=@xmlonly</mcss:span>@endxmlonly" \
- "m_class{1}=@xmlonly<mcss:class xmlns:mcss=\"http://mcss.mosra.cz/doxygen/\" mcss:class=\"\1\" />@endxmlonly"
+ "m_class{1}=@xmlonly<mcss:class xmlns:mcss=\"http://mcss.mosra.cz/doxygen/\" mcss:class=\"\1\" />@endxmlonly" \
+ "m_footernavigation=@xmlonly<mcss:footernavigation xmlns:mcss=\"http://mcss.mosra.cz/doxygen/\" />@endxmlonly"
If you need backwards compatibility with stock Doxygen HTML output, just make
the aliases empty in your original ``Doxyfile``. Note that you can rename the
"m_enddiv=" \
"m_span{1}=" \
"m_endspan=" \
- "m_class{1}="
+ "m_class{1}=" \
+ "m_footernavigation="
With ``@m_div`` and ``@m_span`` it's possible to wrap individual paragraphs or
inline text in :html:`<div>` / :html:`<span>` and add CSS classes to them.
See the red :math-danger:`\Sigma` character.
+The ``@m_footernavigation`` command is similar to ``@tableofcontents``, but
+across pages --- if a page is a subpage of some other page and this command is
+present in page detailed description, it will cause the footer of the rendered
+page to contain a link to previous, parent and next page according to defined
+page order.
+
`Customizing the template`_
===========================
:py:`compound.has_template_details` If there is a detailed documentation
of template parameters
:py:`compound.sections` Sections of detailed description. See
- `Section properties`_ for details.
+ `Navigation properties`_ for details.
+:py:`compound.footer_navigation` Footer navigation of a page. See
+ `Navigation properties`_ for details.
:py:`compound.brief` Brief description. Can be empty. [1]_
:py:`compound.description` Detailed description. Can be empty. [2]_
:py:`compound.dirs` List of directories in this compound.
result will be saved
======================================= =======================================
-`Section properties`_
-`````````````````````
+`Navigation properties`_
+````````````````````````
The :py:`compound.sections` property defines a Table of Contents for given
detailed description. It's a list of :py:`(id, title, children)` tuples, where
description either has no sections or the TOC was not explicitly requested via
``@tableofcontents`` in case of pages.
+The :py:`compound.footer_navigation` property defines footer navigation
+requested by the ``@m_footernavigation`` `theme-specific command <#theme-specific-commands>`_.
+If available, it's a tuple of :py:`(prev, up, next)` where each item is a tuple
+of :py:`(url, title)` for a page that's either previous in the defined order,
+one level up or next. For starting/ending page the :py:`prev`/:py:`next` is
+:py:`None`.
+
`Directory properties`_
```````````````````````
out.params = {}
out.return_value = None
out.add_css_class = None
+ out.footer_navigation = False
# DOXYGEN <PARA> PATCHING 1/4
#
# resetting here explicitly.
add_css_class = parsed.add_css_class
+ # Bubble up also the footer navigation
+ if parsed.footer_navigation: out.footer_navigation = True
+
# Assert we didn't miss anything important
assert not parsed.section
else:
add_inline_css_class = i.attrib['{http://mcss.mosra.cz/doxygen/}class']
+ # Enabling footer navigation in a page
+ elif i.tag == '{http://mcss.mosra.cz/doxygen/}footernavigation':
+ out.footer_navigation = True
+
# Either block or inline
elif i.tag == 'programlisting':
assert element.tag == 'para' # is inside a paragraph :/
assert not parsed.return_value
if parsed.params:
logging.warning("Use @tparam instead of @param for documenting class templates, @param is ignored")
- return (parsed.parsed, parsed.templates, parsed.section[2] if parsed.section else '')
+ return (parsed.parsed, parsed.templates, parsed.section[2] if parsed.section else '', parsed.footer_navigation)
def parse_typedef_desc(state: State, element: ET.Element):
# Verify that we didn't ignore any important info by accident
compound.has_template_details = False
compound.templates = None
compound.brief = parse_desc(state, compounddef.find('briefdescription'))
- compound.description, templates, compound.sections = parse_toplevel_desc(state, compounddef.find('detaileddescription'))
+ compound.description, templates, compound.sections, footer_navigation = parse_toplevel_desc(state, compounddef.find('detaileddescription'))
+ compound.footer_navigation = None
compound.dirs = []
compound.files = []
compound.namespaces = []
if compounddef.find('tableofcontents') is None:
compound.sections = []
+ # Enable footer navigation, if requested
+ if footer_navigation:
+ up = state.compounds[compound.id].parent
+
+ # Go through all parent children and
+ if up:
+ up = state.compounds[up]
+
+ prev = None
+ next = None
+ prev_child = None
+ for child in up.children:
+ if child == compound.id:
+ if prev_child: prev = state.compounds[prev_child]
+ elif prev_child == compound.id:
+ next = state.compounds[child]
+ break
+
+ prev_child = child
+
+ compound.footer_navigation = ((prev.url, prev.name) if prev else None,
+ (up.url, up.name),
+ (next.url, next.name) if next else None)
+
if compound.brief:
# Remove duplicated brief in pages. Doxygen sometimes adds a period
# at the end, try without it also.
{% for css in HTML_EXTRA_STYLESHEET %}
<link rel="stylesheet" href="{{ css|basename_or_url|e }}" />
{% endfor %}
+ {% block header_links %}
+ {% endblock %}
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="{{ M_THEME_COLOR }}" />
</head>
{% block title %}{% if 1 in compound.breadcrumb or compound.breadcrumb[-1][0] != PROJECT_NAME %}{% set j = joiner(' » ') %}{% for name, _ in compound.breadcrumb %}{{ j() }}{{ name }}{% endfor %} | {{ super() }}{% else %}{{ super() }}{% endif %}{% endblock %}
+{% block header_links %}
+{% if compound.footer_navigation and compound.footer_navigation[0] %}
+ <link rel="prev" href="{{ compound.footer_navigation[0][0] }}" />
+{% endif %}
+{% if compound.footer_navigation and compound.footer_navigation[2] %}
+ <link rel="next" href="{{ compound.footer_navigation[2][0] }}" />
+{% endif %}
+{% endblock %}
+
{% block main %}
<h1>
{% for name, target in compound.breadcrumb[:-1] %}
</ul>
</div>
{% endif %}
-{% if compound.description %}
+ {% if compound.description %}
{{ compound.description }}
-{% endif %}
+ {% endif %}
+ {% if compound.footer_navigation %}
+ <div class="m-note m-dim m-thin m-text-center">{% if compound.footer_navigation[0] %}<a href="{{ compound.footer_navigation[0][0] }}" class="m-dox">« {{ compound.footer_navigation[0][1] }}</a> | {% endif %}<a href="{{ compound.footer_navigation[1][0] }}" class="m-dox">{{ compound.footer_navigation[1][1] }}</a>{% if compound.footer_navigation[2] %} | <a href="{{ compound.footer_navigation[2][0] }}" class="m-dox">{{ compound.footer_navigation[2][1] }} »</a>{% endif %}</div>
+ {% endif %}
{% endblock %}
"m_enddiv=@xmlonly</mcss:div>@endxmlonly" \
"m_span{1}=@xmlonly<mcss:span xmlns:mcss=\"http://mcss.mosra.cz/doxygen/\" mcss:class=\"\1\">@endxmlonly" \
"m_endspan=@xmlonly</mcss:span>@endxmlonly" \
- "m_class{1}=@xmlonly<mcss:class xmlns:mcss=\"http://mcss.mosra.cz/doxygen/\" mcss:class=\"\1\" />@endxmlonly"
+ "m_class{1}=@xmlonly<mcss:class xmlns:mcss=\"http://mcss.mosra.cz/doxygen/\" mcss:class=\"\1\" />@endxmlonly" \
+ "m_footernavigation=@xmlonly<mcss:footernavigation xmlns:mcss=\"http://mcss.mosra.cz/doxygen/\" />@endxmlonly"
/** @page math Math
+@m_footernavigation
+
A green formula:
@m_class{m-success}
A yellow @m_class{m-warning} @f$ \Sigma @f$ inline formula.
+- @subpage subpage1 First subpage
+- @subpage subpage2 Second subpage
+
+*/
+
+/** @page subpage1 First subpage
+
+@m_footernavigation
+*/
+
+/** @page subpage2 Second subpage
+
+@m_footernavigation
*/
<g id='eq2-page1'>
<use x='0' xlink:href='#eq2-g0-6' y='0'/>
</g>
-</svg> inline formula.</p>
+</svg> inline formula.</p><ul><li><a href="subpage1.html" class="m-dox">First subpage</a> First subpage</li><li><a href="subpage2.html" class="m-dox">Second subpage</a> Second subpage</li></ul>
</div>
</div>
</div>
</div>
</nav></footer>
</body>
-</html>
\ No newline at end of file
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>Math » First subpage | My Project</title>
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
+ <link rel="stylesheet" href="m-dark+doxygen.compiled.css" />
+ <link rel="next" href="subpage2.html" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta name="theme-color" content="#22272e" />
+</head>
+<body>
+<header><nav id="navigation">
+ <div class="m-container">
+ <div class="m-row">
+ <a href="index.html" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">My Project</a>
+ <a id="m-navbar-show" href="#navigation" title="Show navigation" class="m-col-t-3 m-hide-m m-text-right"></a>
+ <a id="m-navbar-hide" href="#" title="Hide navigation" class="m-col-t-3 m-hide-m m-text-right"></a>
+ <div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
+ <div class="m-row">
+ <ol class="m-col-t-6 m-col-m-none">
+ <li><a href="pages.html" id="m-navbar-current">Pages</a></li>
+ <li><a href="namespaces.html">Namespaces</a></li>
+ </ol>
+ <ol class="m-col-t-6 m-col-m-none" start="3">
+ <li><a href="annotated.html">Classes</a></li>
+ <li><a href="files.html">Files</a></li>
+ </ol>
+ </div>
+ </div>
+ </div>
+ </div>
+</nav></header>
+<main><article>
+ <div class="m-container m-container-inflatable">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <h1>
+ <span class="m-breadcrumb"><a href="math.html">Math</a> »</span>
+ First subpage
+ </h1>
+ <div class="m-note m-dim m-thin m-text-center"><a href="math.html" class="m-dox">Math</a> | <a href="subpage2.html" class="m-dox">Second subpage »</a></div>
+ </div>
+ </div>
+ </div>
+</article></main>
+<footer><nav>
+ <div class="m-container">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <p>My Project. Created by <a href="http://doxygen.org/">Doxygen</a> and <a href="http://mcss.mosra.cz/">m.css</a>.</p>
+ </div>
+ </div>
+ </div>
+</nav></footer>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>Math » Second subpage | My Project</title>
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
+ <link rel="stylesheet" href="m-dark+doxygen.compiled.css" />
+ <link rel="prev" href="subpage1.html" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta name="theme-color" content="#22272e" />
+</head>
+<body>
+<header><nav id="navigation">
+ <div class="m-container">
+ <div class="m-row">
+ <a href="index.html" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">My Project</a>
+ <a id="m-navbar-show" href="#navigation" title="Show navigation" class="m-col-t-3 m-hide-m m-text-right"></a>
+ <a id="m-navbar-hide" href="#" title="Hide navigation" class="m-col-t-3 m-hide-m m-text-right"></a>
+ <div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
+ <div class="m-row">
+ <ol class="m-col-t-6 m-col-m-none">
+ <li><a href="pages.html" id="m-navbar-current">Pages</a></li>
+ <li><a href="namespaces.html">Namespaces</a></li>
+ </ol>
+ <ol class="m-col-t-6 m-col-m-none" start="3">
+ <li><a href="annotated.html">Classes</a></li>
+ <li><a href="files.html">Files</a></li>
+ </ol>
+ </div>
+ </div>
+ </div>
+ </div>
+</nav></header>
+<main><article>
+ <div class="m-container m-container-inflatable">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <h1>
+ <span class="m-breadcrumb"><a href="math.html">Math</a> »</span>
+ Second subpage
+ </h1>
+ <div class="m-note m-dim m-thin m-text-center"><a href="subpage1.html" class="m-dox">« First subpage</a> | <a href="math.html" class="m-dox">Math</a></div>
+ </div>
+ </div>
+ </div>
+</article></main>
+<footer><nav>
+ <div class="m-container">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <p>My Project. Created by <a href="http://doxygen.org/">Doxygen</a> and <a href="http://mcss.mosra.cz/">m.css</a>.</p>
+ </div>
+ </div>
+ </div>
+</nav></footer>
+</body>
+</html>
def test_math(self):
self.run_dox2html5(wildcard='math.xml')
self.assertEqual(*self.actual_expected_contents('math.html'))
+
+ def test_footer_navigation(self):
+ self.run_dox2html5(wildcard='subpage*.xml')
+ self.assertEqual(*self.actual_expected_contents('subpage1.html'))
+ self.assertEqual(*self.actual_expected_contents('subpage2.html'))