chiark / gitweb /
doxygen: implemented section merging.
authorVladimír Vondruš <mosra@centrum.cz>
Wed, 13 Dec 2017 19:46:18 +0000 (20:46 +0100)
committerVladimír Vondruš <mosra@centrum.cz>
Wed, 13 Dec 2017 19:50:09 +0000 (20:50 +0100)
So multiple adjacent \attention, \note etc. paragraph of the same kind
are now merged into one, to be consistent with HTML output. Works also
with code blocks.

doxygen/dox2html5.py
doxygen/test/contents_blocks/Doxyfile
doxygen/test/contents_blocks/File.h [new file with mode: 0644]
doxygen/test/contents_blocks/File_8h.html [new file with mode: 0644]
doxygen/test/contents_blocks/index.html
doxygen/test/contents_blocks/input.dox
doxygen/test/contents_blocks/old.html [new file with mode: 0644]
doxygen/test/contents_code/index.html
doxygen/test/contents_code/input.dox
doxygen/test/test_contents.py

index 38d4af5d559f27dad2a512b70b9351cc65ecccd5..2fb3a297802bdaa65bb91914913ab2e42b7da1b4 100755 (executable)
@@ -165,12 +165,23 @@ def parse_desc_internal(state: State, element: ET.Element, immediate_parent: ET.
     paragraph_count = 0
     has_block_elements = False
 
+    # So we are able to merge content of adjacent sections. Tuple of (tag,
+    # kind), set only if there is no i.tail, reset in the next iteration.
+    previous_section = None
+
     i: ET.Element
     for i in element:
         # State used later
         code_block = None
         formula_block = None
 
+        # A section was left open, but there's nothing to continue it, close
+        # it. Expect that there was nothing after that would mess with us.
+        if previous_section and i.tag != 'simplesect':
+            previous_section = None
+            assert not out.write_paragraph_close_tag
+            out.parsed = out.parsed.rstrip() + '</aside>'
+
         # DOXYGEN <PARA> PATCHING 2/4
         #
         # Upon encountering a block element nested in <para>, we need to act.
@@ -401,22 +412,43 @@ def parse_desc_internal(state: State, element: ET.Element, immediate_parent: ET.
                 out.return_value = parse_desc(state, i)
             else:
                 has_block_elements = True
-                if i.attrib['kind'] == 'see':
-                    out.parsed += '<aside class="m-note m-default"><h4>See also</h4>'
-                elif i.attrib['kind'] == 'note':
-                    out.parsed += '<aside class="m-note m-info"><h4>Note</h4>'
-                elif i.attrib['kind'] == 'attention':
-                    out.parsed += '<aside class="m-note m-warning"><h4>Attention</h4>'
-                else: # pragma: no cover
-                    out.parsed += '<aside class="m-note">'
-                    logging.warning("ignoring {} kind of <simplesect>".format(i.attrib['kind']))
+
+                # There was a section open, but it differs from this one, close
+                # it
+                if previous_section and previous_section != i.attrib['kind']:
+                    out.parsed = out.parsed.rstrip() + '</aside>'
+
+                # Not continuing with a section from before, put a header in
+                if not previous_section or previous_section != i.attrib['kind']:
+                    if i.attrib['kind'] == 'see':
+                        out.parsed += '<aside class="m-note m-default"><h4>See also</h4>'
+                    elif i.attrib['kind'] == 'note':
+                        out.parsed += '<aside class="m-note m-info"><h4>Note</h4>'
+                    elif i.attrib['kind'] == 'attention':
+                        out.parsed += '<aside class="m-note m-warning"><h4>Attention</h4>'
+                    else: # pragma: no cover
+                        out.parsed += '<aside class="m-note">'
+                        logging.warning("ignoring {} kind of <simplesect>".format(i.attrib['kind']))
+
                 out.parsed += parse_desc(state, i)
-                out.parsed += '</aside>'
+
+                # There's something after, close it
+                if i.tail and i.tail.strip():
+                    out.parsed += '</aside>'
+                    previous_section = None
+
+                # Otherwise put the responsibility on the next iteration, maybe
+                # there are more paragraphs that should be merged
+                else:
+                    previous_section = i.attrib['kind']
 
         elif i.tag == 'xrefsect':
             assert element.tag == 'para' # is inside a paragraph :/
             has_block_elements = True
 
+            # Not merging these, as every has usually a different ID each. (And
+            # apparently Doxygen is able to merge them *but only if* they
+            # describe some symbol, not on a page.)
             id = i.attrib['id']
             match = xref_id_rx.match(id)
             file = match.group(1)
@@ -656,6 +688,12 @@ def parse_desc_internal(state: State, element: ET.Element, immediate_parent: ET.
                 tail = tail.lstrip()
             out.parsed += tail
 
+    # A section was left open in the last iteration, close it. Expect that
+    # there was nothing after that would mess with us.
+    if previous_section:
+        assert not out.write_paragraph_close_tag
+        out.parsed = out.parsed.rstrip() + '</aside>'
+
     # Brief description always needs to be single paragraph because we're
     # sending it out without enclosing <p>.
     if element.tag == 'briefdescription':
index d64a2386d33d9fc9455666391fa75dcd17a36132..fea67c7daff9e6bcf72d5f7b3b2e0a18aa5d50f8 100644 (file)
@@ -1,4 +1,4 @@
-INPUT                   = input.dox
+INPUT                   = input.dox File.h
 QUIET                   = YES
 GENERATE_HTML           = NO
 GENERATE_LATEX          = NO
diff --git a/doxygen/test/contents_blocks/File.h b/doxygen/test/contents_blocks/File.h
new file mode 100644 (file)
index 0000000..a17e854
--- /dev/null
@@ -0,0 +1,11 @@
+/** @file
+ * @brief A file
+ */
+
+/**
+@brief A foo
+
+@xrefitem old "Old stuff" "Just old" Xrefitem, gets merged
+@xrefitem old "Old stuff" "Just old" with this one by Doxygen itself.
+*/
+int foo();
diff --git a/doxygen/test/contents_blocks/File_8h.html b/doxygen/test/contents_blocks/File_8h.html
new file mode 100644 (file)
index 0000000..6f06b63
--- /dev/null
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>File.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+doxygen.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <meta name="theme-color" content="#22272e" />
+</head>
+<body>
+<header><nav id="navigation">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="index.html" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">My Project</a>
+      <a id="m-navbar-show" href="#navigation" title="Show navigation" class="m-col-t-3 m-hide-m m-text-right"></a>
+      <a id="m-navbar-hide" href="#" title="Hide navigation" class="m-col-t-3 m-hide-m m-text-right"></a>
+      <div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
+        <div class="m-row">
+          <ol class="m-col-t-6 m-col-m-none">
+            <li><a href="pages.html">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="3">
+            <li><a href="annotated.html">Classes</a></li>
+            <li><a href="files.html" 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>
+          File.h <span class="m-thin">file</span>
+        </h1>
+        <p>A file.</p>
+        <div class="m-block m-default">
+          <h3>Contents</h3>
+          <ul>
+            <li>
+              Reference
+              <ul>
+                <li><a href="#func-members">Functions</a></li>
+              </ul>
+            </li>
+          </ul>
+        </div>
+        <section id="func-members">
+          <h2><a href="#func-members">Functions</a></h3>
+          <dl class="m-dox">
+            <dt>
+              <span class="m-dox-wrap-bumper">auto <a href="#a14bcd2d544b22300bba3863251393e0f" class="m-dox">foo</a>(</span><span class="m-dox-wrap">) -&gt; int</span>
+            </dt>
+            <dd>A foo.</dd>
+          </dl>
+        </section>
+        <section>
+          <h2>Function documentation</h2>
+          <section class="m-dox-details" id="a14bcd2d544b22300bba3863251393e0f"><div>
+            <h3>
+              <span class="m-dox-wrap-bumper">int </span><span class="m-dox-wrap"><span class="m-dox-wrap-bumper"><a href="#a14bcd2d544b22300bba3863251393e0f" class="m-dox-self">foo</a>(</span><span class="m-dox-wrap">)</span></span>
+            </h3>
+            <p>A foo.</p>
+<aside class="m-note m-default"><h4><a href="old.html#_old000004" class="m-dox">Old stuff</a></h4><p>Xrefitem, gets merged</p><p>with this one by Doxygen itself.</p></aside>
+          </div></section>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+<footer><nav>
+  <div class="m-container">
+    <div class="m-row">
+      <div class="m-col-l-10 m-push-l-1">
+        <p>My Project. Created by <a href="http://doxygen.org/">Doxygen</a> and <a href="http://mcss.mosra.cz/">m.css</a>.</p>
+      </div>
+    </div>
+  </div>
+</nav></footer>
+</body>
+</html>
index 32530ac0e90f09f23b80a52be43f15de38f584d8..f7df930680bea654f6981b042b484d3ae417da44 100644 (file)
@@ -37,7 +37,7 @@
         <h1>
           My Project
         </h1>
-<p>First paragraph containing some content.</p><aside class="m-note m-warning"><h4>Attention</h4><p>An attention section.</p></aside><aside class="m-note m-default"><h4>See also</h4><p>Other section.</p></aside><p>Paragraph following the sections.</p><aside class="m-note m-info"><h4>Note</h4><p>A note.</p></aside><aside class="m-note m-danger"><h4><a href="bug.html#_bug000001" class="m-dox">Bug</a></h4><p>This is a bug.</p></aside><aside class="m-note m-dim"><h4><a href="todo.html#_todo000001" class="m-dox">Todo</a></h4><p>Or a TODO.</p></aside><aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000001" class="m-dox">Deprecated</a></h4><p>Which is deprecated.</p></aside><aside class="m-note m-default"><h4><a href="old.html#_old000001" class="m-dox">Old stuff</a></h4><p>This is old.</p></aside><blockquote><p>A blockquote</p></blockquote><p>Text right after that blockquote should be a new paragraph.</p><ul><li>A simple</li><li>List<ol><li>With one line</li><li>for each</li></ol></li><li>item, so paragraphs are removed</li></ul><ul><li>A simple</li><li>List<ol><li>With the sublist delimited</li><li>by blank lines</li></ol></li><li>should behave the same as above</li></ul><ul><li><p>A new list</p><p>of multiple</p><p>paragraphs.</p></li><li><p>Another item</p><ul><li><p>A sub list</p><p>Another paragraph</p></li></ul></li></ul><p>A paragraph after that list.</p><table class="m-table"><thead><tr><th>Table header</th><th>Another</th><th>Third</th></tr></thead><tbody><tr><td>Cell</td><td>Another cell</td><td>3rd</td></tr><tr><td>Next row</td><td></td><td>This</td></tr><tr><td>is a table</td><td><em>really</em></td><td>yes.</td></tr></tbody></table>
+<p>First paragraph containing some content.</p><aside class="m-note m-warning"><h4>Attention</h4><p>An attention section.</p></aside><aside class="m-note m-default"><h4>See also</h4><p>Other section.</p></aside><p>Paragraph following the sections.</p><aside class="m-note m-info"><h4>Note</h4><p>A note.</p></aside><aside class="m-note m-danger"><h4><a href="bug.html#_bug000001" class="m-dox">Bug</a></h4><p>This is a bug.</p></aside><aside class="m-note m-dim"><h4><a href="todo.html#_todo000001" class="m-dox">Todo</a></h4><p>Or a TODO.</p></aside><aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000001" class="m-dox">Deprecated</a></h4><p>Which is deprecated.</p></aside><aside class="m-note m-default"><h4><a href="old.html#_old000001" class="m-dox">Old stuff</a></h4><p>This is old.</p></aside><blockquote><p>A blockquote</p></blockquote><p>Text right after that blockquote should be a new paragraph.</p><ul><li>A simple</li><li>List<ol><li>With one line</li><li>for each</li></ol></li><li>item, so paragraphs are removed</li></ul><ul><li>A simple</li><li>List<ol><li>With the sublist delimited</li><li>by blank lines</li></ol></li><li>should behave the same as above</li></ul><ul><li><p>A new list</p><p>of multiple</p><p>paragraphs.</p></li><li><p>Another item</p><ul><li><p>A sub list</p><p>Another paragraph</p></li></ul></li></ul><p>A paragraph after that list.</p><table class="m-table"><thead><tr><th>Table header</th><th>Another</th><th>Third</th></tr></thead><tbody><tr><td>Cell</td><td>Another cell</td><td>3rd</td></tr><tr><td>Next row</td><td></td><td>This</td></tr><tr><td>is a table</td><td><em>really</em></td><td>yes.</td></tr></tbody></table><aside class="m-note m-warning"><h4>Attention</h4><p>Attention, first paragraph.</p><p>Attention, second paragraph.</p><p>Attention, third paragraph.</p></aside><aside class="m-note m-info"><h4>Note</h4><p>A note, not merged with the above.</p></aside><aside class="m-note m-default"><h4><a href="old.html#_old000002" class="m-dox">Old stuff</a></h4><p>This is not merged.</p></aside><aside class="m-note m-default"><h4><a href="old.html#_old000003" class="m-dox">Old stuff</a></h4><p>With this. Only on the listing page.</p></aside>
       </div>
     </div>
   </div>
index 5b026f258d8189f536e828419a7cdea53cdd691d..ba1a7cc0d9a8ac1d877a38b3f73e9f0e8d1485b7 100644 (file)
@@ -59,6 +59,19 @@ Cell            | Another cell  | 3rd
 Next row        |               | This
 is a table      | *really*      | yes.
 
+@attention
+    Attention, first paragraph.
+@attention
+    Attention, second paragraph.
+@attention
+    Attention, third paragraph.
+@note
+    A note, not merged with the above.
+
+@xrefitem old "Old stuff" "Just old" This is not merged.
+
+@xrefitem old "Old stuff" "Just old" With this. Only on the listing page.
+
 */
 
 /** @page other Other page
diff --git a/doxygen/test/contents_blocks/old.html b/doxygen/test/contents_blocks/old.html
new file mode 100644 (file)
index 0000000..82c9f96
--- /dev/null
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>Just 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+doxygen.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <meta name="theme-color" content="#22272e" />
+</head>
+<body>
+<header><nav id="navigation">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="index.html" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">My Project</a>
+      <a id="m-navbar-show" href="#navigation" title="Show navigation" class="m-col-t-3 m-hide-m m-text-right"></a>
+      <a id="m-navbar-hide" href="#" title="Hide navigation" class="m-col-t-3 m-hide-m m-text-right"></a>
+      <div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
+        <div class="m-row">
+          <ol class="m-col-t-6 m-col-m-none">
+            <li><a href="pages.html" id="m-navbar-current">Pages</a></li>
+            <li><a href="namespaces.html">Namespaces</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="3">
+            <li><a href="annotated.html">Classes</a></li>
+            <li><a href="files.html">Files</a></li>
+          </ol>
+        </div>
+      </div>
+    </div>
+  </div>
+</nav></header>
+<main><article>
+  <div class="m-container m-container-inflatable">
+    <div class="m-row">
+      <div class="m-col-l-10 m-push-l-1">
+        <h1>
+          Just old
+        </h1>
+<dl class="m-dox"><dt><a name="_old000004"></a>Member <a href="File_8h.html#a14bcd2d544b22300bba3863251393e0f" class="m-dox">foo</a>  ()</dt><dd><p>Xrefitem, gets merged</p><p>with this one by Doxygen itself.</p></dd><dt><a name="_old000001"></a>page <a href="index.html" class="m-dox">Main Page</a></dt><dd><p>This is old.</p><p>This is not merged.</p><p>With this. Only on the listing page.</p></dd></dl>
+      </div>
+    </div>
+  </div>
+</article></main>
+<footer><nav>
+  <div class="m-container">
+    <div class="m-row">
+      <div class="m-col-l-10 m-push-l-1">
+        <p>My Project. Created by <a href="http://doxygen.org/">Doxygen</a> and <a href="http://mcss.mosra.cz/">m.css</a>.</p>
+      </div>
+    </div>
+  </div>
+</nav></footer>
+</body>
+</html>
index d6d42604df9a311b53634f93b9fa89e4a7c49576..55797760ff5255d2fad57a903d0d260fba55ebf8 100644 (file)
@@ -42,7 +42,7 @@
     <span class="c1">// a block</span>
         <span class="c1">// that is indented</span>
     <span class="c1">// but has a lot of trailing whitespace which should be removed</span>
-<span class="p">}</span></pre><p>Code block inside a list (has to be done using HTML):</p><ul><li><p>A paragraph.</p><pre class="m-code"><span class="cp">#include</span> <span class="cpf">&lt;os&gt;</span><span class="cp"></span></pre></li><li><p>Another paragraph.</p><p>Yet another</p></li><li>A single paragraph, rendered without the wrapping tag</li></ul>
+<span class="p">}</span></pre><p>Code block inside a list (has to be done using HTML):</p><ul><li><p>A paragraph.</p><pre class="m-code"><span class="cp">#include</span> <span class="cpf">&lt;os&gt;</span><span class="cp"></span></pre></li><li><p>Another paragraph.</p><p>Yet another</p></li><li>A single paragraph, rendered without the wrapping tag</li></ul><aside class="m-note m-info"><h4>Note</h4><p>Code block inside a note:</p><pre class="m-code"><span class="c1">// code block</span></pre><p>Another paragraph of that note.</p></aside>
       </div>
     </div>
   </div>
index 76aa4b63fcea0f84686bfe7687d2606b23d8ca22..29b423b40a5616720e0d27eafda4784ba6bd2e83 100644 (file)
@@ -39,6 +39,15 @@ Code block inside a list (has to be done using HTML):
 <li>A single paragraph, rendered without the wrapping tag</li>
 </ul>
 
+@note
+    Code block inside a note:
+@note
+    @code{.cpp}
+    // code block
+    @endcode
+@note
+    Another paragraph of that note.
+
 */
 
 /** @page warnings Code that produces warnings
index 03347c029f1931def729f0c452cd8fc71d31de57..03fe0f9a662791f14ee12bacb89fda92a891a1fd 100644 (file)
@@ -54,6 +54,13 @@ class Blocks(IntegrationTestCase):
         self.run_dox2html5(wildcard='todo.xml')
         self.assertEqual(*self.actual_expected_contents('todo.html'))
 
+    def test_builtin_xrefitem_merging(self):
+        # Multiple xrefitems should be merged into one here
+        self.run_dox2html5(wildcard='File_8h.xml')
+        self.run_dox2html5(wildcard='old.xml')
+        self.assertEqual(*self.actual_expected_contents('File_8h.html'))
+        self.assertEqual(*self.actual_expected_contents('old.html'))
+
 class Code(IntegrationTestCase):
     def __init__(self, *args, **kwargs):
         super().__init__(__file__, 'code', *args, **kwargs)