diff --git a/docs/docsite/_static/ansible.css b/docs/docsite/_static/ansible.css
index 3fea13034ad..336d35efd2c 100644
--- a/docs/docsite/_static/ansible.css
+++ b/docs/docsite/_static/ansible.css
@@ -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;
+}
diff --git a/docs/templates/collections_galaxy_meta.rst.j2 b/docs/templates/collections_galaxy_meta.rst.j2
index 87c530e0760..cb3568b32ad 100644
--- a/docs/templates/collections_galaxy_meta.rst.j2
+++ b/docs/templates/collections_galaxy_meta.rst.j2
@@ -16,38 +16,44 @@ Structure
The ``galaxy.yml`` file must contain the following keys in valid YAML:
-.. raw:: html
-
-
- {# Header of the documentation -#}
-
- | Key |
- Comments |
-
- {% for entry in options %}
-
- {# key name with required or type label #}
- |
- @{ entry.key }@
-
- @{ entry.type | documented_type }@
- {% if entry.get('required', False) %} / required{% endif %}
-
- |
- {# Comments #}
-
- {% if entry.description is string %}
- @{ entry.description | replace('\n', '\n ') | html_ify }@
- {% else %}
- {% for desc in entry.description %}
- @{ desc | replace('\n', '\n ') | html_ify }@
- {% endfor %}
- {% endif %}
- |
-
- {% endfor %}
-
-
+
+.. 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
========
diff --git a/docs/templates/plugin.rst.j2 b/docs/templates/plugin.rst.j2
index 65acbb2e220..2edbad34d0d 100644
--- a/docs/templates/plugin.rst.j2
+++ b/docs/templates/plugin.rst.j2
@@ -50,13 +50,9 @@ Synopsis
--------
{% if description -%}
-{% if description is string -%}
-- @{ description | rst_ify }@
-{% else %}
-{% for desc in description %}
+{% for desc in description %}
- @{ desc | rst_ify }@
-{% endfor %}
-{% endif %}
+{% endfor %}
{% endif %}
@@ -183,13 +179,9 @@ Parameters
{% endif %}
{# description #}
- {% if value.description is string %}
- @{ value.description | replace('\n', '\n ') | html_ify }@
- {% else %}
- {% for desc in value.description %}
- @{ desc | replace('\n', '\n ') | html_ify }@
- {% endfor %}
- {% endif %}
+ {% for desc in value.description %}
+ @{ desc | replace('\n', '\n ') | html_ify }@
+ {% endfor %}
{% if 'aliases' in value and value.aliases %}
aliases: @{ value.aliases|join(', ') }@
{% endif %}
diff --git a/hacking/build_library/build_ansible/command_plugins/collection_meta.py b/hacking/build_library/build_ansible/command_plugins/collection_meta.py
index b28797473f2..7b7112e8f9a 100644
--- a/hacking/build_library/build_ansible/command_plugins/collection_meta.py
+++ b/hacking/build_library/build_ansible/command_plugins/collection_meta.py
@@ -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', ''))
diff --git a/hacking/build_library/build_ansible/command_plugins/plugin_formatter.py b/hacking/build_library/build_ansible/command_plugins/plugin_formatter.py
index 7407c97f997..1d2ed459f8a 100644
--- a/hacking/build_library/build_ansible/command_plugins/plugin_formatter.py
+++ b/hacking/build_library/build_ansible/command_plugins/plugin_formatter.py
@@ -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()
diff --git a/hacking/build_library/build_ansible/jinja2/filters.py b/hacking/build_library/build_ansible/jinja2/filters.py
index 735d07b7ba7..21436eda907 100644
--- a/hacking/build_library/build_ansible/jinja2/filters.py
+++ b/hacking/build_library/build_ansible/jinja2/filters.py
@@ -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")
|