Galaxy meta docs table (#60171)
* Use an rst table instead of a raw html table * Rst is easier to read so we want to use it wherever possible * Fix the jinja2 filters which create links so that they do not include extraneous whitespace in the URL * Normalize description data before sending them to the templates
This commit is contained in:
parent
60f8483603
commit
d9b3af523b
6 changed files with 127 additions and 56 deletions
|
@ -4,13 +4,63 @@
|
|||
/* override table width restrictions */
|
||||
@media screen and (min-width: 767px) {
|
||||
|
||||
/* If we ever publish to read the docs, we need to use !important for these
|
||||
* two styles as read the docs itself loads their theme in a way that we
|
||||
* can't otherwise override it.
|
||||
*/
|
||||
.wy-table-responsive table td {
|
||||
/* !important prevents the common CSS stylesheets from overriding
|
||||
this as on RTD they are loaded after this stylesheet */
|
||||
white-space: normal !important;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.wy-table-responsive {
|
||||
overflow: visible !important;
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We use the class documentation-table for attribute tables where the first
|
||||
* column is the name of an attribute and the second column is the description.
|
||||
*/
|
||||
|
||||
/* These tables look like this:
|
||||
*
|
||||
* Attribute Name Description
|
||||
* -------------- -----------
|
||||
* **NAME** This is a multi-line description
|
||||
* str/required that can span multiple lines
|
||||
*
|
||||
* With multiple paragraphs
|
||||
* -------------- -----------
|
||||
*
|
||||
* **NAME** is given the class .value-name
|
||||
* str is given the class .value-type
|
||||
* / is given the class .value-separator
|
||||
* required is given the class .value-required
|
||||
*/
|
||||
|
||||
table.documentation-table td:first-child {
|
||||
white-space: nowrap;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.documentation-table .value-name {
|
||||
font-weight: bold;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
table.documentation-table .value-type {
|
||||
font-size: x-small;
|
||||
color: purple;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
table.documentation-table .value-separator {
|
||||
font-size: x-small;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
table.documentation-table .value-required {
|
||||
font-size: x-small;
|
||||
color: red;
|
||||
display: inline;
|
||||
}
|
||||
|
|
68
docs/templates/collections_galaxy_meta.rst.j2
vendored
68
docs/templates/collections_galaxy_meta.rst.j2
vendored
|
@ -16,38 +16,44 @@ Structure
|
|||
|
||||
The ``galaxy.yml`` file must contain the following keys in valid YAML:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<table border=0 cellpadding=0 class="documentation-table">
|
||||
{# Header of the documentation -#}
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th width="100%">Comments</th>
|
||||
</tr>
|
||||
{% for entry in options %}
|
||||
<tr>
|
||||
{# key name with required or type label #}
|
||||
<td>
|
||||
<b>@{ entry.key }@</b>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">@{ entry.type | documented_type }@</span>
|
||||
{% if entry.get('required', False) %} / <span style="color: red">required</span>{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
{# Comments #}
|
||||
<td>
|
||||
{% if entry.description is string %}
|
||||
<div>@{ entry.description | replace('\n', '\n ') | html_ify }@</div>
|
||||
{% else %}
|
||||
{% for desc in entry.description %}
|
||||
<div>@{ desc | replace('\n', '\n ') | html_ify }@</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<br/>
|
||||
.. rst-class:: documentation-table
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:widths: auto
|
||||
|
||||
* - Key
|
||||
- Comment
|
||||
|
||||
{%- for entry in options %}
|
||||
|
||||
|
||||
* - .. rst-class:: value-name
|
||||
|
||||
@{ entry.key }@ |br|
|
||||
|
||||
.. rst-class:: value-type
|
||||
|
||||
@{ entry.type | documented_type }@ |_|
|
||||
|
||||
{% if entry.get('required', False) -%}
|
||||
.. rst-class:: value-separator
|
||||
|
||||
/ |_|
|
||||
|
||||
.. rst-class:: value-required
|
||||
|
||||
required
|
||||
{%- endif %}
|
||||
|
||||
|
||||
- {% for desc in entry.description -%}
|
||||
@{ desc | trim | rst_ify }@
|
||||
|
||||
{% endfor -%}
|
||||
{%- endfor %}
|
||||
|
||||
|
||||
Examples
|
||||
========
|
||||
|
|
8
docs/templates/plugin.rst.j2
vendored
8
docs/templates/plugin.rst.j2
vendored
|
@ -50,13 +50,9 @@ Synopsis
|
|||
--------
|
||||
{% if description -%}
|
||||
|
||||
{% if description is string -%}
|
||||
- @{ description | rst_ify }@
|
||||
{% else %}
|
||||
{% for desc in description %}
|
||||
- @{ desc | rst_ify }@
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
@ -183,13 +179,9 @@ Parameters
|
|||
{% endif %}
|
||||
{# description #}
|
||||
<td>
|
||||
{% 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 %}
|
||||
|
|
|
@ -12,18 +12,26 @@ import pathlib
|
|||
|
||||
import yaml
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.module_utils._text import to_bytes
|
||||
|
||||
# Pylint doesn't understand Python3 namespace modules.
|
||||
from ..change_detection import update_file_if_different # pylint: disable=relative-beyond-top-level
|
||||
from ..commands import Command # pylint: disable=relative-beyond-top-level
|
||||
from ..jinja2.filters import documented_type, html_ify # pylint: disable=relative-beyond-top-level
|
||||
from ..jinja2.filters import documented_type, rst_ify # pylint: disable=relative-beyond-top-level
|
||||
|
||||
|
||||
DEFAULT_TEMPLATE_FILE = 'collections_galaxy_meta.rst.j2'
|
||||
DEFAULT_TEMPLATE_DIR = pathlib.Path(__file__).parents[4] / 'docs/templates'
|
||||
|
||||
|
||||
def normalize_options(options):
|
||||
"""Normalize the options to make for easy templating"""
|
||||
for opt in options:
|
||||
if isinstance(opt['description'], string_types):
|
||||
opt['description'] = [opt['description']]
|
||||
|
||||
|
||||
class DocumentCollectionMeta(Command):
|
||||
name = 'collection-meta'
|
||||
|
||||
|
@ -51,12 +59,14 @@ class DocumentCollectionMeta(Command):
|
|||
with open(args.collection_defs) as f:
|
||||
options = yaml.safe_load(f)
|
||||
|
||||
normalize_options(options)
|
||||
|
||||
env = Environment(loader=FileSystemLoader(template_dir),
|
||||
variable_start_string="@{",
|
||||
variable_end_string="}@",
|
||||
trim_blocks=True)
|
||||
env.filters['documented_type'] = documented_type
|
||||
env.filters['html_ify'] = html_ify
|
||||
env.filters['rst_ify'] = rst_ify
|
||||
|
||||
template = env.get_template(template_file)
|
||||
output_name = os.path.join(output_dir, template_file.replace('.j2', ''))
|
||||
|
|
|
@ -386,8 +386,17 @@ def process_plugins(module_map, templates, outputname, output_dir, ansible_versi
|
|||
if field in doc and doc[field] in (None, ''):
|
||||
print("%s: WARNING: MODULE field '%s' DOCUMENTATION is null/empty value=%s" % (fname, field, doc[field]))
|
||||
|
||||
if 'description' in doc:
|
||||
if isinstance(doc['description'], string_types):
|
||||
doc['description'] = [doc['description']]
|
||||
elif not isinstance(doc['description'], (list, tuple)):
|
||||
raise AnsibleError("Description must be a string or list of strings. Got %s"
|
||||
% type(doc['description']))
|
||||
else:
|
||||
doc['description'] = []
|
||||
|
||||
if 'version_added' not in doc:
|
||||
display.error("*** ERROR: missing version_added in: %s ***\n" % module)
|
||||
raise AnsibleError("*** ERROR: missing version_added in: %s ***\n" % module)
|
||||
|
||||
#
|
||||
# The present template gets everything from doc so we spend most of this
|
||||
|
@ -416,6 +425,14 @@ def process_plugins(module_map, templates, outputname, output_dir, ansible_versi
|
|||
if 'description' not in doc['options'][k]:
|
||||
raise AnsibleError("Missing required description for parameter '%s' in '%s' " % (k, module))
|
||||
|
||||
# Make sure description is a list of lines for later formatting
|
||||
if isinstance(doc['options'][k]['description'], string_types):
|
||||
doc['options'][k]['description'] = [doc['options'][k]['description']]
|
||||
elif not isinstance(doc['options'][k]['description'], (list, tuple)):
|
||||
raise AnsibleError("Invalid type for options['%s']['description']."
|
||||
" Must be string or list of strings. Got %s" %
|
||||
(k, type(doc['options'][k]['description'])))
|
||||
|
||||
# Error out if required isn't a boolean (people have been putting
|
||||
# information on when something is required in here. Those need
|
||||
# to go in the description instead).
|
||||
|
@ -427,10 +444,6 @@ def process_plugins(module_map, templates, outputname, output_dir, ansible_versi
|
|||
if 'version_added' in doc['options'][k] and too_old(doc['options'][k]['version_added']):
|
||||
del doc['options'][k]['version_added']
|
||||
|
||||
# Make sure description is a list of lines for later formatting
|
||||
if not isinstance(doc['options'][k]['description'], list):
|
||||
doc['options'][k]['description'] = [doc['options'][k]['description']]
|
||||
|
||||
option_names.append(k)
|
||||
|
||||
option_names.sort()
|
||||
|
|
|
@ -27,7 +27,7 @@ _ITALIC = re.compile(r"I\(([^)]+)\)")
|
|||
_BOLD = re.compile(r"B\(([^)]+)\)")
|
||||
_MODULE = re.compile(r"M\(([^)]+)\)")
|
||||
_URL = re.compile(r"U\(([^)]+)\)")
|
||||
_LINK = re.compile(r"L\(([^)]+),([^)]+)\)")
|
||||
_LINK = re.compile(r"L\(([^)]+), *([^)]+)\)")
|
||||
_CONST = re.compile(r"C\(([^)]+)\)")
|
||||
_RULER = re.compile(r"HORIZONTALLINE")
|
||||
|
||||
|
|
Loading…
Reference in a new issue