chiark / gitweb /
documentation/doxygen: support \since as labels in entry lists.
authorVladimír Vondruš <mosra@centrum.cz>
Sat, 16 Nov 2019 22:45:14 +0000 (23:45 +0100)
committerVladimír Vondruš <mosra@centrum.cz>
Sun, 17 Nov 2019 12:40:53 +0000 (13:40 +0100)
Makes everything much easier to discover. Since I'm by far no longer the
only user, I have a fear of breaking things, so this is completely
opt-in.

Also recognizes a combination of \since and \deprecated as "a version in
which given API got deprecated", expanding the red deprecated label with
a custom text.

53 files changed:
doc/documentation/doxygen.rst
documentation/doxygen.py
documentation/templates/doxygen/annotated.html
documentation/templates/doxygen/base-class-reference.html
documentation/templates/doxygen/details-define.html
documentation/templates/doxygen/details-enum.html
documentation/templates/doxygen/details-func.html
documentation/templates/doxygen/details-typedef.html
documentation/templates/doxygen/details-var.html
documentation/templates/doxygen/dir.html
documentation/templates/doxygen/entry-class.html
documentation/templates/doxygen/entry-define.html
documentation/templates/doxygen/entry-dir.html
documentation/templates/doxygen/entry-enum.html
documentation/templates/doxygen/entry-file.html
documentation/templates/doxygen/entry-func.html
documentation/templates/doxygen/entry-module.html
documentation/templates/doxygen/entry-namespace.html
documentation/templates/doxygen/entry-typedef.html
documentation/templates/doxygen/entry-var.html
documentation/templates/doxygen/file.html
documentation/templates/doxygen/files.html
documentation/templates/doxygen/group.html
documentation/templates/doxygen/modules.html
documentation/templates/doxygen/namespace.html
documentation/templates/doxygen/namespaces.html
documentation/templates/doxygen/page.html
documentation/templates/doxygen/pages.html
documentation/test_doxygen/compound_since/Class_8h.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/DeprecatedClass_8h.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/DeprecatedDirectory/DeprecatedClass.h [new file with mode: 0644]
documentation/test_doxygen/compound_since/Directory/Class.h [new file with mode: 0644]
documentation/test_doxygen/compound_since/Doxyfile [new file with mode: 0644]
documentation/test_doxygen/compound_since/a.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/annotated.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/classDeprecatedFoo_1_1DeprecatedClass.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/classFoo_1_1Class.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/deprecated-a.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/dir_4b0d5f8864bf89936129251a2d32609b.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/dir_73d1500434dee6f1c83b12ee799c54af.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/files.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/group__deprecated-group.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/group__group.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/modules.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/namespaceDeprecatedFoo.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/namespaceFoo.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/namespaces.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/pages.dox [new file with mode: 0644]
documentation/test_doxygen/compound_since/pages.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/structDeprecatedFoo_1_1DeprecatedSubclass.html [new file with mode: 0644]
documentation/test_doxygen/compound_since/structFoo_1_1Subclass.html [new file with mode: 0644]
documentation/test_doxygen/test_compound.py
documentation/test_doxygen/test_doxyfile.py

index 9388c3e805e550043464b5ec6767aec49dbd60ef..621abd9eea2e49108769a6fd86302c23c63b191f 100644 (file)
@@ -389,6 +389,10 @@ Variable                            Description
                                     search is offered. See `Search options`_
                                     for more information. Has effect only if
                                     :ini:`M_SEARCH_DISABLED` is not ``YES``.
+:ini:`M_VERSION_LABELS`             Show the ``@since`` annotation as labels
+                                    visible in entry listing and detailed docs.
+                                    Defaults to ``NO``, see `Version labels`_
+                                    for more information.
 :ini:`M_SHOW_UNDOCUMENTED`          Include undocumented symbols, files and
                                     directories in the output. If not set,
                                     ``NO`` is used. See `Showing undocumented symbols and files`_
@@ -1187,6 +1191,52 @@ suffix of the title.
      */
     template<class T> lerp(const T& x, const T& y, float a);
 
+`Version labels`_
+-----------------
+
+By default, to keep compatibility with existing content, the ``@since`` block
+is rendered as a note directly in the text flow. If you enable the
+:ini:`M_SINCE_BADGES` option, content of the ``@since`` block is expected to be
+a single label that can optionally link to a changelog entry. The label is then
+placed visibly next to given entry and detailed description as well as all
+listings. Additionally, if ``@since`` is followed by ``@deprecated``, it adds
+version info to the deprecation notice (instead of denoting when given feature
+was added) --- in this case it expects just a textual info, without any label
+styling. Recommended use is in combination with an alias that takes care of the
+label rendering and  For example (the ``@m_class`` is the same as described in
+`Theme-specific commands`_ above):
+
+.. code:: ini
+
+    M_VERSION_LABELS = YES
+    ALIASES = \
+        "m_class{1}=@xmlonly<mcss:class xmlns:mcss=\"http://mcss.mosra.cz/doxygen/\" mcss:class=\"\1\" />@endxmlonly" \
+        "m_since{2}=@since @m_class{m-label m-success m-flat} @ref changelog-\1-\2 \"since v\1.\2\"" \
+        "m_deprecated_since{2}=@since deprecated in v\1.\2 @deprecated"
+
+With the above configuration, the following markup will render a
+:label-flat-success:`since v1.3` label leading to a page named ``changelog-1-3``
+next to both function entry and detailed docs in the first case, and a
+:label-danger:`deprecated since v1.3` label in the second case:
+
+.. code:: c++
+
+    /**
+    @brief Fast inverse square root
+    @m_since{1,3}
+
+    Faster than `1.0f/sqrt(a)`.
+    */
+    float fastinvsqrt(float a);
+
+    /**
+    @brief Slow inverse square root
+
+    Attempts to figure out the value by a binary search.
+    @m_deprecated_since{1,3} Use @ref fastinvsqrt() instead.
+    */
+    float slowinvsqrt(float a);
+
 `Command-line options`_
 =======================
 
@@ -1471,7 +1521,9 @@ Property                                Description
 :py:`compound.brief`                    Brief description. Can be empty. [1]_
 :py:`compound.is_final`                 Whether the class is :cpp:`final`. Set
                                         only for classes.
-:py:`compound.is_deprecated`            Whether the compound is deprecated. [7]_
+:py:`compound.deprecated`               Deprecation status [7]_
+:py:`compound.since`                    Since which version the compound is
+                                        available [8]_
 :py:`compound.description`              Detailed description. Can be empty. [2]_
 :py:`compound.modules`                  List of submodules in this compound.
                                         Set only for modules. See
@@ -1632,7 +1684,8 @@ Property                    Description
 :py:`module.url`            URL of the file containing detailed module docs
 :py:`module.name`           Module name (just the leaf)
 :py:`module.brief`          Brief description. Can be empty. [1]_
-:py:`module.is_deprecated`  Whether the module is deprecated. [7]_
+:py:`module.deprecated`     Deprecation status [7]_
+:py:`module.since`          Since which version the module is available [8]_
 =========================== ===================================================
 
 `Directory properties`_
@@ -1649,7 +1702,8 @@ Property                    Description
 :py:`dir.url`               URL of the file containing detailed directory docs
 :py:`dir.name`              Directory name (just the leaf)
 :py:`dir.brief`             Brief description. Can be empty. [1]_
-:py:`dir.is_deprecated`     Whether the directory is deprecated. [7]_
+:py:`dir.deprecated`        Deprecation status [7]_
+:py:`dir.since`             Since which version the directory is available [8]_
 =========================== ===================================================
 
 `File properties`_
@@ -1666,7 +1720,8 @@ Property                    Description
 :py:`file.url`              URL of the file containing detailed file docs
 :py:`file.name`             File name (just the leaf)
 :py:`file.brief`            Brief description. Can be empty. [1]_
-:py:`file.is_deprecated`    Whether the file is deprecated. [7]_
+:py:`file.deprecated`       Deprecation status [7]_
+:py:`file.since`            Since which version the file is available [8]_
 =========================== ===================================================
 
 `Namespace properties`_
@@ -1686,7 +1741,9 @@ Property                        Description
                                 a file documentation, just the leaf name if in
                                 a namespace documentation.
 :py:`namespace.brief`           Brief description. Can be empty. [1]_
-:py:`namespace.is_deprecated`   Whether the namespace is deprecated. [7]_
+:py:`namespace.deprecated`      Deprecation status [7]_
+:py:`namespace.since`           Since which version the namespace is available
+                                [8]_
 =============================== ===============================================
 
 `Class properties`_
@@ -1708,7 +1765,8 @@ Property                    Description
 :py:`class.templates`       Template specification. See `Template properties`_
                             for details.
 :py:`class.brief`           Brief description. Can be empty. [1]_
-:py:`class.is_deprecated`   Whether the class is deprecated. [7]_
+:py:`class.deprecated`      Deprecation status [7]_
+:py:`class.since`           Since which version the class is available [8]_
 :py:`class.is_protected`    Whether this is a protected base class. Set only
                             for base classes.
 :py:`class.is_virtual`      Whether this is a virtual base class or a
@@ -1744,7 +1802,8 @@ Property                        Description
 :py:`enum.description`          Detailed description. Can be empty. [2]_
 :py:`enum.has_details`          If there is enough content for the full
                                 description block [5]_
-:py:`enum.is_deprecated`        Whether the enum is deprecated. [7]_
+:py:`enum.deprecated`           Deprecation status [7]_
+:py:`enum.since`                Since which version the enum is available [8]_
 :py:`enum.is_protected`         If the enum is :cpp:`protected`. Set only for
                                 member types.
 :py:`enum.values`               List of enum values
@@ -1763,7 +1822,8 @@ Property                    Description
 :py:`value.id`              Identifier hash [3]_
 :py:`value.name`            Value name [4]_
 :py:`value.initializer`     Value initializer. Can be empty. [1]_
-:py:`value.is_deprecated`   Whether the value is deprecated. [7]_
+:py:`value.deprecated`      Deprecation status [7]_
+:py:`value.since`           Since which version the value is available [8]_
 :py:`value.brief`           Brief description. Can be empty. [1]_
 :py:`value.description`     Detailed description. Can be empty. [2]_
 =========================== ===================================================
@@ -1800,7 +1860,9 @@ Property                            Description
                                     for details.
 :py:`typedef.has_template_details`  If template parameters have description
 :py:`typedef.brief`                 Brief description. Can be empty. [1]_
-:py:`typedef.is_deprecated`         Whether the typedef is deprecated. [7]_
+:py:`typedef.deprecated`            Deprecation status [7]_
+:py:`typedef.since`                 Since which version the typedef is
+                                    available [8]_
 :py:`typedef.description`           Detailed description. Can be empty. [2]_
 :py:`typedef.has_details`           If there is enough content for the full
                                     description block [4]_
@@ -1863,7 +1925,9 @@ Property                            Description
                                     and :cpp:`delete`\ d / :cpp:`default`\ ed
                                     functions is removed from the suffix and
                                     available via other properties.
-:py:`func.is_deprecated`            Whether the function is deprecated. [7]_
+:py:`func.deprecated`               Deprecation status [7]_
+:py:`func.since`                    Since which version the function is
+                                    available [8]_
 :py:`func.is_protected`             If the function is :cpp:`protected`. Set
                                     only for member functions.
 :py:`func.is_private`               If the function is :cpp:`private`. Set only
@@ -1948,7 +2012,9 @@ Property                        Description
 :py:`var.description`           Detailed description. Can be empty. [2]_
 :py:`var.has_details`           If there is enough content for the full
                                 description block [5]_
-:py:`var.is_deprecated`         Whether the variable is deprecated. [7]_
+:py:`var.deprecated`            Deprecation status [7]_
+:py:`var.since`                 Since which version the variable is available
+                                [8]_
 :py:`var.is_static`             If the variable is :cpp:`static`. Set only for
                                 member variables.
 :py:`var.is_protected`          If the variable is :cpp:`protected`. Set only
@@ -1981,7 +2047,9 @@ Property                        Description
 :py:`define.return_value`       Return value description. Can be empty.
 :py:`define.brief`              Brief description. Can be empty. [1]_
 :py:`define.description`        Detailed description. Can be empty. [2]_
-:py:`define.is_deprecated`      Whether the define is deprecated. [7]_
+:py:`define.deprecated`         Deprecation status [7]_
+:py:`define.since`              Since which version the define is available
+                                [8]_
 :py:`define.has_details`        If there is enough content for the full
                                 description block [5]_
 =============================== ===============================================
@@ -2107,7 +2175,8 @@ Property                        Description
 :py:`i.name`                    Name
 :py:`i.url`                     URL of the file with detailed documentation
 :py:`i.brief`                   Brief documentation
-:py:`i.is_deprecated`           Whether the entry is deprecated. [7]_
+:py:`i.deprecated`              Deprecation status [7]_
+:py:`i.since`                   Since which version the entry is available [8]_
 :py:`i.is_final`                Whether the class is :cpp:`final`. Set only for
                                 classes.
 :py:`i.has_nestable_children`   If the list has nestable children (i.e., dirs
@@ -2140,5 +2209,8 @@ all directories are before all files.
     :py:`compound.url`, its :py:`i.has_details` is always set to :py:`False`.
 .. [6] :py:`i.type` and :py:`param.default` is rendered as HTML and usually
     contains links to related documentation
-.. [7] :py:`i.is_deprecated` is set to :py:`True` if detailed docs of given
-    symbol contain the ``@deprecated`` command and to :py:`False` otherwise
+.. [7] :py:`i.deprecated` is set to a string containing the deprecation
+    status if detailed docs of given symbol contain the ``@deprecated`` command and to :py:`None` otherwise.  See also `Version labels`_ for more
+    information.
+.. [8] :py:`i.status` HTML code with a label or :py:`None`. See
+    `Version labels`_ for more information.
index 6d4e4d545fe84ea085f3215dca9487730e1511c3..cb12de0031b04f7ea20f3a64ec2b2e6a6286e384 100755 (executable)
@@ -103,7 +103,7 @@ class StateCompound:
         self.url: str
         self.brief: str
         self.has_details: bool
-        self.is_deprecated: bool
+        self.deprecated: str
         self.is_final: bool = None
         self.children: List[str]
         self.parent: str = None
@@ -301,7 +301,8 @@ def parse_desc_internal(state: State, element: ET.Element, immediate_parent: ET.
     out.example_navigation = None
     out.search_keywords = []
     out.search_enum_values_as_keywords = False
-    out.is_deprecated = False
+    out.deprecated = None
+    out.since = None
 
     # DOXYGEN <PARA> PATCHING 1/4
     #
@@ -356,6 +357,11 @@ def parse_desc_internal(state: State, element: ET.Element, immediate_parent: ET.
             out.return_values += parsed.return_values
         if parsed.exceptions:
             out.exceptions += parsed.exceptions
+        if parsed.since:
+            out.since = parsed.since
+        if parsed.deprecated:
+            assert not out.since
+            out.deprecated = parsed.deprecated
 
     i: ET.Element
     for index, i in enumerate(element):
@@ -659,7 +665,6 @@ def parse_desc_internal(state: State, element: ET.Element, immediate_parent: ET.
             if parsed.example_navigation: out.example_navigation = parsed.example_navigation
             out.search_keywords += parsed.search_keywords
             if parsed.search_enum_values_as_keywords: out.search_enum_values_as_keywords = True
-            if parsed.is_deprecated: out.is_deprecated = True
 
             # Assert we didn't miss anything important
             assert not parsed.section
@@ -742,6 +747,14 @@ def parse_desc_internal(state: State, element: ET.Element, immediate_parent: ET.
                     logging.warning("{}: superfluous @return section found, ignoring: {} ".format(state.current, ''.join(i.itertext())))
                 else:
                     out.return_value = parse_desc(state, i)
+
+            # Content of @since tags is put as-is into entry description /
+            # details, if enabled.
+            elif i.attrib['kind'] == 'since' and state.doxyfile['M_VERSION_LABELS']:
+                since = parse_inline_desc(state, i).strip()
+                assert since.startswith('<p>') and since.endswith('</p>')
+                out.since = since[3:-4]
+
             else:
                 has_block_elements = True
 
@@ -848,15 +861,24 @@ def parse_desc_internal(state: State, element: ET.Element, immediate_parent: ET.
             id = i.attrib['id']
             match = xref_id_rx.match(id)
             file = match.group(1)
+            title = i.find('xreftitle').text
             if add_css_class:
                 css_class = add_css_class
                 heading = 'h3'
             else:
                 heading = 'h4'
                 css_class = 'm-note '
+                # If we have version info from a previous Since badge, use it
+                # instead of the title
                 if file.startswith('deprecated'):
                     css_class += 'm-danger'
-                    out.is_deprecated = True
+                    if out.since:
+                        out.deprecated = out.since
+                        title = out.since.capitalize()
+                        out.since = None
+                    else:
+                        out.deprecated = 'deprecated'
+                        title = 'Deprecated'
                 elif file.startswith('bug'):
                     css_class += 'm-danger'
                 elif file.startswith('todo'):
@@ -868,7 +890,7 @@ def parse_desc_internal(state: State, element: ET.Element, immediate_parent: ET.
                 heading=heading,
                 file=file,
                 anchor=match.group(2),
-                title=i.find('xreftitle').text,
+                title=title,
                 description=parse_desc(state, i.find('xrefdescription')))
 
         elif i.tag == 'parameterlist':
@@ -1624,14 +1646,14 @@ def parse_enum_desc(state: State, element: ET.Element) -> Tuple[str, List[Tuple[
     if parsed.templates or parsed.params or parsed.return_value or parsed.return_values or parsed.exceptions:
         logging.warning("{}: unexpected @tparam / @param / @return / @retval / @exception found in enum description, ignoring".format(state.current))
     assert not parsed.section # might be problematic
-    return parsed.parsed, parsed.search_keywords, parsed.search_enum_values_as_keywords, parsed.is_deprecated
+    return parsed.parsed, parsed.search_keywords, parsed.search_enum_values_as_keywords, parsed.deprecated, parsed.since
 
 def parse_enum_value_desc(state: State, element: ET.Element) -> Tuple[str, List[Tuple[str, str, int]], bool]:
     parsed = parse_desc_internal(state, element.find('detaileddescription'))
     if parsed.templates or parsed.params or parsed.return_value or parsed.return_values or parsed.exceptions:
         logging.warning("{}: unexpected @tparam / @param / @return / @retval / @exception found in enum value description, ignoring".format(state.current))
     assert not parsed.section # might be problematic
-    return parsed.parsed, parsed.search_keywords, parsed.is_deprecated
+    return parsed.parsed, parsed.search_keywords, parsed.deprecated, parsed.since
 
 def parse_var_desc(state: State, element: ET.Element) -> Tuple[str, List[Any], List[Tuple[str, str, int]], bool]:
     parsed = parse_desc_internal(state, element.find('detaileddescription'))
@@ -1639,7 +1661,7 @@ def parse_var_desc(state: State, element: ET.Element) -> Tuple[str, List[Any], L
     if parsed.params or parsed.return_value or parsed.return_values or parsed.exceptions:
         logging.warning("{}: unexpected @param / @return / @retval / @exception found in variable description, ignoring".format(state.current))
     assert not parsed.section # might be problematic
-    return parsed.parsed, parsed.templates, parsed.search_keywords, parsed.is_deprecated
+    return parsed.parsed, parsed.templates, parsed.search_keywords, parsed.deprecated, parsed.since
 
 def parse_toplevel_desc(state: State, element: ET.Element) -> Tuple[str, List[Any], str, Any, Any, List[Tuple[str, str, int]], bool]:
     state.parsing_toplevel_desc = True
@@ -1647,7 +1669,7 @@ def parse_toplevel_desc(state: State, element: ET.Element) -> Tuple[str, List[An
     state.parsing_toplevel_desc = False
     if parsed.params or parsed.return_value or parsed.return_values or parsed.exceptions:
         logging.warning("{}: unexpected @param / @return / @retval / @exception found in top-level description, ignoring".format(state.current))
-    return parsed.parsed, parsed.templates, parsed.section[2] if parsed.section else '', parsed.footer_navigation, parsed.example_navigation, parsed.search_keywords, parsed.is_deprecated
+    return parsed.parsed, parsed.templates, parsed.section[2] if parsed.section else '', parsed.footer_navigation, parsed.example_navigation, parsed.search_keywords, parsed.deprecated, parsed.since
 
 def parse_typedef_desc(state: State, element: ET.Element) -> Tuple[str, List[Any], List[Tuple[str, str, int]], bool]:
     parsed = parse_desc_internal(state, element.find('detaileddescription'))
@@ -1655,13 +1677,13 @@ def parse_typedef_desc(state: State, element: ET.Element) -> Tuple[str, List[Any
     if parsed.params or parsed.return_value or parsed.return_values or parsed.exceptions:
         logging.warning("{}: unexpected @param / @return / @retval / @exception found in typedef description, ignoring".format(state.current))
     assert not parsed.section # might be problematic
-    return parsed.parsed, parsed.templates, parsed.search_keywords, parsed.is_deprecated
+    return parsed.parsed, parsed.templates, parsed.search_keywords, parsed.deprecated, parsed.since
 
 def parse_func_desc(state: State, element: ET.Element) -> Tuple[str, List[Any], List[Any], str, List[Any], List[Any], List[Tuple[str, str, int]], bool]:
     parsed = parse_desc_internal(state, element.find('detaileddescription'))
     parsed.parsed += parse_desc(state, element.find('inbodydescription'))
     assert not parsed.section # might be problematic
-    return parsed.parsed, parsed.templates, parsed.params, parsed.return_value, parsed.return_values, parsed.exceptions, parsed.search_keywords, parsed.is_deprecated
+    return parsed.parsed, parsed.templates, parsed.params, parsed.return_value, parsed.return_values, parsed.exceptions, parsed.search_keywords, parsed.deprecated, parsed.since
 
 def parse_define_desc(state: State, element: ET.Element) -> Tuple[str, List[Any], str, List[Tuple[str, str, int]], bool]:
     parsed = parse_desc_internal(state, element.find('detaileddescription'))
@@ -1669,7 +1691,7 @@ def parse_define_desc(state: State, element: ET.Element) -> Tuple[str, List[Any]
     if parsed.templates or parsed.return_values or parsed.exceptions:
         logging.warning("{}: unexpected @tparam / @retval / @exception found in macro description, ignoring".format(state.current))
     assert not parsed.section # might be problematic
-    return parsed.parsed, parsed.params, parsed.return_value, parsed.search_keywords, parsed.is_deprecated
+    return parsed.parsed, parsed.params, parsed.return_value, parsed.search_keywords, parsed.deprecated, parsed.since
 
 def parse_inline_desc(state: State, element: ET.Element) -> str:
     if element is None: return ''
@@ -1689,7 +1711,7 @@ def parse_enum(state: State, element: ET.Element):
     enum.name = element.find('name').text
     if enum.name.startswith('@'): enum.name = '(anonymous)'
     enum.brief = parse_desc(state, element.find('briefdescription'))
-    enum.description, search_keywords, search_enum_values_as_keywords, enum.is_deprecated = parse_enum_desc(state, element)
+    enum.description, search_keywords, search_enum_values_as_keywords, enum.deprecated, enum.since = parse_enum_desc(state, element)
     enum.is_protected = element.attrib['prot'] == 'protected'
     enum.is_strong = False
     if 'strong' in element.attrib:
@@ -1707,11 +1729,11 @@ def parse_enum(state: State, element: ET.Element):
         # There can be an implicit initializer for enum value
         value.initializer = html.escape(enumvalue.findtext('initializer', ''))
         value.brief = parse_desc(state, enumvalue.find('briefdescription'))
-        value.description, value_search_keywords, value.is_deprecated = parse_enum_value_desc(state, enumvalue)
+        value.description, value_search_keywords, value.deprecated, value.since = parse_enum_value_desc(state, enumvalue)
         if value.brief or value.description:
             if enum.base_url == state.current_compound_url and not state.doxyfile['M_SEARCH_DISABLED']:
                 result = Empty()
-                result.flags = ResultFlag.from_type(ResultFlag.DEPRECATED if value.is_deprecated else ResultFlag(0), EntryType.ENUM_VALUE)
+                result.flags = ResultFlag.from_type(ResultFlag.DEPRECATED if value.deprecated else ResultFlag(0), EntryType.ENUM_VALUE)
                 result.url = enum.base_url + '#' + value.id
                 result.prefix = state.current_prefix + [enum.name]
                 result.name = value.name
@@ -1736,7 +1758,7 @@ def parse_enum(state: State, element: ET.Element):
     if enum.brief or enum.has_details or enum.has_value_details:
         if enum.base_url == state.current_compound_url and not state.doxyfile['M_SEARCH_DISABLED']:
             result = Empty()
-            result.flags = ResultFlag.from_type(ResultFlag.DEPRECATED if enum.is_deprecated else ResultFlag(0), EntryType.ENUM)
+            result.flags = ResultFlag.from_type(ResultFlag.DEPRECATED if enum.deprecated else ResultFlag(0), EntryType.ENUM)
             result.url = enum.base_url + '#' + enum.id
             result.prefix = state.current_prefix
             result.name = enum.name
@@ -1802,7 +1824,7 @@ def parse_typedef(state: State, element: ET.Element):
     typedef.args = parse_type(state, element.find('argsstring'))
     typedef.name = element.find('name').text
     typedef.brief = parse_desc(state, element.find('briefdescription'))
-    typedef.description, templates, search_keywords, typedef.is_deprecated = parse_typedef_desc(state, element)
+    typedef.description, templates, search_keywords, typedef.deprecated, typedef.since = parse_typedef_desc(state, element)
     typedef.is_protected = element.attrib['prot'] == 'protected'
     typedef.has_template_details, typedef.templates = parse_template_params(state, element.find('templateparamlist'), templates)
 
@@ -1812,7 +1834,7 @@ def parse_typedef(state: State, element: ET.Element):
         # Avoid duplicates in search
         if typedef.base_url == state.current_compound_url and not state.doxyfile['M_SEARCH_DISABLED']:
             result = Empty()
-            result.flags = ResultFlag.from_type(ResultFlag.DEPRECATED if typedef.is_deprecated else ResultFlag(0), EntryType.TYPEDEF)
+            result.flags = ResultFlag.from_type(ResultFlag.DEPRECATED if typedef.deprecated else ResultFlag(0), EntryType.TYPEDEF)
             result.url = typedef.base_url + '#' + typedef.id
             result.prefix = state.current_prefix
             result.name = typedef.name
@@ -1829,7 +1851,7 @@ def parse_func(state: State, element: ET.Element):
     func.type = parse_type(state, element.find('type'))
     func.name = fix_type_spacing(html.escape(element.find('name').text))
     func.brief = parse_desc(state, element.find('briefdescription'))
-    func.description, templates, params, func.return_value, func.return_values, func.exceptions, search_keywords, func.is_deprecated = parse_func_desc(state, element)
+    func.description, templates, params, func.return_value, func.return_values, func.exceptions, search_keywords, func.deprecated, func.since = parse_func_desc(state, element)
 
     # Friend functions have friend as type. That's just awful. COME ON.
     if func.type.startswith('friend '):
@@ -1957,7 +1979,7 @@ def parse_func(state: State, element: ET.Element):
         # Avoid duplicates in search
         if func.base_url == state.current_compound_url and not state.doxyfile['M_SEARCH_DISABLED']:
             result = Empty()
-            result.flags = ResultFlag.from_type((ResultFlag.DEPRECATED if func.is_deprecated else ResultFlag(0))|(ResultFlag.DELETED if func.is_deleted else ResultFlag(0)), EntryType.FUNC)
+            result.flags = ResultFlag.from_type((ResultFlag.DEPRECATED if func.deprecated else ResultFlag(0))|(ResultFlag.DELETED if func.is_deleted else ResultFlag(0)), EntryType.FUNC)
             result.url = func.base_url + '#' + func.id
             result.prefix = state.current_prefix
             result.name = func.name
@@ -1984,7 +2006,7 @@ def parse_var(state: State, element: ET.Element):
     var.is_private = element.attrib['prot'] == 'private'
     var.name = element.find('name').text
     var.brief = parse_desc(state, element.find('briefdescription'))
-    var.description, templates, search_keywords, var.is_deprecated = parse_var_desc(state, element)
+    var.description, templates, search_keywords, var.deprecated, var.since = parse_var_desc(state, element)
     var.has_template_details, var.templates = parse_template_params(state, element.find('templateparamlist'), templates)
 
     if var.base_url == state.current_compound_url and (var.description or var.has_template_details):
@@ -1993,7 +2015,7 @@ def parse_var(state: State, element: ET.Element):
         # Avoid duplicates in search
         if var.base_url == state.current_compound_url and not state.doxyfile['M_SEARCH_DISABLED']:
             result = Empty()
-            result.flags = ResultFlag.from_type(ResultFlag.DEPRECATED if var.is_deprecated else ResultFlag(0), EntryType.VAR)
+            result.flags = ResultFlag.from_type(ResultFlag.DEPRECATED if var.deprecated else ResultFlag(0), EntryType.VAR)
             result.url = var.base_url + '#' + var.id
             result.prefix = state.current_prefix
             result.name = var.name
@@ -2009,7 +2031,7 @@ def parse_define(state: State, element: ET.Element):
     state.current_definition_url_base, define.base_url, define.id, define.include, define.has_details = parse_id_and_include(state, element)
     define.name = element.find('name').text
     define.brief = parse_desc(state, element.find('briefdescription'))
-    define.description, params, define.return_value, search_keywords, define.is_deprecated = parse_define_desc(state, element)
+    define.description, params, define.return_value, search_keywords, define.deprecated, define.since = parse_define_desc(state, element)
     define.has_param_details = False
     define.params = None
     for p in element.findall('param'):
@@ -2033,7 +2055,7 @@ def parse_define(state: State, element: ET.Element):
         # Avoid duplicates in search
         if define.base_url == state.current_compound_url and not state.doxyfile['M_SEARCH_DISABLED']:
             result = Empty()
-            result.flags = ResultFlag.from_type(ResultFlag.DEPRECATED if define.is_deprecated else ResultFlag(0), EntryType.DEFINE)
+            result.flags = ResultFlag.from_type(ResultFlag.DEPRECATED if define.deprecated else ResultFlag(0), EntryType.DEFINE)
             result.url = define.base_url + '#' + define.id
             result.prefix = []
             result.name = define.name
@@ -2120,14 +2142,26 @@ def extract_metadata(state: State, xml):
     compound.has_details = compound.kind == 'group' or compound.brief or compounddef.find('detaileddescription') or (compound.kind == 'page' and not is_a_stupid_empty_markdown_page(compounddef))
     compound.children = []
 
-    # Deprecation status
-    compound.is_deprecated = False
+    # Version badges, deprecation status. If @since is followed by
+    # @deprecated, treat it as version in which given feature was deprecated
+    compound.deprecated = None
+    compound.since = None
+    if state.doxyfile['M_VERSION_LABELS']:
+        for i in compounddef.find('detaileddescription').findall('.//simplesect'):
+            if i.attrib['kind'] != 'since': continue
+            since = parse_inline_desc(state, i).strip()
+            assert since.startswith('<p>') and since.endswith('</p>')
+            compound.since = since[3:-4]
     for i in compounddef.find('detaileddescription').findall('.//xrefsect'):
         id = i.attrib['id']
         match = xref_id_rx.match(id)
         file = match.group(1)
         if file.startswith('deprecated'):
-            compound.is_deprecated = True
+            if compound.since:
+                compound.deprecated = compound.since
+                compound.since = None
+            else:
+                compound.deprecated = 'deprecated'
             break
 
     # Final classes
@@ -2429,7 +2463,7 @@ def parse_xml(state: State, xml: str):
     compound.has_template_details = False
     compound.templates = None
     compound.brief = parse_desc(state, compounddef.find('briefdescription'))
-    compound.description, templates, compound.sections, footer_navigation, example_navigation, search_keywords, compound.is_deprecated = parse_toplevel_desc(state, compounddef.find('detaileddescription'))
+    compound.description, templates, compound.sections, footer_navigation, example_navigation, search_keywords, compound.deprecated, compound.since = parse_toplevel_desc(state, compounddef.find('detaileddescription'))
     compound.example_navigation = None
     compound.footer_navigation = None
     compound.modules = []
@@ -2583,7 +2617,8 @@ def parse_xml(state: State, xml: str):
                 f.url = file.url
                 f.name = file.leaf_name
                 f.brief = file.brief
-                f.is_deprecated = file.is_deprecated
+                f.deprecated = file.deprecated
+                f.since = file.since
 
                 if compounddef_child.tag == 'innerdir':
                     compound.dirs += [f]
@@ -2604,7 +2639,8 @@ def parse_xml(state: State, xml: str):
                     namespace.url = symbol.url
                     namespace.name = symbol.leaf_name if compound.kind == 'namespace' else symbol.name
                     namespace.brief = symbol.brief
-                    namespace.is_deprecated = symbol.is_deprecated
+                    namespace.deprecated = symbol.deprecated
+                    namespace.since = symbol.since
                     compound.namespaces += [namespace]
 
                 else:
@@ -2615,7 +2651,8 @@ def parse_xml(state: State, xml: str):
                     class_.url = symbol.url
                     class_.name = symbol.leaf_name if compound.kind in ['namespace', 'class', 'struct', 'union'] else symbol.name
                     class_.brief = symbol.brief
-                    class_.is_deprecated = symbol.is_deprecated
+                    class_.deprecated = symbol.deprecated
+                    class_.since = symbol.since
                     class_.templates = symbol.templates
 
                     # Put classes into the public/protected section for
@@ -2647,7 +2684,8 @@ def parse_xml(state: State, xml: str):
                     class_.name = symbol.leaf_name if state.compounds[compound.id].parent and symbol.parent and symbol.parent.startswith(state.compounds[compound.id].parent) else symbol.name
                     class_.brief = symbol.brief
                     class_.templates = symbol.templates
-                    class_.is_deprecated = symbol.is_deprecated
+                    class_.deprecated = symbol.deprecated
+                    class_.since = symbol.since
                     class_.is_protected = compounddef_child.attrib['prot'] == 'protected'
                     class_.is_virtual = compounddef_child.attrib['virt'] == 'virtual'
 
@@ -2670,7 +2708,8 @@ def parse_xml(state: State, xml: str):
                     class_.name = symbol.leaf_name if state.compounds[compound.id].parent and symbol.parent and symbol.parent.startswith(state.compounds[compound.id].parent) else symbol.name
                     class_.brief = symbol.brief
                     class_.templates = symbol.templates
-                    class_.is_deprecated = symbol.is_deprecated
+                    class_.deprecated = symbol.deprecated
+                    class_.since = symbol.since
                     class_.is_virtual = compounddef_child.attrib['virt'] == 'virtual'
                     class_.is_final = symbol.is_final
 
@@ -2685,7 +2724,8 @@ def parse_xml(state: State, xml: str):
             g.url = group.url
             g.name = group.leaf_name
             g.brief = group.brief
-            g.is_deprecated = group.is_deprecated
+            g.deprecated = group.deprecated
+            g.since = group.since
             compound.modules += [g]
 
         # Other, grouped in sections
@@ -3125,7 +3165,7 @@ def parse_xml(state: State, xml: str):
         else: assert False # pragma: no cover
 
         result = Empty()
-        result.flags = ResultFlag.from_type(ResultFlag.DEPRECATED if compound.is_deprecated else ResultFlag(0), kind)
+        result.flags = ResultFlag.from_type(ResultFlag.DEPRECATED if compound.deprecated else ResultFlag(0), kind)
         result.url = compound.url
         result.prefix = state.current_prefix[:-1]
         result.name = state.current_prefix[-1]
@@ -3178,7 +3218,8 @@ def parse_index_xml(state: State, xml):
         entry.url = compound.url
         entry.brief = compound.brief
         entry.children = []
-        entry.is_deprecated = compound.is_deprecated
+        entry.deprecated = compound.deprecated
+        entry.since = compound.since
         entry.has_nestable_children = False
         if compound.kind in ['class', 'struct', 'union']:
             entry.is_final = compound.is_final
@@ -3303,7 +3344,8 @@ copy a link to the result using <span class="m-label m-dim">⌘</span>
 """],
         'M_SEARCH_BASE_URL': [''],
         'M_SEARCH_EXTERNAL_URL': [''],
-        'M_SHOW_UNDOCUMENTED': ['NO']
+        'M_SHOW_UNDOCUMENTED': ['NO'],
+        'M_VERSION_LABELS': ['NO']
     }
 
     # Defaults so we don't fail with minimal Doxyfiles and also that the
@@ -3423,7 +3465,8 @@ copy a link to the result using <span class="m-label m-dim">⌘</span>
               'M_EXPAND_INNER_TYPES',
               'M_SEARCH_DISABLED',
               'M_SEARCH_DOWNLOAD_BINARY',
-              'M_SHOW_UNDOCUMENTED']:
+              'M_SHOW_UNDOCUMENTED',
+              'M_VERSION_LABELS']:
         if i in config: state.doxyfile[i] = ' '.join(config[i]) == 'YES'
 
     # List values that we want. Drop empty lines.
index a81e20311c09ddfc9ee176019af682b4f677cc75..338ad88116dfd524b9432c71fa61840495ca53ec 100644 (file)
@@ -7,13 +7,13 @@
           {% for i in index.symbols recursive %}
           {% if i.children %}
           <li class="m-doc-collapsible{% if loop.depth > M_CLASS_TREE_EXPAND_LEVELS or (i.kind != 'namespace' and not M_EXPAND_INNER_TYPES) %} collapsed{% endif %}">
-            <a href="#" onclick="return toggle(this)">{{ i.kind }}</a> <a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %} <span class="m-doc">{{ i.brief }}</span>
+            <a href="#" onclick="return toggle(this)">{{ i.kind }}</a> <a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.deprecated %} <span class="m-label m-danger">{{ i.deprecated }}</span>{% endif %}{% if i.since %} {{ i.since }}{% endif %} <span class="m-doc">{{ i.brief }}</span>
             <ul class="m-doc">
 {{ loop(i.children)|rtrim|indent(4, true) }}
             </ul>
           </li>
           {% else %}
-          <li>{{ i.kind }} <a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.is_final %} <span class="m-label m-flat m-warning">final</span>{% endif %}{% if i.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %} <span class="m-doc">{{ i.brief }}</span></li>
+          <li>{{ i.kind }} <a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.is_final %} <span class="m-label m-flat m-warning">final</span>{% endif %}{% if i.deprecated %} <span class="m-label m-danger">{{ i.deprecated }}</span>{% endif %}{% if i.since %} {{ i.since }}{% endif %} <span class="m-doc">{{ i.brief }}</span></li>
           {% endif %}
           {% endfor %}
         </ul>
index abcb996cc8210708a7687c383600b37e52ab009d..7c7eae524b0b55a813c0b84a7bd064378505588d 100644 (file)
@@ -24,7 +24,7 @@
           {% set j = joiner(', ') %}
           <div class="m-doc-template">template&lt;{% for t in compound.templates %}{{ j() }}{{ t.type }}{% if t.name %} {{ t.name }}{% endif %}{% if t.default %} = {{ t.default }}{% endif%}{% endfor %}&gt;</div>
           {% endif %}
-          {%+ for name, target in compound.breadcrumb[:-1] %}<span class="m-breadcrumb"><a href="{{ target }}">{{ name }}</a>::<wbr/></span>{% endfor %}{{ compound.breadcrumb[-1][0] }} <span class="m-thin">{{ compound.kind }}</span>{% if compound.is_final %} <span class="m-label m-flat m-warning">final</span>{% endif %}
+          {%+ for name, target in compound.breadcrumb[:-1] %}<span class="m-breadcrumb"><a href="{{ target }}">{{ name }}</a>::<wbr/></span>{% endfor %}{{ compound.breadcrumb[-1][0] }} <span class="m-thin">{{ compound.kind }}</span>{% if compound.is_final %} <span class="m-label m-flat m-warning">final</span>{% endif %}{% if compound.since %} {{ compound.since }}{% endif %}
           {# need an explicit space here otherwise the newline gets removed #}
 
           {% if compound.include and compound.templates == None %}
index 63cc720bcc869997b8f21fed1ad7dc4fe474cf3b..6e30eadf07834164c835ec460ba44b8c88218f16 100644 (file)
@@ -1,7 +1,7 @@
           <section class="m-doc-details" id="{{ define.id }}"><div>
             <h3>
               {% set j = joiner(',\n              ') %}
-              <span class="m-doc-wrap-bumper">#define <a href="#{{ define.id }}" class="m-doc-self">{{ define.name }}</a>{% if define.params != None %}(</span><span class="m-doc-wrap">{% for param in define.params %}{{ j() }}{{ param[0] }}{% endfor %}){% endif %}</span>
+              <span class="m-doc-wrap-bumper">#define <a href="#{{ define.id }}" class="m-doc-self">{{ define.name }}</a>{% if define.params != None %}(</span><span class="m-doc-wrap">{% for param in define.params %}{{ j() }}{{ param[0] }}{% endfor %}){% endif %}{% if define.since %} {{ define.since }}{% endif %}</span>
               {% if define.include %}
               <div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="{{ define.include[1] }}">{{ define.include[0] }}</a></div>
               {% endif %}
index 72ef6756b52fa11f27a785f0ae03ab149b01dc9e..0134304120366ebdf4dc54d59f007736dcdc7716 100644 (file)
@@ -6,7 +6,7 @@
                 template&lt;{% for t in compound.templates %}{{ j() }}{{ t.type }} {% if t.name %}{{ t.name }}{% else %}_{{ loop.index }}{% endif %}{% endfor %}&gt;
               </div>
               {% endif %}
-              enum {% if enum.is_strong %}class {% endif %}{{ prefix }}<a href="#{{ enum.id }}" class="m-doc-self">{{ enum.name }}</a>{% if enum.type %}: {{ enum.type }}{% endif %}{% if enum.is_protected %} <span class="m-label m-warning">protected</span>{% endif %}
+              enum {% if enum.is_strong %}class {% endif %}{{ prefix }}<a href="#{{ enum.id }}" class="m-doc-self">{{ enum.name }}</a>{% if enum.type %}: {{ enum.type }}{% endif %}{% if enum.is_protected %} <span class="m-label m-warning">protected</span>{% endif %}{% if enum.since %} {{ enum.since }}{% endif %}
               {# not sure why there needs to be this space #}
 
               {% if enum.include %}
@@ -29,7 +29,7 @@
               <tbody>
                 {% for value in enum.values %}
                 <tr>
-                  <td><a href="#{{ value.id }}" class="m-doc-self" id="{{ value.id }}">{{ value.name }}</a></td>
+                  <td><a href="#{{ value.id }}" class="m-doc-self" id="{{ value.id }}">{{ value.name }}</a>{% if value.since %} {{ value.since }}{% endif %}</td>
                   <td>
                   {% if value.brief %}{# brief is not required for values #}
                   <p>{{ value.brief }}</p>
index 5db4d2dc2996e6c481c4e80105ab821a158831c3..5044dc95eb3b68564b0ff4c67c1f7993f0974a2c 100644 (file)
@@ -16,7 +16,7 @@
               </div>
               {% endif %}
               {% set j = joiner(',\n              ') %}
-              <span class="m-doc-wrap-bumper">{{ func.prefix }}{{ func.type }} {{ prefix }}</span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#{{ func.id }}" class="m-doc-self">{{ func.name }}</a>(</span><span class="m-doc-wrap">{% for param in func.params %}{{ j() }}{{ param.type_name }}{% if param.default %} = {{ param.default }}{% endif %}{% endfor %}){{ func.suffix }}{% if func.is_explicit %} <span class="m-label m-info">explicit</span> {% endif %}{% if func.is_final %} <span class="m-label m-warning">final</span>{% elif func.is_override %} <span class="m-label m-warning">override</span>{% elif func.is_pure_virtual %} <span class="m-label m-warning">pure virtual</span>{% elif func.is_virtual %} <span class="m-label m-warning">virtual</span>{% endif %}{% if func.is_protected %} <span class="m-label m-warning">protected{% if func.is_slot %} slot{% endif %}</span>{% elif func.is_private %} <span class="m-label m-danger">private{% if func.is_slot %} slot{% endif %}</span>{% elif func.is_signal %} <span class="m-label m-success">signal</span>{% elif func.is_slot %} <span class="m-label m-success">public slot</span>{% endif %}{% if func.is_defaulted %} <span class="m-label m-info">defaulted</span>{% endif %}{% if func.is_deleted %} <span class="m-label m-danger">deleted</span>{% endif %}{% if func.is_constexpr %} <span class="m-label m-primary">constexpr</span>{% endif %}{% if func.is_conditional_noexcept %} <span class="m-label m-success">noexcept(…)</span>{% elif func.is_noexcept %} <span class="m-label m-success">noexcept</span>{% endif %}</span></span>
+              <span class="m-doc-wrap-bumper">{{ func.prefix }}{{ func.type }} {{ prefix }}</span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#{{ func.id }}" class="m-doc-self">{{ func.name }}</a>(</span><span class="m-doc-wrap">{% for param in func.params %}{{ j() }}{{ param.type_name }}{% if param.default %} = {{ param.default }}{% endif %}{% endfor %}){{ func.suffix }}{% if func.is_explicit %} <span class="m-label m-info">explicit</span> {% endif %}{% if func.is_final %} <span class="m-label m-warning">final</span>{% elif func.is_override %} <span class="m-label m-warning">override</span>{% elif func.is_pure_virtual %} <span class="m-label m-warning">pure virtual</span>{% elif func.is_virtual %} <span class="m-label m-warning">virtual</span>{% endif %}{% if func.is_protected %} <span class="m-label m-warning">protected{% if func.is_slot %} slot{% endif %}</span>{% elif func.is_private %} <span class="m-label m-danger">private{% if func.is_slot %} slot{% endif %}</span>{% elif func.is_signal %} <span class="m-label m-success">signal</span>{% elif func.is_slot %} <span class="m-label m-success">public slot</span>{% endif %}{% if func.is_defaulted %} <span class="m-label m-info">defaulted</span>{% endif %}{% if func.is_deleted %} <span class="m-label m-danger">deleted</span>{% endif %}{% if func.is_constexpr %} <span class="m-label m-primary">constexpr</span>{% endif %}{% if func.is_conditional_noexcept %} <span class="m-label m-success">noexcept(…)</span>{% elif func.is_noexcept %} <span class="m-label m-success">noexcept</span>{% endif %}{% if func.since %} {{ func.since }}{% endif %}</span></span>
               {% if func.include and compound.templates == None and func.templates == None %}
               <div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="{{ func.include[1] }}">{{ func.include[0] }}</a></div>
               {% endif %}
index b0b37c923852d4c0264f9794b3126dbd71755fba..76346baaa0cba38c99d580fa1a871d6e096c79cc 100644 (file)
@@ -16,9 +16,9 @@
               </div>
               {% endif %}
               {% if typedef.is_using %}
-              using {{ prefix }}<a href="#{{ typedef.id }}" class="m-doc-self">{{ typedef.name }}</a> = {{ typedef.type }}{{ typedef.args }}{% if typedef.is_protected %} <span class="m-label m-warning">protected</span>{% endif %}
+              using {{ prefix }}<a href="#{{ typedef.id }}" class="m-doc-self">{{ typedef.name }}</a> = {{ typedef.type }}{{ typedef.args }}{% if typedef.is_protected %} <span class="m-label m-warning">protected</span>{% endif %}{% if typedef.since %} {{ typedef.since }}{% endif %}
               {% else %}
-              typedef {{ typedef.type }}{% if not typedef.args %} {% endif %}{{ prefix }}<a href="#{{ typedef.id }}" class="m-doc-self">{{ typedef.name }}</a>{{ typedef.args }}{% if typedef.is_protected %} <span class="m-label m-warning">protected</span>{% endif %}
+              typedef {{ typedef.type }}{% if not typedef.args %} {% endif %}{{ prefix }}<a href="#{{ typedef.id }}" class="m-doc-self">{{ typedef.name }}</a>{{ typedef.args }}{% if typedef.is_protected %} <span class="m-label m-warning">protected</span>{% endif %}{% if typedef.since %} {{ typedef.since }}{% endif %}
               {% endif %}
               {# the empty line has to be here to prevent the lines from merging #}
 
index 89ce64aef96cfe979d313f212c8e246d312a73d6..da2edbdf607bd520585da18e6109c9dc94303756 100644 (file)
@@ -15,7 +15,7 @@
                 {% endif %}
               </div>
               {% endif %}
-              {%+ if var.is_static %}static {% endif %}{{ var.type }} {{ prefix }}<a href="#{{ var.id }}" class="m-doc-self">{{ var.name }}</a>{% if var.is_protected %} <span class="m-label m-warning">protected</span>{% endif %}{% if var.is_constexpr %} <span class="m-label m-primary">constexpr</span>{% endif %}
+              {%+ if var.is_static %}static {% endif %}{{ var.type }} {{ prefix }}<a href="#{{ var.id }}" class="m-doc-self">{{ var.name }}</a>{% if var.is_protected %} <span class="m-label m-warning">protected</span>{% endif %}{% if var.is_constexpr %} <span class="m-label m-primary">constexpr</span>{% endif %}{% if var.since %} {{ var.since }}{% endif %}
               {# the empty line needs to be here to prevent the lines from merging #}
 
               {% if var.include and compound.templates == None and var.templates == None %}
index 666f07d03ca01f5e0ba727f53a4162a7b647d956..a5fd53232ebdf214b172dbce2931ac899d7a242f 100644 (file)
@@ -4,6 +4,8 @@
 
 {% block header %}
         <h1>
-          {%+ for name, target in compound.breadcrumb[:-1] %}<span class="m-breadcrumb"><a href="{{ target }}">{{ name }}</a>/</span>{% endfor %}{{ compound.breadcrumb[-1][0] }}<span class="m-breadcrumb">/</span> <span class="m-thin">directory</span>
+          {%+ for name, target in compound.breadcrumb[:-1] %}<span class="m-breadcrumb"><a href="{{ target }}">{{ name }}</a>/</span>{% endfor %}{{ compound.breadcrumb[-1][0] }}<span class="m-breadcrumb">/</span> <span class="m-thin">directory</span>{% if compound.since %} {{ compound.since }}{% endif %}
+          {# need an explicit space here otherwise the newline gets removed #}
+
         </h1>
 {% endblock %}
index 2d8dcdd028057d7a62090c055c6fd82ba6dbfb14..fa291b5d0df1beeb5de06be4ec0dd07f9818532d 100644 (file)
@@ -3,7 +3,7 @@
               {% set j = joiner(', ') %}
               <div class="m-doc-template">template&lt;{% for t in class.templates %}{{ j() }}{{ t.type }}{% if t.name %} {{ t.name }}{% endif %}{% if t.default %} = {{ t.default }}{% endif %}{% endfor %}&gt;</div>
               {% endif %}
-              {{ class.kind }} <a href="{{ class.url }}" class="m-doc">{{ class.name }}</a>{% if class.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}{% if class.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% endif %}{% if class.is_final %} <span class="m-label m-flat m-warning">final</span>{% elif class.is_virtual %} <span class="m-label m-flat m-warning">virtual</span>{% endif %}
+              {{ class.kind }} <a href="{{ class.url }}" class="m-doc">{{ class.name }}</a>{% if class.deprecated %} <span class="m-label m-danger">{{ class.deprecated }}</span>{% endif %}{% if class.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% endif %}{% if class.is_final %} <span class="m-label m-flat m-warning">final</span>{% elif class.is_virtual %} <span class="m-label m-flat m-warning">virtual</span>{% endif %}{% if class.since %} {{ class.since }}{% endif %}
 
               {# the empty line is above to fix spacing #}
             </dt>
index c6a0334720c4e22208033dde3345c348f7de1594..c1972899c6a4d39ad21489600220d8dcd8df591c 100644 (file)
@@ -1,5 +1,5 @@
             <dt{% if not define.has_details and define.base_url == compound.url %} id="{{ define.id }}"{% endif %}>
               {% set j = joiner(',\n              ') %}
-              <span class="m-doc-wrap-bumper">#define <a href="{% if define.base_url != compound.url %}{{ define.base_url }}{% endif %}#{{ define.id }}" class="m-doc{% if not define.has_details and define.base_url == compound.url %}-self{% endif %}">{{ define.name }}</a>{% if define.params != None %}(</span><span class="m-doc-wrap">{% for param in define.params %}{{ j() }}{{ param[0] }}{% endfor %}){% endif %}{% if define.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}</span>
+              <span class="m-doc-wrap-bumper">#define <a href="{% if define.base_url != compound.url %}{{ define.base_url }}{% endif %}#{{ define.id }}" class="m-doc{% if not define.has_details and define.base_url == compound.url %}-self{% endif %}">{{ define.name }}</a>{% if define.params != None %}(</span><span class="m-doc-wrap">{% for param in define.params %}{{ j() }}{{ param[0] }}{% endfor %}){% endif %}{% if define.deprecated %} <span class="m-label m-danger">{{ define.deprecated }}</span>{% endif %}{% if define.since %} {{ define.since }}{% endif %}</span>
             </dt>
             <dd>{{ define.brief }}</dd>
index 39b475a4ab93468f112bc5e546c171c05e4a2efe..701d17ff142c8616e7b5ec626d8329050f1bea64 100644 (file)
@@ -1,2 +1,2 @@
-            <dt>directory <a href="{{ dir.url }}" class="m-doc">{{ dir.name }}</a>/{% if dir.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}</dt>
+            <dt>directory <a href="{{ dir.url }}" class="m-doc">{{ dir.name }}</a>/{% if dir.deprecated %} <span class="m-label m-danger">{{ dir.deprecated }}</span>{% endif %}{% if dir.since %} {{ dir.since }}{% endif %}</dt>
             <dd>{{ dir.brief }}</dd>
index dcfc5680f38631b91d43497eb0bb518deb7db0f4..e1cd2c1b239f2ed4bff0963c7135aed8d676d661 100644 (file)
@@ -1,5 +1,5 @@
             <dt{% if not enum.has_details and enum.base_url == compound.url %} id="{{ enum.id }}"{% endif %}>
               {% set j = joiner(',\n              ') %}
-              <span class="m-doc-wrap-bumper">enum {% if enum.is_strong %}class {% endif %}<a href="{% if enum.base_url != compound.url %}{{ enum.base_url }}{% endif %}#{{ enum.id }}" class="m-doc{% if not enum.has_details and enum.base_url == compound.url %}-self{% endif %}">{{ enum.name }}</a>{% if enum.type %}: {{ enum.type }}{% endif %} { </span><span class="m-doc-wrap">{% for value in enum.values %}{{ j() }}<a href="#{{ value.id }}" class="m-doc">{{ value.name }}</a>{% if value.initializer %} {{ value.initializer }}{% endif %}{% if value.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}{% endfor %} }{% if enum.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}{% if mark_nonpublic and enum.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% endif %}</span>
+              <span class="m-doc-wrap-bumper">enum {% if enum.is_strong %}class {% endif %}<a href="{% if enum.base_url != compound.url %}{{ enum.base_url }}{% endif %}#{{ enum.id }}" class="m-doc{% if not enum.has_details and enum.base_url == compound.url %}-self{% endif %}">{{ enum.name }}</a>{% if enum.type %}: {{ enum.type }}{% endif %} { </span><span class="m-doc-wrap">{% for value in enum.values %}{{ j() }}<a href="#{{ value.id }}" class="m-doc">{{ value.name }}</a>{% if value.initializer %} {{ value.initializer }}{% endif %}{% if value.since %} {{ value.since }}{% endif %}{% if value.deprecated %} <span class="m-label m-danger">{{ value.deprecated }}</span>{% endif %}{% endfor %} }{% if enum.deprecated %} <span class="m-label m-danger">{{ enum.deprecated }}</span>{% endif %}{% if mark_nonpublic and enum.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% endif %}{% if enum.since %} {{ enum.since }}{% endif %}</span>
             </dt>
             <dd>{{ enum.brief }}</dd>
index 908c5e1c5d58f682fc7d3e6592561fbd665dcb85..43a70c4ab99b0f917d36b2fb8b0c1120e179be26 100644 (file)
@@ -1,2 +1,2 @@
-            <dt>file <a href="{{ file.url }}" class="m-doc">{{ file.name }}</a>{% if file.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}</dt>
+            <dt>file <a href="{{ file.url }}" class="m-doc">{{ file.name }}</a>{% if file.deprecated %} <span class="m-label m-danger">{{ file.deprecated }}</span>{% endif %}{% if file.since %} {{ file.since }}{% endif %}</dt>
             <dd>{{ file.brief }}</dd>
index 80bd66789f8f660d1aa94247717fad4e37ce2de6..0738fe904d51cebaf6d020e07b43edc777879ce4 100644 (file)
@@ -4,6 +4,6 @@
               <div class="m-doc-template">template&lt;{% for t in func.templates %}{{ j() }}{{ t.type }}{% if t.name %} {{ t.name }}{% endif %}{% if t.default %} = {{ t.default }}{% endif %}{% endfor %}&gt;</div>
               {% endif %}
               {% set j = joiner(',\n              ') %}
-              <span class="m-doc-wrap-bumper">{{ func.prefix }}{% if func.type == 'void' %}void {% elif func.type %}auto {% endif %}<a href="{% if func.base_url != compound.url %}{{ func.base_url }}{% endif %}#{{ func.id }}" class="m-doc{% if not func.has_details and func.base_url == compound.url %}-self{% endif %}">{{ func.name }}</a>(</span><span class="m-doc-wrap">{% for param in func.params %}{{ j() }}{{ param.type_name }}{% if param.default %} = {{ param.default }}{% endif %}{% endfor %}){{ func.suffix }}{% if func.type and func.type != 'void' %} -&gt; {{ func.type }}{% endif %}{% if func.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}{% if not func.type or mark_nonpublic %}{% if func.is_protected %} <span class="m-label m-flat m-warning">protected{% if func.is_slot %} slot{% endif %}</span>{% elif func.is_private %} <span class="m-label m-flat m-danger">private{% if func.is_slot %} slot{% endif %}</span>{% elif func.is_signal %} <span class="m-label m-flat m-success">signal</span>{% elif func.is_slot %} <span class="m-label m-flat m-success">public slot</span>{% endif %}{% endif %}{% if func.is_defaulted %} <span class="m-label m-flat m-info">defaulted</span>{% endif %}{% if func.is_deleted %} <span class="m-label m-flat m-danger">deleted</span>{% endif %}{% if func.is_explicit %} <span class="m-label m-flat m-info">explicit</span> {% endif %}{% if func.is_final %} <span class="m-label m-flat m-warning">final</span>{% elif func.is_override %} <span class="m-label m-flat m-warning">override</span>{% elif func.is_pure_virtual %} <span class="m-label m-flat m-warning">pure virtual</span>{% elif func.is_virtual %} <span class="m-label m-flat m-warning">virtual</span>{% endif %}{% if func.is_constexpr %} <span class="m-label m-flat m-primary">constexpr</span>{% endif %}{% if func.is_conditional_noexcept %} <span class="m-label m-flat m-success">noexcept(…)</span>{% elif func.is_noexcept %} <span class="m-label m-flat m-success">noexcept</span>{% endif %}</span>
+              <span class="m-doc-wrap-bumper">{{ func.prefix }}{% if func.type == 'void' %}void {% elif func.type %}auto {% endif %}<a href="{% if func.base_url != compound.url %}{{ func.base_url }}{% endif %}#{{ func.id }}" class="m-doc{% if not func.has_details and func.base_url == compound.url %}-self{% endif %}">{{ func.name }}</a>(</span><span class="m-doc-wrap">{% for param in func.params %}{{ j() }}{{ param.type_name }}{% if param.default %} = {{ param.default }}{% endif %}{% endfor %}){{ func.suffix }}{% if func.type and func.type != 'void' %} -&gt; {{ func.type }}{% endif %}{% if func.deprecated %} <span class="m-label m-danger">{{ func.deprecated }}</span>{% endif %}{% if not func.type or mark_nonpublic %}{% if func.is_protected %} <span class="m-label m-flat m-warning">protected{% if func.is_slot %} slot{% endif %}</span>{% elif func.is_private %} <span class="m-label m-flat m-danger">private{% if func.is_slot %} slot{% endif %}</span>{% elif func.is_signal %} <span class="m-label m-flat m-success">signal</span>{% elif func.is_slot %} <span class="m-label m-flat m-success">public slot</span>{% endif %}{% endif %}{% if func.is_defaulted %} <span class="m-label m-flat m-info">defaulted</span>{% endif %}{% if func.is_deleted %} <span class="m-label m-flat m-danger">deleted</span>{% endif %}{% if func.is_explicit %} <span class="m-label m-flat m-info">explicit</span> {% endif %}{% if func.is_final %} <span class="m-label m-flat m-warning">final</span>{% elif func.is_override %} <span class="m-label m-flat m-warning">override</span>{% elif func.is_pure_virtual %} <span class="m-label m-flat m-warning">pure virtual</span>{% elif func.is_virtual %} <span class="m-label m-flat m-warning">virtual</span>{% endif %}{% if func.is_constexpr %} <span class="m-label m-flat m-primary">constexpr</span>{% endif %}{% if func.is_conditional_noexcept %} <span class="m-label m-flat m-success">noexcept(…)</span>{% elif func.is_noexcept %} <span class="m-label m-flat m-success">noexcept</span>{% endif %}{% if func.since %} {{ func.since }}{% endif %}</span>
             </dt>
             <dd>{{ func.brief }}</dd>
index 504066dea70e6a61a9b7eebf241427547bbc3bc6..78e0b81f7c8125086b729ee10325c5b16d769fea 100644 (file)
@@ -1,2 +1,2 @@
-            <dt>module <a href="{{ module.url }}" class="m-doc">{{ module.name }}</a>{% if module.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}</dt>
+            <dt>module <a href="{{ module.url }}" class="m-doc">{{ module.name }}</a>{% if module.deprecated %} <span class="m-label m-danger">{{ module.deprecated }}</span>{% endif %}{% if module.since %} {{ module.since }}{% endif %}</dt>
             <dd>{{ module.brief }}</dd>
index 83687525fb0cccefa3d5c565504dd8e111d18a84..9e90087bafc1e5a124a0a8817be0984b09565b3d 100644 (file)
@@ -1,2 +1,2 @@
-            <dt>namespace <a href="{{ namespace.url }}" class="m-doc">{{ namespace.name }}</a>{% if namespace.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}</dt>
+            <dt>namespace <a href="{{ namespace.url }}" class="m-doc">{{ namespace.name }}</a>{% if namespace.deprecated %} <span class="m-label m-danger">{{ namespace.deprecated }}</span>{% endif %}{% if namespace.since %} {{ namespace.since }}{% endif %}</dt>
             <dd>{{ namespace.brief }}</dd>
index e2395d0f675998fa1aed17869e8d15de11c306d0..5285beeeb0f260dc2659ea44e8f7f17c752d2606 100644 (file)
@@ -3,7 +3,7 @@
               {% set j = joiner(', ') %}
               <div class="m-doc-template">template&lt;{% for t in typedef.templates %}{{ j() }}{{ t.type }}{% if t.name %} {{ t.name }}{% endif %}{% if t.default %} = {{ t.default }}{% endif%}{% endfor %}&gt;</div>
               {% endif %}
-              using <a href="{% if typedef.base_url != compound.url %}{{ typedef.base_url }}{% endif %}#{{ typedef.id }}" class="m-doc{% if not typedef.has_details and typedef.base_url == compound.url %}-self{% endif %}">{{ typedef.name }}</a> = {{ typedef.type }}{{ typedef.args }}{% if typedef.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}{% if mark_nonpublic and typedef.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% endif %}
+              using <a href="{% if typedef.base_url != compound.url %}{{ typedef.base_url }}{% endif %}#{{ typedef.id }}" class="m-doc{% if not typedef.has_details and typedef.base_url == compound.url %}-self{% endif %}">{{ typedef.name }}</a> = {{ typedef.type }}{{ typedef.args }}{% if typedef.deprecated %} <span class="m-label m-danger">{{ typedef.deprecated }}</span>{% endif %}{% if mark_nonpublic and typedef.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% endif %}{% if typedef.since %} {{ typedef.since }}{% endif %}
               {# This empty line needs to be there otherwise it's eaten #}
 
             </dt>
index a1740271b786a28db0680c4ebf2fb66c0b174ae9..52f21d494ccec3f39d2f6da5852999a47eb32ed9 100644 (file)
@@ -3,7 +3,7 @@
               {% set j = joiner(', ') %}
               <div class="m-doc-template">template&lt;{% for t in var.templates %}{{ j() }}{{ t.type }}{% if t.name %} {{ t.name }}{% endif %}{% if t.default %} = {{ t.default }}{% endif%}{% endfor %}&gt;</div>
               {% endif %}
-              {%+ if var.is_static %}static {% endif %}{{ var.type }} <a href="{% if var.base_url != compound.url %}{{ var.base_url }}{% endif %}#{{ var.id }}" class="m-doc{% if not var.has_details and var.base_url == compound.url %}-self{% endif %}">{{ var.name }}</a>{% if var.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}{% if mark_nonpublic and var.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% endif %}{% if var.is_constexpr %} <span class="m-label m-flat m-primary">constexpr</span>{% endif %}
+              {%+ if var.is_static %}static {% endif %}{{ var.type }} <a href="{% if var.base_url != compound.url %}{{ var.base_url }}{% endif %}#{{ var.id }}" class="m-doc{% if not var.has_details and var.base_url == compound.url %}-self{% endif %}">{{ var.name }}</a>{% if var.deprecated %} <span class="m-label m-danger">{{ var.deprecated }}</span>{% endif %}{% if mark_nonpublic and var.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% endif %}{% if var.is_constexpr %} <span class="m-label m-flat m-primary">constexpr</span>{% endif %}{% if var.since %} {{ var.since }}{% endif %}
               {# This empty line needs to be there otherwise it's eaten #}
 
             </dt>
index 126ccaa5f0f18d30c0db57c747719a0b9880a40c..2427983b2975f734d198013cd49d604995cedbb9 100644 (file)
@@ -4,6 +4,8 @@
 
 {% block header %}
         <h1>
-          {%+ for name, target in compound.breadcrumb[:-1] %}<span class="m-breadcrumb"><a href="{{ target }}">{{ name }}</a>/</span>{% endfor %}{{ compound.breadcrumb[-1][0] }} <span class="m-thin">file</span>
+          {%+ for name, target in compound.breadcrumb[:-1] %}<span class="m-breadcrumb"><a href="{{ target }}">{{ name }}</a>/</span>{% endfor %}{{ compound.breadcrumb[-1][0] }} <span class="m-thin">file</span>{% if compound.since %} {{ compound.since }}{% endif %}
+          {# need an explicit space here otherwise the newline gets removed #}
+
         </h1>
 {% endblock %}
index 972ca7d07747171b1fc4db1e39219c88f8e7103d..7400a5d18f31e9a7039ba4634a31540496646327 100644 (file)
@@ -7,13 +7,13 @@
           {% for i in index.files recursive %}
           {% if i.children %}
           <li class="m-doc-collapsible{% if loop.depth > M_FILE_TREE_EXPAND_LEVELS %} collapsed{% endif %}">
-            <a href="#" onclick="return toggle(this)">{{ i.kind }}</a> <a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %} <span class="m-doc">{{ i.brief }}</span>
+            <a href="#" onclick="return toggle(this)">{{ i.kind }}</a> <a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.deprecated %} <span class="m-label m-danger">{{ i.deprecated }}</span>{% endif %}{% if i.since %} {{ i.since }}{% endif %} <span class="m-doc">{{ i.brief }}</span>
             <ul class="m-doc">
 {{ loop(i.children)|rtrim|indent(4, true) }}
             </ul>
           </li>
           {% else %}
-          <li>{{ i.kind }} <a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %} <span class="m-doc">{{ i.brief }}</span></li>
+          <li>{{ i.kind }} <a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.deprecated %} <span class="m-label m-danger">{{ i.deprecated }}</span>{% endif %}{% if i.since %} {{ i.since }}{% endif %} <span class="m-doc">{{ i.brief }}</span></li>
           {% endif %}
           {% endfor %}
         </ul>
index 991657fb03c0158cefbeaf8b45a0b59be93f0018..86b34d2a26ff087ea3f223e197ce07ddd31d5778 100644 (file)
@@ -7,5 +7,5 @@
           {% for name, target in compound.breadcrumb[:-1] %}
           <span class="m-breadcrumb"><a href="{{ target }}">{{ name }}</a> &raquo;</span>
           {% endfor %}
-          {{ compound.breadcrumb[-1][0] }} <span class="m-thin">module</span></h1>
+          {{ compound.breadcrumb[-1][0] }} <span class="m-thin">module</span>{% if compound.since %} {{ compound.since }}{% endif %}</h1>
 {% endblock %}
index 8487a1bd6b40a0a954f39af872583e10e71841ef..a8547112456039348366a6be00c33da1ab22d8a8 100644 (file)
@@ -7,13 +7,13 @@
           {% for i in index.modules recursive %}
           {% if i.has_nestable_children %}
           <li class="m-doc-collapsible">
-            <a href="#" onclick="return toggle(this)">module</a> <a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %} <span class="m-doc">{{ i.brief }}</span>
+            <a href="#" onclick="return toggle(this)">module</a> <a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.deprecated %} <span class="m-label m-danger">{{ i.deprecated }}</span>{% endif %}{% if i.since %} {{ i.since }}{% endif %} <span class="m-doc">{{ i.brief }}</span>
             <ul class="m-doc">
 {{ loop(i.children)|rtrim|indent(4, true) }}
             </ul>
           </li>
           {% else %}
-          <li>module <a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %} <span class="m-doc">{{ i.brief }}</span></li>
+          <li>module <a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.deprecated %} <span class="m-label m-danger">{{ i.deprecated }}</span>{% endif %}{% if i.since %} {{ i.since }}{% endif %} <span class="m-doc">{{ i.brief }}</span></li>
           {% endif %}
           {% endfor %}
         </ul>
index e5925ade61fdf2accf039b255079c6502d9f2c33..9cab47fccad1f2edd80ad584751e9f7fc61aba4d 100644 (file)
@@ -4,7 +4,9 @@
 
 {% block header %}
         <h1>
-          {%+ for name, target in compound.breadcrumb[:-1] %}<span class="m-breadcrumb"><a href="{{ target }}">{{ name }}</a>::<wbr/></span>{% endfor %}{{ compound.breadcrumb[-1][0] }} <span class="m-thin">namespace</span>
+          {%+ for name, target in compound.breadcrumb[:-1] %}<span class="m-breadcrumb"><a href="{{ target }}">{{ name }}</a>::<wbr/></span>{% endfor %}{{ compound.breadcrumb[-1][0] }} <span class="m-thin">namespace</span>{% if compound.since %} {{ compound.since }}{% endif %}
+          {# need an explicit space here otherwise the newline gets removed #}
+
           {% if compound.include %}
           <div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="{{ compound.include[1] }}">{{ compound.include[0] }}</a></div>
           {% endif %}
index 986ab38c8141c843243463ced8d62b7bcf3ce755..5ff416bff5e7895f083afd2e03536883861faa7d 100644 (file)
@@ -7,13 +7,13 @@
           {% for i in index.symbols|selectattr('kind', 'equalto', 'namespace') recursive %}
           {% if i.has_nestable_children %}
           <li class="m-doc-collapsible">
-            <a href="#" onclick="return toggle(this)">{{ i.kind }}</a> <a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %} <span class="m-doc">{{ i.brief }}</span>
+            <a href="#" onclick="return toggle(this)">{{ i.kind }}</a> <a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.deprecated %} <span class="m-label m-danger">{{ i.deprecated }}</span>{% endif %}{% if i.since %} {{ i.since }}{% endif %} <span class="m-doc">{{ i.brief }}</span>
             <ul class="m-doc">
 {{ loop(i.children|selectattr('kind', 'equalto', 'namespace'))|rtrim|indent(4, true) }}
             </ul>
           </li>
           {% else %}
-          <li>{{ i.kind }} <a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %} <span class="m-doc">{{ i.brief }}</span></li>
+          <li>{{ i.kind }} <a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.deprecated %} <span class="m-label m-danger">{{ i.deprecated }}</span>{% endif %}{% if i.since %} {{ i.since }}{% endif %} <span class="m-doc">{{ i.brief }}</span></li>
           {% endif %}
           {% endfor %}
         </ul>
index 473d30f339a54e8692528ae951094b5adfd06803..8494f253801d59ba8b915bd3710b7b766e55fd77 100644 (file)
@@ -16,7 +16,9 @@
           {% for name, target in compound.breadcrumb[:-1] %}
           <span class="m-breadcrumb"><a href="{{ target }}">{{ name }}</a> &raquo;</span>
           {% endfor %}
-          {{ compound.breadcrumb[-1][0] }}
+          {{ compound.breadcrumb[-1][0] }}{% if compound.since %} {{ compound.since }}{% endif %}
+          {# need an explicit space here otherwise the newline gets removed #}
+
         </h1>
         {% if compound.brief %}
         <p>{{ compound.brief }}</p>
index 8d52dd8a9c210ab1ea42c61daf5946b8ab620da9..46bf87b8a50759e63a5e27af636aa137c23381c0 100644 (file)
@@ -7,13 +7,13 @@
           {% for i in index.pages recursive %}
           {% if i.children %}
           <li class="m-doc-collapsible">
-            <a href="#" onclick="return toggle(this)"></a><a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %} <span class="m-doc">{{ i.brief }}</span>
+            <a href="#" onclick="return toggle(this)"></a><a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.deprecated %} <span class="m-label m-danger">{{ i.deprecated }}</span>{% endif %}{% if i.since %} {{ i.since }}{% endif %} <span class="m-doc">{{ i.brief }}</span>
             <ul class="m-doc">
 {{ loop(i.children)|rtrim|indent(4, true) }}
             </ul>
           </li>
           {% else %}
-          <li><a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %} <span class="m-doc">{{ i.brief }}</span></li>
+          <li><a href="{{ i.url }}" class="m-doc">{{ i.name }}</a>{% if i.deprecated %} <span class="m-label m-danger">{{ i.deprecated }}</span>{% endif %}{% if i.since %} {{ i.since }}{% endif %} <span class="m-doc">{{ i.brief }}</span></li>
           {% endif %}
           {% endfor %}
         </ul>
diff --git a/documentation/test_doxygen/compound_since/Class_8h.html b/documentation/test_doxygen/compound_since/Class_8h.html
new file mode 100644 (file)
index 0000000..286705d
--- /dev/null
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>Directory/Class.h file | 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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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="dir_4b0d5f8864bf89936129251a2d32609b.html">Directory</a>/</span>Class.h <span class="m-thin">file</span> <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a>
+        </h1>
+        <p>Pretty old things.</p>
+        <div class="m-block m-default">
+          <h3>Contents</h3>
+          <ul>
+            <li>
+              Reference
+              <ul>
+                <li><a href="#namespaces">Namespaces</a></li>
+                <li><a href="#nested-classes">Classes</a></li>
+                <li><a href="#define-members">Defines</a></li>
+              </ul>
+            </li>
+          </ul>
+        </div>
+        <section id="namespaces">
+          <h2><a href="#namespaces">Namespaces</a></h2>
+          <dl class="m-doc">
+            <dt>namespace <a href="namespaceFoo.html" class="m-doc">Foo</a> <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a></dt>
+            <dd>A namespace.</dd>
+          </dl>
+        </section>
+        <section id="nested-classes">
+          <h2><a href="#nested-classes">Classes</a></h2>
+          <dl class="m-doc">
+            <dt>
+              class <a href="classFoo_1_1Class.html" class="m-doc">Foo::Class</a> <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a>
+            </dt>
+            <dd>A class.</dd>
+            <dt>
+              struct <a href="structFoo_1_1Subclass.html" class="m-doc">Foo::Subclass</a> <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a>
+            </dt>
+            <dd>A subclass.</dd>
+          </dl>
+        </section>
+        <section id="define-members">
+          <h2><a href="#define-members">Defines</a></h2>
+          <dl class="m-doc">
+            <dt>
+              <span class="m-doc-wrap-bumper">#define <a href="#a144a2a84c08d05de76f6a4a245584810" class="m-doc">A_DEFINE</a> <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a></span>
+            </dt>
+            <dd>A define.</dd>
+          </dl>
+        </section>
+        <section>
+          <h2>Define documentation</h2>
+          <section class="m-doc-details" id="a144a2a84c08d05de76f6a4a245584810"><div>
+            <h3>
+              <span class="m-doc-wrap-bumper">#define <a href="#a144a2a84c08d05de76f6a4a245584810" class="m-doc-self">A_DEFINE</a> <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a></span>
+            </h3>
+            <p>A define.</p>
+<p>Details should have the badge too.</p>
+          </div></section>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/DeprecatedClass_8h.html b/documentation/test_doxygen/compound_since/DeprecatedClass_8h.html
new file mode 100644 (file)
index 0000000..5b3bce6
--- /dev/null
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>DeprecatedDirectory/DeprecatedClass.h file | 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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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="dir_73d1500434dee6f1c83b12ee799c54af.html">DeprecatedDirectory</a>/</span>DeprecatedClass.h <span class="m-thin">file</span>
+        </h1>
+        <p>Pretty old things.</p>
+        <div class="m-block m-default">
+          <h3>Contents</h3>
+          <ul>
+            <li>
+              Reference
+              <ul>
+                <li><a href="#namespaces">Namespaces</a></li>
+                <li><a href="#nested-classes">Classes</a></li>
+                <li><a href="#define-members">Defines</a></li>
+              </ul>
+            </li>
+          </ul>
+        </div>
+<aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000002" class="m-doc">Deprecated since 2010.02</a></h4><p>Yes it is.</p></aside>
+        <section id="namespaces">
+          <h2><a href="#namespaces">Namespaces</a></h2>
+          <dl class="m-doc">
+            <dt>namespace <a href="namespaceDeprecatedFoo.html" class="m-doc">DeprecatedFoo</a> <span class="m-label m-danger">deprecated since 2010.02</span></dt>
+            <dd>A namespace.</dd>
+          </dl>
+        </section>
+        <section id="nested-classes">
+          <h2><a href="#nested-classes">Classes</a></h2>
+          <dl class="m-doc">
+            <dt>
+              class <a href="classDeprecatedFoo_1_1DeprecatedClass.html" class="m-doc">DeprecatedFoo::DeprecatedClass</a> <span class="m-label m-danger">deprecated since 2010.02</span>
+            </dt>
+            <dd>A class.</dd>
+            <dt>
+              struct <a href="structDeprecatedFoo_1_1DeprecatedSubclass.html" class="m-doc">DeprecatedFoo::DeprecatedSubclass</a> <span class="m-label m-danger">deprecated since 2010.02</span>
+            </dt>
+            <dd>A subclass.</dd>
+          </dl>
+        </section>
+        <section id="define-members">
+          <h2><a href="#define-members">Defines</a></h2>
+          <dl class="m-doc">
+            <dt>
+              <span class="m-doc-wrap-bumper">#define <a href="#ac72c6c984074fb4cfc0f3fa070f8514d" class="m-doc">DEPRECATED_DEFINE</a> <span class="m-label m-danger">deprecated since 2010.02</span></span>
+            </dt>
+            <dd>A define.</dd>
+          </dl>
+        </section>
+        <section>
+          <h2>Define documentation</h2>
+          <section class="m-doc-details" id="ac72c6c984074fb4cfc0f3fa070f8514d"><div>
+            <h3>
+              <span class="m-doc-wrap-bumper">#define <a href="#ac72c6c984074fb4cfc0f3fa070f8514d" class="m-doc-self">DEPRECATED_DEFINE</a></span>
+            </h3>
+            <p>A define.</p>
+<aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000004" class="m-doc">Deprecated since 2010.02</a></h4><p>Yes it is.</p></aside><p>Details should have the badge too.</p>
+          </div></section>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/DeprecatedDirectory/DeprecatedClass.h b/documentation/test_doxygen/compound_since/DeprecatedDirectory/DeprecatedClass.h
new file mode 100644 (file)
index 0000000..1a4284d
--- /dev/null
@@ -0,0 +1,81 @@
+/** @dir DeprecatedDirectory
+ * @brief A dir with pretty old things.
+ * @m_deprecated_since{2010,02} Yes it is.
+ */
+
+/** @file
+ * @brief Pretty old things.
+ * @m_deprecated_since{2010,02} Yes it is.
+ */
+
+/**
+@brief A namespace
+@m_deprecated_since{2010,02} Yes it is.
+*/
+namespace DeprecatedFoo {
+
+/**
+@brief A class
+@m_deprecated_since{2010,02} Yes it is.
+*/
+class DeprecatedClass {};
+
+/**
+@brief A subclass
+@m_deprecated_since{2010,02} Yes it is.
+*/
+struct DeprecatedSubclass: DeprecatedClass {};
+
+/**
+@brief A function
+@m_deprecated_since{2010,02} Yes it is.
+
+Details should have the badge too.
+*/
+void deprecatedFoo();
+
+/**
+@brief A typedef
+@m_deprecated_since{2010,02} Yes it is.
+
+Details should have the badge too.
+*/
+typedef DeprecatedClass DeprecatedKlazz;
+
+/**
+@brief An enum
+@m_deprecated_since{2010,02} Yes it is.
+
+Details should have the badge too.
+*/
+enum DeprecatedEnum {
+    /**
+     * This thing is deprecated.
+     *
+     * Yes.
+     *
+     * @m_deprecated_since{2010,02} Yes it is.
+     */
+    DeprecatedOldValue = 0,
+
+    /* Some other. */
+    NewValue = 3
+};
+
+/**
+@brief A constant
+@m_deprecated_since{2010,02} Yes it is.
+
+Details should have the badge too.
+*/
+constexpr int DeprecatedFive = 5;
+
+}
+
+/**
+@brief A define
+@m_deprecated_since{2010,02} Yes it is.
+
+Details should have the badge too.
+*/
+#define DEPRECATED_DEFINE
diff --git a/documentation/test_doxygen/compound_since/Directory/Class.h b/documentation/test_doxygen/compound_since/Directory/Class.h
new file mode 100644 (file)
index 0000000..998f1bc
--- /dev/null
@@ -0,0 +1,81 @@
+/* WHAT THE FUCK DOXYGEN WHY IS THIS MATCHING THE NAME PARTIALLY?! WHAT */
+/** @dir compound_since/Directory
+ * @brief A dir with pretty old things.
+ * @m_since{2010,02}
+ */
+
+/** @file
+ * @brief Pretty old things.
+ * @m_since{2010,02}
+ */
+
+/**
+@brief A namespace
+@m_since{2010,02}
+*/
+namespace Foo {
+
+/**
+@brief A class
+@m_since{2019,11}
+*/
+class Class {};
+
+/**
+@brief A subclass
+@m_since{2019,11}
+*/
+struct Subclass: Class {};
+
+/**
+@brief A function
+@m_since{2010,02}
+
+Details should have the badge too.
+*/
+void foo();
+
+/**
+@brief A typedef
+@m_since{2010,02}
+
+Details should have the badge too.
+*/
+typedef Class Klazz;
+
+/**
+@brief An enum
+@m_since{2010,02}
+
+Details should have the badge too.
+*/
+enum Enum {
+    OldValue = 0,
+
+    /**
+     * This thing is new.
+     *
+     * Yes.
+     *
+     * @m_since{2019,11}
+     */
+    NewValue = 3
+};
+
+/**
+@brief A constant
+@m_since{2010,02}
+
+Details should have the badge too.
+*/
+constexpr int Five = 5;
+
+}
+
+/**
+@brief A define
+@m_since{2010,02}
+
+Details should have the badge too.
+*/
+#define A_DEFINE
diff --git a/documentation/test_doxygen/compound_since/Doxyfile b/documentation/test_doxygen/compound_since/Doxyfile
new file mode 100644 (file)
index 0000000..2bd734b
--- /dev/null
@@ -0,0 +1,19 @@
+INPUT                   = Directory/Class.h DeprecatedDirectory/DeprecatedClass.h pages.dox
+QUIET                   = YES
+GENERATE_HTML           = NO
+GENERATE_LATEX          = NO
+GENERATE_XML            = YES
+XML_PROGRAMLISTING      = NO
+CASE_SENSE_NAMES        = YES
+
+##! M_PAGE_FINE_PRINT   =
+##! M_THEME_COLOR       =
+##! M_FAVICON           =
+##! M_LINKS_NAVBAR1     = pages namespaces modules
+##! M_SEARCH_DISABLED   = YES
+##! M_VERSION_LABELS    = YES
+
+ALIASES = \
+    "m_class{1}=@xmlonly<mcss:class xmlns:mcss=\"http://mcss.mosra.cz/doxygen/\" mcss:class=\"\1\" />@endxmlonly" \
+    "m_since{2}=@since @m_class{m-label m-success m-flat} @ref changelog-\1-\2 \"since \1.\2\"" \
+    "m_deprecated_since{2}=@since deprecated since \1.\2 @deprecated"
diff --git a/documentation/test_doxygen/compound_since/a.html b/documentation/test_doxygen/compound_since/a.html
new file mode 100644 (file)
index 0000000..33a9ae2
--- /dev/null
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>This is new. | 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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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>
+          This is new. <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a>
+        </h1>
+<p>Yes.</p>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/annotated.html b/documentation/test_doxygen/compound_since/annotated.html
new file mode 100644 (file)
index 0000000..8a00a8d
--- /dev/null
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <li><a href="annotated.html" id="m-navbar-current">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>Classes</h2>
+        <ul class="m-doc">
+          <li class="m-doc-collapsible">
+            <a href="#" onclick="return toggle(this)">namespace</a> <a href="namespaceDeprecatedFoo.html" class="m-doc">DeprecatedFoo</a> <span class="m-label m-danger">deprecated since 2010.02</span> <span class="m-doc">A namespace.</span>
+            <ul class="m-doc">
+              <li>class <a href="classDeprecatedFoo_1_1DeprecatedClass.html" class="m-doc">DeprecatedClass</a> <span class="m-label m-danger">deprecated since 2010.02</span> <span class="m-doc">A class.</span></li>
+              <li>struct <a href="structDeprecatedFoo_1_1DeprecatedSubclass.html" class="m-doc">DeprecatedSubclass</a> <span class="m-label m-danger">deprecated since 2010.02</span> <span class="m-doc">A subclass.</span></li>
+            </ul>
+          </li>
+          <li class="m-doc-collapsible">
+            <a href="#" onclick="return toggle(this)">namespace</a> <a href="namespaceFoo.html" class="m-doc">Foo</a> <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a> <span class="m-doc">A namespace.</span>
+            <ul class="m-doc">
+              <li>class <a href="classFoo_1_1Class.html" class="m-doc">Class</a> <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a> <span class="m-doc">A class.</span></li>
+              <li>struct <a href="structFoo_1_1Subclass.html" class="m-doc">Subclass</a> <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a> <span class="m-doc">A subclass.</span></li>
+            </ul>
+          </li>
+        </ul>
+        <script>
+        function toggle(e) {
+            e.parentElement.className = e.parentElement.className == 'm-doc-collapsible' ?
+                'm-doc-expansible' : 'm-doc-collapsible';
+            return false;
+        }
+        /* Collapse all nodes marked as such. Doing it via JS instead of
+           directly in markup so disabling it doesn't harm usability. The list
+           is somehow regenerated on every iteration and shrinks as I change
+           the classes. It's not documented anywhere and I'm not sure if this
+           is the same across browsers, so I am going backwards in that list to
+           be sure. */
+        var collapsed = document.getElementsByClassName("collapsed");
+        for(var i = collapsed.length - 1; i >= 0; --i)
+            collapsed[i].className = 'm-doc-expansible';
+        </script>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/classDeprecatedFoo_1_1DeprecatedClass.html b/documentation/test_doxygen/compound_since/classDeprecatedFoo_1_1DeprecatedClass.html
new file mode 100644 (file)
index 0000000..8479e40
--- /dev/null
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>DeprecatedFoo::DeprecatedClass class | 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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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="namespaceDeprecatedFoo.html">DeprecatedFoo</a>::<wbr/></span>DeprecatedClass <span class="m-thin">class</span>
+          <div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="DeprecatedClass_8h.html">&lt;DeprecatedDirectory/DeprecatedClass.h&gt;</a></div>
+        </h1>
+        <p>A class.</p>
+<aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000005" class="m-doc">Deprecated since 2010.02</a></h4><p>Yes it is.</p></aside>
+        <section id="derived-classes">
+          <h2><a href="#derived-classes">Derived classes</a></h2>
+          <dl class="m-doc">
+            <dt>
+              struct <a href="structDeprecatedFoo_1_1DeprecatedSubclass.html" class="m-doc">DeprecatedSubclass</a> <span class="m-label m-danger">deprecated since 2010.02</span>
+            </dt>
+            <dd>A subclass.</dd>
+          </dl>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/classFoo_1_1Class.html b/documentation/test_doxygen/compound_since/classFoo_1_1Class.html
new file mode 100644 (file)
index 0000000..e4bf101
--- /dev/null
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>Foo::Class class | 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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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="namespaceFoo.html">Foo</a>::<wbr/></span>Class <span class="m-thin">class</span> <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a>
+          <div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="Class_8h.html">&lt;Directory/Class.h&gt;</a></div>
+        </h1>
+        <p>A class.</p>
+        <section id="derived-classes">
+          <h2><a href="#derived-classes">Derived classes</a></h2>
+          <dl class="m-doc">
+            <dt>
+              struct <a href="structFoo_1_1Subclass.html" class="m-doc">Subclass</a> <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a>
+            </dt>
+            <dd>A subclass.</dd>
+          </dl>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/deprecated-a.html b/documentation/test_doxygen/compound_since/deprecated-a.html
new file mode 100644 (file)
index 0000000..7ec5e08
--- /dev/null
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>This is old. | 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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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>
+          This is old.
+        </h1>
+<p>Yes.</p><aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000012" class="m-doc">Deprecated since 2010.02</a></h4><p>Yes it is.</p></aside>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/dir_4b0d5f8864bf89936129251a2d32609b.html b/documentation/test_doxygen/compound_since/dir_4b0d5f8864bf89936129251a2d32609b.html
new file mode 100644 (file)
index 0000000..894d6e8
--- /dev/null
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>Directory/ directory | 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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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>
+          Directory<span class="m-breadcrumb">/</span> <span class="m-thin">directory</span> <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a>
+        </h1>
+        <p>A dir with pretty old things.</p>
+        <div class="m-block m-default">
+          <h3>Contents</h3>
+          <ul>
+            <li>
+              Reference
+              <ul>
+                <li><a href="#files">Files</a></li>
+              </ul>
+            </li>
+          </ul>
+        </div>
+        <section id="files">
+          <h2><a href="#files">Files</a></h2>
+          <dl class="m-doc">
+            <dt>file <a href="Class_8h.html" class="m-doc">Class.h</a> <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a></dt>
+            <dd>Pretty old things.</dd>
+          </dl>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/dir_73d1500434dee6f1c83b12ee799c54af.html b/documentation/test_doxygen/compound_since/dir_73d1500434dee6f1c83b12ee799c54af.html
new file mode 100644 (file)
index 0000000..4c56516
--- /dev/null
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>DeprecatedDirectory/ directory | 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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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>
+          DeprecatedDirectory<span class="m-breadcrumb">/</span> <span class="m-thin">directory</span>
+        </h1>
+        <p>A dir with pretty old things.</p>
+        <div class="m-block m-default">
+          <h3>Contents</h3>
+          <ul>
+            <li>
+              Reference
+              <ul>
+                <li><a href="#files">Files</a></li>
+              </ul>
+            </li>
+          </ul>
+        </div>
+<aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000001" class="m-doc">Deprecated since 2010.02</a></h4><p>Yes it is.</p></aside>
+        <section id="files">
+          <h2><a href="#files">Files</a></h2>
+          <dl class="m-doc">
+            <dt>file <a href="DeprecatedClass_8h.html" class="m-doc">DeprecatedClass.h</a> <span class="m-label m-danger">deprecated since 2010.02</span></dt>
+            <dd>Pretty old things.</dd>
+          </dl>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/files.html b/documentation/test_doxygen/compound_since/files.html
new file mode 100644 (file)
index 0000000..e49e391
--- /dev/null
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <li><a href="annotated.html">Classes</a></li>
+            <li><a href="files.html" id="m-navbar-current">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>Files</h2>
+        <ul class="m-doc">
+          <li class="m-doc-collapsible">
+            <a href="#" onclick="return toggle(this)">dir</a> <a href="dir_73d1500434dee6f1c83b12ee799c54af.html" class="m-doc">DeprecatedDirectory</a> <span class="m-label m-danger">deprecated since 2010.02</span> <span class="m-doc">A dir with pretty old things.</span>
+            <ul class="m-doc">
+              <li>file <a href="DeprecatedClass_8h.html" class="m-doc">DeprecatedClass.h</a> <span class="m-label m-danger">deprecated since 2010.02</span> <span class="m-doc">Pretty old things.</span></li>
+            </ul>
+          </li>
+          <li class="m-doc-collapsible">
+            <a href="#" onclick="return toggle(this)">dir</a> <a href="dir_4b0d5f8864bf89936129251a2d32609b.html" class="m-doc">Directory</a> <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a> <span class="m-doc">A dir with pretty old things.</span>
+            <ul class="m-doc">
+              <li>file <a href="Class_8h.html" class="m-doc">Class.h</a> <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a> <span class="m-doc">Pretty old things.</span></li>
+            </ul>
+          </li>
+        </ul>
+        <script>
+        function toggle(e) {
+            e.parentElement.className = e.parentElement.className == 'm-doc-collapsible' ?
+                'm-doc-expansible' : 'm-doc-collapsible';
+            return false;
+        }
+        /* Collapse all nodes marked as such. Doing it via JS instead of
+           directly in markup so disabling it doesn't harm usability. The list
+           is somehow regenerated on every iteration and shrinks as I change
+           the classes. It's not documented anywhere and I'm not sure if this
+           is the same across browsers, so I am going backwards in that list to
+           be sure. */
+        var collapsed = document.getElementsByClassName("collapsed");
+        for(var i = collapsed.length - 1; i >= 0; --i)
+            collapsed[i].className = 'm-doc-expansible';
+        </script>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/group__deprecated-group.html b/documentation/test_doxygen/compound_since/group__deprecated-group.html
new file mode 100644 (file)
index 0000000..64bfdce
--- /dev/null
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>A group module | 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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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>
+          A group <span class="m-thin">module</span></h1>
+        <div class="m-block m-default">
+          <h3>Contents</h3>
+          <ul>
+            <li>
+              Reference
+              <ul>
+                <li><a href="#groups">Modules</a></li>
+              </ul>
+            </li>
+          </ul>
+        </div>
+<aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000013" class="m-doc">Deprecated since 2010.02</a></h4><p>Yes it is.</p></aside><p>Detailed description.</p>
+        <section id="groups">
+          <h2><a href="#groups">Modules</a></h2>
+          <dl class="m-doc">
+            <dt>module <a href="group__deprecated-subgroup.html" class="m-doc">A subgroup</a> <span class="m-label m-danger">deprecated since 2019.11</span></dt>
+            <dd></dd>
+          </dl>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/group__group.html b/documentation/test_doxygen/compound_since/group__group.html
new file mode 100644 (file)
index 0000000..2cc969d
--- /dev/null
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>A group module | 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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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>
+          A group <span class="m-thin">module</span> <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a></h1>
+        <div class="m-block m-default">
+          <h3>Contents</h3>
+          <ul>
+            <li>
+              Reference
+              <ul>
+                <li><a href="#groups">Modules</a></li>
+              </ul>
+            </li>
+          </ul>
+        </div>
+<p>Detailed description.</p>
+        <section id="groups">
+          <h2><a href="#groups">Modules</a></h2>
+          <dl class="m-doc">
+            <dt>module <a href="group__subgroup.html" class="m-doc">A subgroup</a> <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a></dt>
+            <dd></dd>
+          </dl>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/modules.html b/documentation/test_doxygen/compound_since/modules.html
new file mode 100644 (file)
index 0000000..0c49d81
--- /dev/null
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html" id="m-navbar-current">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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>Modules</h2>
+        <ul class="m-doc">
+          <li class="m-doc-collapsible">
+            <a href="#" onclick="return toggle(this)">module</a> <a href="group__group.html" class="m-doc">A group</a> <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a> <span class="m-doc"></span>
+            <ul class="m-doc">
+              <li>module <a href="group__subgroup.html" class="m-doc">A subgroup</a> <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a> <span class="m-doc"></span></li>
+            </ul>
+          </li>
+          <li class="m-doc-collapsible">
+            <a href="#" onclick="return toggle(this)">module</a> <a href="group__deprecated-group.html" class="m-doc">A group</a> <span class="m-label m-danger">deprecated since 2010.02</span> <span class="m-doc"></span>
+            <ul class="m-doc">
+              <li>module <a href="group__deprecated-subgroup.html" class="m-doc">A subgroup</a> <span class="m-label m-danger">deprecated since 2019.11</span> <span class="m-doc"></span></li>
+            </ul>
+          </li>
+        </ul>
+        <script>
+        function toggle(e) {
+            e.parentElement.className = e.parentElement.className == 'm-doc-collapsible' ?
+                'm-doc-expansible' : 'm-doc-collapsible';
+            return false;
+        }
+        /* Collapse all nodes marked as such. Doing it via JS instead of
+           directly in markup so disabling it doesn't harm usability. The list
+           is somehow regenerated on every iteration and shrinks as I change
+           the classes. It's not documented anywhere and I'm not sure if this
+           is the same across browsers, so I am going backwards in that list to
+           be sure. */
+        var collapsed = document.getElementsByClassName("collapsed");
+        for(var i = collapsed.length - 1; i >= 0; --i)
+            collapsed[i].className = 'm-doc-expansible';
+        </script>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/namespaceDeprecatedFoo.html b/documentation/test_doxygen/compound_since/namespaceDeprecatedFoo.html
new file mode 100644 (file)
index 0000000..6373de2
--- /dev/null
@@ -0,0 +1,174 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>DeprecatedFoo namespace | 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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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>
+          DeprecatedFoo <span class="m-thin">namespace</span>
+        </h1>
+        <p>A namespace.</p>
+        <div class="m-block m-default">
+          <h3>Contents</h3>
+          <ul>
+            <li>
+              Reference
+              <ul>
+                <li><a href="#nested-classes">Classes</a></li>
+                <li><a href="#enum-members">Enums</a></li>
+                <li><a href="#typedef-members">Typedefs</a></li>
+                <li><a href="#func-members">Functions</a></li>
+                <li><a href="#var-members">Variables</a></li>
+              </ul>
+            </li>
+          </ul>
+        </div>
+<aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000003" class="m-doc">Deprecated since 2010.02</a></h4><p>Yes it is.</p></aside>
+        <section id="nested-classes">
+          <h2><a href="#nested-classes">Classes</a></h2>
+          <dl class="m-doc">
+            <dt>
+              class <a href="classDeprecatedFoo_1_1DeprecatedClass.html" class="m-doc">DeprecatedClass</a> <span class="m-label m-danger">deprecated since 2010.02</span>
+            </dt>
+            <dd>A class.</dd>
+            <dt>
+              struct <a href="structDeprecatedFoo_1_1DeprecatedSubclass.html" class="m-doc">DeprecatedSubclass</a> <span class="m-label m-danger">deprecated since 2010.02</span>
+            </dt>
+            <dd>A subclass.</dd>
+          </dl>
+        </section>
+        <section id="enum-members">
+          <h2><a href="#enum-members">Enums</a></h2>
+          <dl class="m-doc">
+            <dt>
+              <span class="m-doc-wrap-bumper">enum <a href="#a1b67a9bfeff003e6d1da986ac426696b" class="m-doc">DeprecatedEnum</a> { </span><span class="m-doc-wrap"><a href="#a1b67a9bfeff003e6d1da986ac426696baf0e0b3081a15aeb278f401cde19e4acb" class="m-doc">DeprecatedOldValue</a> = 0 <span class="m-label m-danger">deprecated since 2010.02</span>,
+              <a href="#a1b67a9bfeff003e6d1da986ac426696ba79c936e03eebb061623bc8978202f1ad" class="m-doc">NewValue</a> = 3 } <span class="m-label m-danger">deprecated since 2010.02</span></span>
+            </dt>
+            <dd>An enum.</dd>
+          </dl>
+        </section>
+        <section id="typedef-members">
+          <h2><a href="#typedef-members">Typedefs</a></h2>
+          <dl class="m-doc">
+            <dt>
+              using <a href="#a1c5216038f22a0f81a037f4ed74cecf1" class="m-doc">DeprecatedKlazz</a> = <a href="classDeprecatedFoo_1_1DeprecatedClass.html" class="m-doc">DeprecatedClass</a> <span class="m-label m-danger">deprecated since 2010.02</span>
+            </dt>
+            <dd>A typedef.</dd>
+          </dl>
+        </section>
+        <section id="func-members">
+          <h2><a href="#func-members">Functions</a></h2>
+          <dl class="m-doc">
+            <dt>
+              <span class="m-doc-wrap-bumper">void <a href="#a607bf852d369ac0a1d42b6b5accf2e36" class="m-doc">deprecatedFoo</a>(</span><span class="m-doc-wrap">) <span class="m-label m-danger">deprecated since 2010.02</span></span>
+            </dt>
+            <dd>A function.</dd>
+          </dl>
+        </section>
+        <section id="var-members">
+          <h2><a href="#var-members">Variables</a></h2>
+          <dl class="m-doc">
+            <dt>
+              int <a href="#ae045683ee9ae5bf2f811ba2d8e015087" class="m-doc">DeprecatedFive</a> <span class="m-label m-danger">deprecated since 2010.02</span> <span class="m-label m-flat m-primary">constexpr</span>
+            </dt>
+            <dd>A constant.</dd>
+          </dl>
+        </section>
+        <section>
+          <h2>Enum documentation</h2>
+          <section class="m-doc-details" id="a1b67a9bfeff003e6d1da986ac426696b"><div>
+            <h3>
+              enum DeprecatedFoo::<wbr /><a href="#a1b67a9bfeff003e6d1da986ac426696b" class="m-doc-self">DeprecatedEnum</a>
+              <div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="DeprecatedClass_8h.html">&lt;DeprecatedDirectory/DeprecatedClass.h&gt;</a></div>
+            </h3>
+            <p>An enum.</p>
+<aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000009" class="m-doc">Deprecated since 2010.02</a></h4><p>Yes it is.</p></aside><p>Details should have the badge too.</p>
+            <table class="m-table m-fullwidth m-flat m-doc">
+              <thead><tr><th style="width: 1%">Enumerators</th><th></th></tr></thead>
+              <tbody>
+                <tr>
+                  <td><a href="#a1b67a9bfeff003e6d1da986ac426696baf0e0b3081a15aeb278f401cde19e4acb" class="m-doc-self" id="a1b67a9bfeff003e6d1da986ac426696baf0e0b3081a15aeb278f401cde19e4acb">DeprecatedOldValue</a></td>
+                  <td>
+<p>This thing is deprecated.</p><p>Yes.</p><aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000011" class="m-doc">Deprecated since 2010.02</a></h4><p>Yes it is.</p></aside>
+                  </td>
+                </tr>
+                <tr>
+                  <td><a href="#a1b67a9bfeff003e6d1da986ac426696ba79c936e03eebb061623bc8978202f1ad" class="m-doc-self" id="a1b67a9bfeff003e6d1da986ac426696ba79c936e03eebb061623bc8978202f1ad">NewValue</a></td>
+                  <td>
+                  </td>
+                </tr>
+              </tbody>
+            </table>
+          </div></section>
+        </section>
+        <section>
+          <h2>Typedef documentation</h2>
+          <section class="m-doc-details" id="a1c5216038f22a0f81a037f4ed74cecf1"><div>
+            <h3>
+              typedef <a href="classDeprecatedFoo_1_1DeprecatedClass.html" class="m-doc">DeprecatedClass</a> DeprecatedFoo::<wbr /><a href="#a1c5216038f22a0f81a037f4ed74cecf1" class="m-doc-self">DeprecatedKlazz</a>
+              <div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="DeprecatedClass_8h.html">&lt;DeprecatedDirectory/DeprecatedClass.h&gt;</a></div>
+            </h3>
+            <p>A typedef.</p>
+<aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000008" class="m-doc">Deprecated since 2010.02</a></h4><p>Yes it is.</p></aside><p>Details should have the badge too.</p>
+          </div></section>
+        </section>
+        <section>
+          <h2>Function documentation</h2>
+          <section class="m-doc-details" id="a607bf852d369ac0a1d42b6b5accf2e36"><div>
+            <h3>
+              <span class="m-doc-wrap-bumper">void DeprecatedFoo::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#a607bf852d369ac0a1d42b6b5accf2e36" class="m-doc-self">deprecatedFoo</a>(</span><span class="m-doc-wrap">)</span></span>
+              <div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="DeprecatedClass_8h.html">&lt;DeprecatedDirectory/DeprecatedClass.h&gt;</a></div>
+            </h3>
+            <p>A function.</p>
+<aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000007" class="m-doc">Deprecated since 2010.02</a></h4><p>Yes it is.</p></aside><p>Details should have the badge too.</p>
+          </div></section>
+        </section>
+        <section>
+          <h2>Variable documentation</h2>
+          <section class="m-doc-details" id="ae045683ee9ae5bf2f811ba2d8e015087"><div>
+            <h3>
+              int DeprecatedFoo::<wbr /><a href="#ae045683ee9ae5bf2f811ba2d8e015087" class="m-doc-self">DeprecatedFive</a> <span class="m-label m-primary">constexpr</span>
+              <div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="DeprecatedClass_8h.html">&lt;DeprecatedDirectory/DeprecatedClass.h&gt;</a></div>
+            </h3>
+            <p>A constant.</p>
+<aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000010" class="m-doc">Deprecated since 2010.02</a></h4><p>Yes it is.</p></aside><p>Details should have the badge too.</p>
+          </div></section>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/namespaceFoo.html b/documentation/test_doxygen/compound_since/namespaceFoo.html
new file mode 100644 (file)
index 0000000..4254b62
--- /dev/null
@@ -0,0 +1,173 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>Foo namespace | 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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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>
+          Foo <span class="m-thin">namespace</span> <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a>
+        </h1>
+        <p>A namespace.</p>
+        <div class="m-block m-default">
+          <h3>Contents</h3>
+          <ul>
+            <li>
+              Reference
+              <ul>
+                <li><a href="#nested-classes">Classes</a></li>
+                <li><a href="#enum-members">Enums</a></li>
+                <li><a href="#typedef-members">Typedefs</a></li>
+                <li><a href="#func-members">Functions</a></li>
+                <li><a href="#var-members">Variables</a></li>
+              </ul>
+            </li>
+          </ul>
+        </div>
+        <section id="nested-classes">
+          <h2><a href="#nested-classes">Classes</a></h2>
+          <dl class="m-doc">
+            <dt>
+              class <a href="classFoo_1_1Class.html" class="m-doc">Class</a> <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a>
+            </dt>
+            <dd>A class.</dd>
+            <dt>
+              struct <a href="structFoo_1_1Subclass.html" class="m-doc">Subclass</a> <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a>
+            </dt>
+            <dd>A subclass.</dd>
+          </dl>
+        </section>
+        <section id="enum-members">
+          <h2><a href="#enum-members">Enums</a></h2>
+          <dl class="m-doc">
+            <dt>
+              <span class="m-doc-wrap-bumper">enum <a href="#aa599494b5d1882fa0ebde0dc124b2d36" class="m-doc">Enum</a> { </span><span class="m-doc-wrap"><a href="#aa599494b5d1882fa0ebde0dc124b2d36afbb9877f08f72a4124c53bd332d4524d" class="m-doc">OldValue</a> = 0,
+              <a href="#aa599494b5d1882fa0ebde0dc124b2d36a118b94bbd363b0cd3dc969f93c3f1398" class="m-doc">NewValue</a> = 3 <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a> } <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a></span>
+            </dt>
+            <dd>An enum.</dd>
+          </dl>
+        </section>
+        <section id="typedef-members">
+          <h2><a href="#typedef-members">Typedefs</a></h2>
+          <dl class="m-doc">
+            <dt>
+              using <a href="#aaac8068beb284217ad38a3f6a0db757c" class="m-doc">Klazz</a> = <a href="classFoo_1_1Class.html" class="m-doc">Class</a> <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a>
+            </dt>
+            <dd>A typedef.</dd>
+          </dl>
+        </section>
+        <section id="func-members">
+          <h2><a href="#func-members">Functions</a></h2>
+          <dl class="m-doc">
+            <dt>
+              <span class="m-doc-wrap-bumper">void <a href="#a1d0dde98446ce72fbaebef84c86efe1a" class="m-doc">foo</a>(</span><span class="m-doc-wrap">) <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a></span>
+            </dt>
+            <dd>A function.</dd>
+          </dl>
+        </section>
+        <section id="var-members">
+          <h2><a href="#var-members">Variables</a></h2>
+          <dl class="m-doc">
+            <dt>
+              int <a href="#a4673bb940e88847b3fe2687789dd19dc" class="m-doc">Five</a> <span class="m-label m-flat m-primary">constexpr</span> <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a>
+            </dt>
+            <dd>A constant.</dd>
+          </dl>
+        </section>
+        <section>
+          <h2>Enum documentation</h2>
+          <section class="m-doc-details" id="aa599494b5d1882fa0ebde0dc124b2d36"><div>
+            <h3>
+              enum Foo::<wbr /><a href="#aa599494b5d1882fa0ebde0dc124b2d36" class="m-doc-self">Enum</a> <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a>
+              <div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="Class_8h.html">&lt;Directory/Class.h&gt;</a></div>
+            </h3>
+            <p>An enum.</p>
+<p>Details should have the badge too.</p>
+            <table class="m-table m-fullwidth m-flat m-doc">
+              <thead><tr><th style="width: 1%">Enumerators</th><th></th></tr></thead>
+              <tbody>
+                <tr>
+                  <td><a href="#aa599494b5d1882fa0ebde0dc124b2d36afbb9877f08f72a4124c53bd332d4524d" class="m-doc-self" id="aa599494b5d1882fa0ebde0dc124b2d36afbb9877f08f72a4124c53bd332d4524d">OldValue</a></td>
+                  <td>
+                  </td>
+                </tr>
+                <tr>
+                  <td><a href="#aa599494b5d1882fa0ebde0dc124b2d36a118b94bbd363b0cd3dc969f93c3f1398" class="m-doc-self" id="aa599494b5d1882fa0ebde0dc124b2d36a118b94bbd363b0cd3dc969f93c3f1398">NewValue</a> <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a></td>
+                  <td>
+<p>This thing is new.</p><p>Yes.</p>
+                  </td>
+                </tr>
+              </tbody>
+            </table>
+          </div></section>
+        </section>
+        <section>
+          <h2>Typedef documentation</h2>
+          <section class="m-doc-details" id="aaac8068beb284217ad38a3f6a0db757c"><div>
+            <h3>
+              typedef <a href="classFoo_1_1Class.html" class="m-doc">Class</a> Foo::<wbr /><a href="#aaac8068beb284217ad38a3f6a0db757c" class="m-doc-self">Klazz</a> <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a>
+              <div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="Class_8h.html">&lt;Directory/Class.h&gt;</a></div>
+            </h3>
+            <p>A typedef.</p>
+<p>Details should have the badge too.</p>
+          </div></section>
+        </section>
+        <section>
+          <h2>Function documentation</h2>
+          <section class="m-doc-details" id="a1d0dde98446ce72fbaebef84c86efe1a"><div>
+            <h3>
+              <span class="m-doc-wrap-bumper">void Foo::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#a1d0dde98446ce72fbaebef84c86efe1a" class="m-doc-self">foo</a>(</span><span class="m-doc-wrap">) <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a></span></span>
+              <div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="Class_8h.html">&lt;Directory/Class.h&gt;</a></div>
+            </h3>
+            <p>A function.</p>
+<p>Details should have the badge too.</p>
+          </div></section>
+        </section>
+        <section>
+          <h2>Variable documentation</h2>
+          <section class="m-doc-details" id="a4673bb940e88847b3fe2687789dd19dc"><div>
+            <h3>
+              int Foo::<wbr /><a href="#a4673bb940e88847b3fe2687789dd19dc" class="m-doc-self">Five</a> <span class="m-label m-primary">constexpr</span> <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a>
+              <div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="Class_8h.html">&lt;Directory/Class.h&gt;</a></div>
+            </h3>
+            <p>A constant.</p>
+<p>Details should have the badge too.</p>
+          </div></section>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/namespaces.html b/documentation/test_doxygen/compound_since/namespaces.html
new file mode 100644 (file)
index 0000000..0800f35
--- /dev/null
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html" id="m-navbar-current">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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>Namespaces</h2>
+        <ul class="m-doc">
+          <li>namespace <a href="namespaceDeprecatedFoo.html" class="m-doc">DeprecatedFoo</a> <span class="m-label m-danger">deprecated since 2010.02</span> <span class="m-doc">A namespace.</span></li>
+          <li>namespace <a href="namespaceFoo.html" class="m-doc">Foo</a> <a href="changelog.html#changelog-2010-02" class="m-label m-success m-flat">since 2010.02</a> <span class="m-doc">A namespace.</span></li>
+        </ul>
+        <script>
+        function toggle(e) {
+            e.parentElement.className = e.parentElement.className == 'm-doc-collapsible' ?
+                'm-doc-expansible' : 'm-doc-collapsible';
+            return false;
+        }
+        /* Collapse all nodes marked as such. Doing it via JS instead of
+           directly in markup so disabling it doesn't harm usability. The list
+           is somehow regenerated on every iteration and shrinks as I change
+           the classes. It's not documented anywhere and I'm not sure if this
+           is the same across browsers, so I am going backwards in that list to
+           be sure. */
+        var collapsed = document.getElementsByClassName("collapsed");
+        for(var i = collapsed.length - 1; i >= 0; --i)
+            collapsed[i].className = 'm-doc-expansible';
+        </script>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/pages.dox b/documentation/test_doxygen/compound_since/pages.dox
new file mode 100644 (file)
index 0000000..6aa3944
--- /dev/null
@@ -0,0 +1,54 @@
+/** @page a This is new.
+
+Yes.
+
+@m_since{2019,11}
+
+*/
+
+/** @page deprecated-a This is old.
+
+Yes.
+
+@m_deprecated_since{2010,02} Yes it is.
+
+*/
+
+/** @page changelog Changelog
+
+@section changelog-2019-11 Version 2019.11
+
+Stuff happened.
+
+@section changelog-2010-02 Version 2010.02
+
+Ages ago. Who knows.
+*/
+
+/** @defgroup group A group
+
+@m_since{2019,11}
+
+Detailed description.
+
+@defgroup subgroup A subgroup
+@ingroup group
+
+@m_since{2019,11}
+
+More.
+*/
+
+/** @defgroup deprecated-group A group
+
+@m_deprecated_since{2010,02} Yes it is.
+
+Detailed description.
+
+@defgroup deprecated-subgroup A subgroup
+@ingroup deprecated-group
+
+More.
+
+@m_deprecated_since{2019,11} Yep.
+*/
diff --git a/documentation/test_doxygen/compound_since/pages.html b/documentation/test_doxygen/compound_since/pages.html
new file mode 100644 (file)
index 0000000..1e20616
--- /dev/null
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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>Pages</h2>
+        <ul class="m-doc">
+          <li><a href="a.html" class="m-doc">This is new.</a> <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a> <span class="m-doc"></span></li>
+          <li><a href="deprecated-a.html" class="m-doc">This is old.</a> <span class="m-label m-danger">deprecated since 2010.02</span> <span class="m-doc"></span></li>
+          <li><a href="changelog.html" class="m-doc">Changelog</a> <span class="m-doc"></span></li>
+          <li><a href="deprecated.html" class="m-doc">Deprecated List</a> <span class="m-doc"></span></li>
+        </ul>
+        <script>
+        function toggle(e) {
+            e.parentElement.className = e.parentElement.className == 'm-doc-collapsible' ?
+                'm-doc-expansible' : 'm-doc-collapsible';
+            return false;
+        }
+        /* Collapse all nodes marked as such. Doing it via JS instead of
+           directly in markup so disabling it doesn't harm usability. The list
+           is somehow regenerated on every iteration and shrinks as I change
+           the classes. It's not documented anywhere and I'm not sure if this
+           is the same across browsers, so I am going backwards in that list to
+           be sure. */
+        var collapsed = document.getElementsByClassName("collapsed");
+        for(var i = collapsed.length - 1; i >= 0; --i)
+            collapsed[i].className = 'm-doc-expansible';
+        </script>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/structDeprecatedFoo_1_1DeprecatedSubclass.html b/documentation/test_doxygen/compound_since/structDeprecatedFoo_1_1DeprecatedSubclass.html
new file mode 100644 (file)
index 0000000..a5f49f8
--- /dev/null
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>DeprecatedFoo::DeprecatedSubclass struct | 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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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="namespaceDeprecatedFoo.html">DeprecatedFoo</a>::<wbr/></span>DeprecatedSubclass <span class="m-thin">struct</span>
+          <div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="DeprecatedClass_8h.html">&lt;DeprecatedDirectory/DeprecatedClass.h&gt;</a></div>
+        </h1>
+        <p>A subclass.</p>
+<aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000006" class="m-doc">Deprecated since 2010.02</a></h4><p>Yes it is.</p></aside>
+        <section id="base-classes">
+          <h2><a href="#base-classes">Base classes</a></h2>
+          <dl class="m-doc">
+            <dt>
+              class <a href="classDeprecatedFoo_1_1DeprecatedClass.html" class="m-doc">DeprecatedClass</a> <span class="m-label m-danger">deprecated since 2010.02</span>
+            </dt>
+            <dd>A class.</dd>
+          </dl>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/documentation/test_doxygen/compound_since/structFoo_1_1Subclass.html b/documentation/test_doxygen/compound_since/structFoo_1_1Subclass.html
new file mode 100644 (file)
index 0000000..22390d9
--- /dev/null
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>Foo::Subclass struct | 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+documentation.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</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-8 m-col-m-none m-left-m">My Project</a>
+      <div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
+        <a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
+        <a id="m-navbar-hide" href="#" title="Hide navigation"></a>
+      </div>
+      <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">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+            <li><a href="modules.html">Modules</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="4">
+            <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="namespaceFoo.html">Foo</a>::<wbr/></span>Subclass <span class="m-thin">struct</span> <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a>
+          <div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="Class_8h.html">&lt;Directory/Class.h&gt;</a></div>
+        </h1>
+        <p>A subclass.</p>
+        <section id="base-classes">
+          <h2><a href="#base-classes">Base classes</a></h2>
+          <dl class="m-doc">
+            <dt>
+              class <a href="classFoo_1_1Class.html" class="m-doc">Class</a> <a href="changelog.html#changelog-2019-11" class="m-label m-success m-flat">since 2019.11</a>
+            </dt>
+            <dd>A class.</dd>
+          </dl>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
index 15422e0cd04ac54ff7cadd94cd6fd67dd25c5800..ace70e42ba87d051d5ab296ea793bae201419e01 100644 (file)
@@ -326,3 +326,37 @@ class BaseDerivedInRootNamespace(IntegrationTestCase):
 
         # Shouldn't crash or anything
         self.assertEqual(*self.actual_expected_contents('structNamespace_1_1BothBaseAndDerivedInRootNamespace.html'))
+
+class Since(IntegrationTestCase):
+    def __init__(self, *args, **kwargs):
+        super().__init__(__file__, 'since', *args, **kwargs)
+
+    def test(self):
+        self.run_doxygen(wildcard='*.xml')
+
+        # Verify all entries and details get the Since badge with a link to
+        # changelog. Not class/namespace/file/dir entries yet because we don't
+        # propagate those right now.
+        self.assertEqual(*self.actual_expected_contents('dir_4b0d5f8864bf89936129251a2d32609b.html'))
+        self.assertEqual(*self.actual_expected_contents('Class_8h.html'))
+        self.assertEqual(*self.actual_expected_contents('group__group.html'))
+        self.assertEqual(*self.actual_expected_contents('namespaceFoo.html'))
+        self.assertEqual(*self.actual_expected_contents('classFoo_1_1Class.html'))
+        self.assertEqual(*self.actual_expected_contents('structFoo_1_1Subclass.html'))
+        self.assertEqual(*self.actual_expected_contents('a.html'))
+
+        # And these should have an extended deprecation badge
+        self.assertEqual(*self.actual_expected_contents('dir_73d1500434dee6f1c83b12ee799c54af.html'))
+        self.assertEqual(*self.actual_expected_contents('DeprecatedClass_8h.html'))
+        self.assertEqual(*self.actual_expected_contents('group__deprecated-group.html'))
+        self.assertEqual(*self.actual_expected_contents('namespaceDeprecatedFoo.html'))
+        self.assertEqual(*self.actual_expected_contents('classDeprecatedFoo_1_1DeprecatedClass.html'))
+        self.assertEqual(*self.actual_expected_contents('structDeprecatedFoo_1_1DeprecatedSubclass.html'))
+        self.assertEqual(*self.actual_expected_contents('deprecated-a.html'))
+
+        # The listings should have both
+        self.assertEqual(*self.actual_expected_contents('annotated.html'))
+        self.assertEqual(*self.actual_expected_contents('files.html'))
+        self.assertEqual(*self.actual_expected_contents('modules.html'))
+        self.assertEqual(*self.actual_expected_contents('namespaces.html'))
+        self.assertEqual(*self.actual_expected_contents('pages.html'))
index 0a9a7adbbf2f312959a872dd13cd26a221f716a3..7e522fa279bbbad3ec062318f60cc27bd50677ab 100644 (file)
@@ -75,6 +75,7 @@ copy a link to the result using <span class="m-label m-dim">⌘</span>
 """,
             'M_SHOW_UNDOCUMENTED': False,
             'M_THEME_COLOR': '#22272e',
+            'M_VERSION_LABELS': False,
             'OUTPUT_DIRECTORY': '',
             'PROJECT_BRIEF': 'is cool',
             'PROJECT_LOGO': '',