diff options
author | Brian Campbell <lambda@continuation.org> | 2018-05-31 13:58:33 -0400 |
---|---|---|
committer | Matt Clay <matt@mystile.com> | 2018-06-01 10:37:39 -0700 |
commit | 7d3ce99a6f848718a2d3ff29335ae7bbf5827079 (patch) | |
tree | f37c2a42b3d34f8a89ca73377a13aa285c1d36c0 /docs | |
parent | 4536fcc722a2bd3b1e200f303b758430842e7002 (diff) | |
download | ansible-7d3ce99a6f848718a2d3ff29335ae7bbf5827079.tar.gz |
Use colspan on td instead of divs for hierarchical tables (#39948)
Address Firefox table-rendering issues in docs. Refactor to use colspan to provide table cells which can vary in width and indentation; the outermost has the greatest colspan, and each nested key has a colspan of one less than the parent, with padding cells for indentation.
Apply styling to table cells to get the table height to work without hacks or browser-specific
styling. Simplify the markup and CSS by removing extra divs. Use two passes over the options, return values, and return facts in the Jinja2 module-docs template: one to determine the maximum nesting depth to compute the maximum colspan needed, plus one to lay out the rows.
(cherry picked from commit fa5c0282a4816c4dd48e80b983ffc1e14506a1f5)
Diffstat (limited to 'docs')
-rw-r--r-- | docs/docsite/_themes/sphinx_rtd_theme/static/css/theme.css | 42 | ||||
-rw-r--r-- | docs/docsite/_themes/srtd/static/css/theme.css | 41 | ||||
-rw-r--r-- | docs/templates/plugin.rst.j2 | 294 |
3 files changed, 162 insertions, 215 deletions
diff --git a/docs/docsite/_themes/sphinx_rtd_theme/static/css/theme.css b/docs/docsite/_themes/sphinx_rtd_theme/static/css/theme.css index e20a3466ef..15fd8915f1 100644 --- a/docs/docsite/_themes/sphinx_rtd_theme/static/css/theme.css +++ b/docs/docsite/_themes/sphinx_rtd_theme/static/css/theme.css @@ -421,51 +421,17 @@ table { max-width: 100%; } - -.outer-elbow-container { - display: flex; - height: 100%; - flex-direction: row; -} - -.elbow-placeholder { +.documentation-table td.elbow-placeholder { border-left: 1px solid #000; - height: 100%; + border-top: 0px; width: 30px; + min-width: 30px; } -.elbow-key { - height: 100%; - padding: 4px; - border-top: 1px solid #000; - flex-grow: 1; - border-left: 1px solid #000; -} - -.elbow-blocker { - height: 0; - overflow: hidden; -} - -.return-value-column { - height: 1px -} - -.return-value-column td { - height: inherit -} - -@-moz-document url-prefix() { - .return-value-column td { - height: 100% - } -} - -.cell-border { +.documentation-table th, .documentation-table td { padding: 4px; border-left: 1px solid #000; border-top: 1px solid #000; - height: 100%; } .documentation-table { diff --git a/docs/docsite/_themes/srtd/static/css/theme.css b/docs/docsite/_themes/srtd/static/css/theme.css index fc4d036c6f..8694ee7a2e 100644 --- a/docs/docsite/_themes/srtd/static/css/theme.css +++ b/docs/docsite/_themes/srtd/static/css/theme.css @@ -4867,50 +4867,17 @@ table { } } -.outer-elbow-container { - display: flex; - height: 100%; - flex-direction: row; -} - -.elbow-placeholder { +.documentation-table td.elbow-placeholder { border-left: 1px solid #000; - height: 100%; + border-top: 0px; width: 30px; + min-width: 30px; } -.elbow-key { - height: 100%; - padding: 4px; - border-top: 1px solid #000; - flex-grow: 1; - border-left: 1px solid #000; -} - -.elbow-blocker { - height: 0; - overflow: hidden; -} - -.return-value-column { - height: 1px -} - -.return-value-column td { - height: inherit -} - -@-moz-document url-prefix() { - .return-value-column td { - height: 100% - } -} - -.cell-border { +.documentation-table th, .documentation-table td { padding: 4px; border-left: 1px solid #000; border-top: 1px solid #000; - height: 100%; } .documentation-table { diff --git a/docs/templates/plugin.rst.j2 b/docs/templates/plugin.rst.j2 index 421e681c57..a928d32758 100644 --- a/docs/templates/plugin.rst.j2 +++ b/docs/templates/plugin.rst.j2 @@ -88,104 +88,107 @@ Parameters .. raw:: html <table border=0 cellpadding=0 class="documentation-table"> + {# Pre-compute the nesting depth to allocate columns #} + {% set ns = namespace(maxdepth=1) %} + {% for key, value in options|dictsort recursive %} + {% set ns.maxdepth = [loop.depth, ns.maxdepth] | max %} + {% if value.suboptions %} + {% if value.suboptions.items %} + @{ loop(value.suboptions.items()) }@ + {% elif value.suboptions[0].items %} + @{ loop(value.suboptions[0].items()) }@ + {% endif %} + {% endif %} + {% endfor %} {# Header of the documentation #} <tr> - <th class="head"><div class="cell-border">Parameter</div></th> - <th class="head"><div class="cell-border">Choices/<font color="blue">Defaults</font></div></th> + <th colspan="@{ ns.maxdepth }@">Parameter</th> + <th>Choices/<font color="blue">Defaults</font></th> {% if plugin_type != 'module' %} - <th class="head"><div class="cell-border">Configuration</div></th> + <th>Configuration</th> {% endif %} - <th class="head" width="100%"><div class="cell-border">Comments</div></th> + <th width="100%">Comments</th> </tr> {% for key, value in options|dictsort recursive %} - <tr class="return-value-column"> + <tr> + {# indentation based on nesting level #} + {% for i in range(1, loop.depth) %} + <td class="elbow-placeholder"></td> + {% endfor %} {# parameter name with required and/or introduced label #} - <td> - <div class="outer-elbow-container"> - {% for i in range(1, loop.depth) %} - <div class="elbow-placeholder"> </div> - {% endfor %} - <div class="elbow-key"> - <b>@{ key }@</b> - {% if value.get('required', False) %}<br/><div style="font-size: small; color: red">required</div>{% endif %} - {% if value.version_added %}<br/><div style="font-size: small; color: darkgreen">(added in @{value.version_added}@)</div>{% endif %} - </div> - </div> + <td colspan="@{ ns.maxdepth - loop.depth0 }@"> + <b>@{ key }@</b> + {% if value.get('required', False) %}<br/><div style="font-size: small; color: red">required</div>{% endif %} + {% if value.version_added %}<br/><div style="font-size: small; color: darkgreen">(added in @{value.version_added}@)</div>{% endif %} </td> {# default / choices #} <td> - <div class="cell-border"> - {# Turn boolean values in 'yes' and 'no' values #} - {% if value.default is sameas true %} - {% set _x = value.update({'default': 'yes'}) %} - {% elif value.default is sameas false %} - {% set _x = value.update({'default': 'no'}) %} - {% endif %} - {% if value.type == 'bool' %} - {% set _x = value.update({'choices': ['no', 'yes']}) %} - {% endif %} - {# Show possible choices and highlight details #} - {% if value.choices %} - <ul><b>Choices:</b> - {% for choice in value.choices %} - {# Turn boolean values in 'yes' and 'no' values #} - {% if choice is sameas true %} - {% set choice = 'yes' %} - {% elif choice is sameas false %} - {% set choice = 'no' %} - {% endif %} - {% if (value.default is string and value.default == choice) or (value.default is iterable and value.default is not string and choice in value.default) %} - <li><div style="color: blue"><b>@{ choice | escape }@</b> ←</div></li> - {% else %} - <li>@{ choice | escape }@</li> - {% endif %} - {% endfor %} - </ul> - {% endif %} - {# Show default value, when multiple choice or no choices #} - {% if value.default is defined and value.default not in value.choices %} - <b>Default:</b><br/><div style="color: blue">@{ value.default | escape }@</div> - {% endif %} - </div> + {# Turn boolean values in 'yes' and 'no' values #} + {% if value.default is sameas true %} + {% set _x = value.update({'default': 'yes'}) %} + {% elif value.default is sameas false %} + {% set _x = value.update({'default': 'no'}) %} + {% endif %} + {% if value.type == 'bool' %} + {% set _x = value.update({'choices': ['no', 'yes']}) %} + {% endif %} + {# Show possible choices and highlight details #} + {% if value.choices %} + <ul><b>Choices:</b> + {% for choice in value.choices %} + {# Turn boolean values in 'yes' and 'no' values #} + {% if choice is sameas true %} + {% set choice = 'yes' %} + {% elif choice is sameas false %} + {% set choice = 'no' %} + {% endif %} + {% if (value.default is string and value.default == choice) or (value.default is iterable and value.default is not string and choice in value.default) %} + <li><div style="color: blue"><b>@{ choice | escape }@</b> ←</div></li> + {% else %} + <li>@{ choice | escape }@</li> + {% endif %} + {% endfor %} + </ul> + {% endif %} + {# Show default value, when multiple choice or no choices #} + {% if value.default is defined and value.default not in value.choices %} + <b>Default:</b><br/><div style="color: blue">@{ value.default | escape }@</div> + {% endif %} </td> {# configuration #} {% if plugin_type != 'module' %} <td> - <div class="cell-border"> - {% if 'ini' in value %} - <div> ini entries: - {% for ini in value.ini %} - <p>[@{ ini.section }@ ]<br>@{ ini.key }@ = @{ value.default | default('VALUE') }@</p> - {% endfor %} - </div> - {% endif %} - {% if 'env' in value %} - {% for env in value.env %} - <div>env:@{ env.name }@</div> + {% if 'ini' in value %} + <div> ini entries: + {% for ini in value.ini %} + <p>[@{ ini.section }@ ]<br>@{ ini.key }@ = @{ value.default | default('VALUE') }@</p> {% endfor %} - {% endif %} - {% if 'vars' in value %} - {% for myvar in value.vars %} - <div>var: @{ myvar.name }@</div> - {% endfor %} - {% endif %} - </div> + </div> + {% endif %} + {% if 'env' in value %} + {% for env in value.env %} + <div>env:@{ env.name }@</div> + {% endfor %} + {% endif %} + {% if 'vars' in value %} + {% for myvar in value.vars %} + <div>var: @{ myvar.name }@</div> + {% endfor %} + {% endif %} </td> {% endif %} {# description #} <td> - <div class="cell-border"> - {% if value.description is string %} - <div>@{ value.description | replace('\n', '\n ') | html_ify }@</div> - {% else %} - {% for desc in value.description %} - <div>@{ desc | replace('\n', '\n ') | html_ify }@</div> - {% endfor %} - {% endif %} - {% if 'aliases' in value and value.aliases %} - <div style="font-size: small; color: darkgreen"><br/>aliases: @{ value.aliases|join(', ') }@</div> - {% endif %} - </div> + {% if value.description is string %} + <div>@{ value.description | replace('\n', '\n ') | html_ify }@</div> + {% else %} + {% for desc in value.description %} + <div>@{ desc | replace('\n', '\n ') | html_ify }@</div> + {% endfor %} + {% endif %} + {% if 'aliases' in value and value.aliases %} + <div style="font-size: small; color: darkgreen"><br/>aliases: @{ value.aliases|join(', ') }@</div> + {% endif %} </td> </tr> {% if value.suboptions %} @@ -242,43 +245,49 @@ Facts returned by this module are added/updated in the ``hostvars`` host facts a .. raw:: html <table border=0 cellpadding=0 class="documentation-table"> + {# Pre-compute the nesting depth to allocate columns #} + {% set ns = namespace(maxdepth=1) %} + {% for key, value in returnfacts|dictsort recursive %} + {% set ns.maxdepth = [loop.depth, ns.maxdepth] | max %} + {% if value.contains %} + {% if value.contains.items %} + @{ loop(value.contains.items()) }@ + {% elif value.contains[0].items %} + @{ loop(value.contains[0].items()) }@ + {% endif %} + {% endif %} + {% endfor %} <tr> - <th class="head"><div class="cell-border">Fact</div></th> - <th class="head"><div class="cell-border">Returned</div></th> - <th class="head" width="100%"><div class="cell-border">Description</div></th> + <th colspan="@{ ns.maxdepth }@">Fact</th> + <th>Returned</th> + <th width="100%">Description</th> </tr> {% for key, value in returnfacts|dictsort recursive %} - <tr class="return-value-column"> - <td> - <div class="outer-elbow-container"> - {% for i in range(1, loop.depth) %} - <div class="elbow-placeholder"> </div> - {% endfor %} - <div class="elbow-key"> - <b>@{ key }@</b> - <br/><div style="font-size: small; color: red">@{ value.type }@</div> - </div> - </div> + <tr> + {% for i in range(1, loop.depth) %} + <td class="elbow-placeholder"></td> + {% endfor %} + <td colspan="@{ ns.maxdepth - loop.depth0 }@" colspan="@{ ns.maxdepth - loop.depth0 }@"> + <b>@{ key }@</b> + <br/><div style="font-size: small; color: red">@{ value.type }@</div> </td> - <td><div class="cell-border">@{ value.returned | html_ify }@</div></td> + <td>@{ value.returned | html_ify }@</td> <td> - <div class="cell-border"> - {% if value.description is string %} - <div>@{ value.description | html_ify }@ + {% if value.description is string %} + <div>@{ value.description | html_ify }@ + </div> + {% else %} + {% for desc in value.description %} + <div>@{ desc | html_ify }@ </div> - {% else %} - {% for desc in value.description %} - <div>@{ desc | html_ify }@ - </div> - {% endfor %} - {% endif %} - <br/> - {% if value.sample is defined and value.sample %} - <div style="font-size: smaller"><b>Sample:</b></div> - {# TODO: The sample should be escaped, using | escape or | htmlify, but both mess things up beyond repair with dicts #} - <div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">@{ value.sample | replace('\n', '\n ') | html_ify }@</div> - {% endif %} - </div> + {% endfor %} + {% endif %} + <br/> + {% if value.sample is defined and value.sample %} + <div style="font-size: smaller"><b>Sample:</b></div> + {# TODO: The sample should be escaped, using | escape or | htmlify, but both mess things up beyond repair with dicts #} + <div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">@{ value.sample | replace('\n', '\n ') | html_ify }@</div> + {% endif %} </td> </tr> {# --------------------------------------------------------- @@ -308,41 +317,46 @@ Common return values are documented :ref:`here <common_return_values>`, the foll .. raw:: html <table border=0 cellpadding=0 class="documentation-table"> + {% set ns = namespace(maxdepth=1) %} + {% for key, value in returndocs|dictsort recursive %} + {% set ns.maxdepth = [loop.depth, ns.maxdepth] | max %} + {% if value.contains %} + {% if value.contains.items %} + @{ loop(value.contains.items()) }@ + {% elif value.contains[0].items %} + @{ loop(value.contains[0].items()) }@ + {% endif %} + {% endif %} + {% endfor %} <tr> - <th class="head"><div class="cell-border">Key</div></th> - <th class="head"><div class="cell-border">Returned</div></th> - <th class="head" width="100%"><div class="cell-border">Description</div></th> + <th colspan="@{ ns.maxdepth }@">Key</th> + <th>Returned</th> + <th width="100%">Description</th> </tr> {% for key, value in returndocs|dictsort recursive %} - <tr class="return-value-column"> - <td> - <div class="outer-elbow-container"> - {% for i in range(1, loop.depth) %} - <div class="elbow-placeholder"> </div> - {% endfor %} - <div class="elbow-key"> - <b>@{ key }@</b> - <br/><div style="font-size: small; color: red">@{ value.type }@</div> - </div> - </div> + <tr> + {% for i in range(1, loop.depth) %} + <td class="elbow-placeholder"> </td> + {% endfor %} + <td colspan="@{ ns.maxdepth - loop.depth0 }@"> + <b>@{ key }@</b> + <br/><div style="font-size: small; color: red">@{ value.type }@</div> </td> - <td><div class="cell-border">@{ value.returned | html_ify }@</div></td> + <td>@{ value.returned | html_ify }@</td> <td> - <div class="cell-border"> - {% if value.description is string %} - <div>@{ value.description | html_ify |indent(4)}@</div> - {% else %} - {% for desc in value.description %} - <div>@{ desc | html_ify |indent(4)}@</div> - {% endfor %} - {% endif %} - <br/> - {% if value.sample is defined and value.sample %} - <div style="font-size: smaller"><b>Sample:</b></div> - {# TODO: The sample should be escaped, using |escape or |htmlify, but both mess things up beyond repair with dicts #} - <div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">@{ value.sample | replace('\n', '\n ') | html_ify }@</div> - {% endif %} - </div> + {% if value.description is string %} + <div>@{ value.description | html_ify |indent(4)}@</div> + {% else %} + {% for desc in value.description %} + <div>@{ desc | html_ify |indent(4)}@</div> + {% endfor %} + {% endif %} + <br/> + {% if value.sample is defined and value.sample %} + <div style="font-size: smaller"><b>Sample:</b></div> + {# TODO: The sample should be escaped, using |escape or |htmlify, but both mess things up beyond repair with dicts #} + <div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">@{ value.sample | replace('\n', '\n ') | html_ify }@</div> + {% endif %} </td> </tr> {# --------------------------------------------------------- |