From 4bb11fd6cdf736d045369e54fa105dd5d57fdca2 Mon Sep 17 00:00:00 2001 From: Robert Kaussow Date: Tue, 8 Oct 2024 08:26:25 +0200 Subject: [PATCH] feat: add to_code filter and enable codeblocks for tabulated vars (#784) --- ansibledoctor/doc_generator.py | 20 ++ .../templates/hugo-book/_vars_tabulated.j2 | 8 +- .../templates/readme/_vars_tabulated.j2 | 8 +- example/other-role/README.md | 183 +++++++++++++++++- example/other-role/defaults/main.yml | 80 +++++++- 5 files changed, 284 insertions(+), 15 deletions(-) diff --git a/ansibledoctor/doc_generator.py b/ansibledoctor/doc_generator.py index 619600d..3532aca 100644 --- a/ansibledoctor/doc_generator.py +++ b/ansibledoctor/doc_generator.py @@ -96,6 +96,7 @@ class Generator: autoescape=jinja2.select_autoescape(), ) jenv.filters["to_nice_yaml"] = self._to_nice_yaml + jenv.filters["to_code"] = self._to_code jenv.filters["deep_get"] = self._deep_get jenv.filters["safe_join"] = self._safe_join # keep the old name of the function to not break custom templates. @@ -127,6 +128,25 @@ class Generator: yaml.dump(a, stream, **kw) return stream.getvalue().rstrip() + def _to_code(self, a, to_multiline=False, skip_list_len=0, lang="plain"): + """Wrap a string in backticks.""" + if a is None or a == "": + return "" + + if (isinstance(a, list) and len(a) < 1) or (isinstance(a, dict) and not a): + return "" + + if isinstance(a, list) and len(a) == 1: + return f"`{a[0]}`" + + if isinstance(a, list) and skip_list_len > 0 and len(a) > skip_list_len: + return a + + if (isinstance(a, list)) and to_multiline: + return "```" + lang + "\n" + "\n".join(a) + "\n```" + + return f"`{a}`" + def _deep_get(self, _, dictionary, keys): default = None return reduce( diff --git a/ansibledoctor/templates/hugo-book/_vars_tabulated.j2 b/ansibledoctor/templates/hugo-book/_vars_tabulated.j2 index 92fd685..96339e8 100644 --- a/ansibledoctor/templates/hugo-book/_vars_tabulated.j2 +++ b/ansibledoctor/templates/hugo-book/_vars_tabulated.j2 @@ -17,13 +17,13 @@ {% endfor %} | {% for key, item in var | dictsort %} -|{{ key -}} -|{{ (item.value | default({}))[key] | default -}} +|{{ key | to_code -}} +|{{ (item.value | default({}))[key] | default | to_code -}} {% if "description" in found_columns %} |{{ item.description | default([]) | safe_join("
") | replace("\n", "
") | replace("|", "\|") -}} {% endif %} {% if "type" in found_columns %} -|{{ item.type | default([]) | join("
") -}} +|{{ item.type | default([]) | to_code(skip_list_len=1) | safe_join("
") -}} {% endif %} {% if "deprecated" in found_columns %} | @@ -42,7 +42,7 @@ False {% endif %} {% endif %} {% if "example" in found_columns %} -|{{ item.example | default([]) | safe_join("
") | replace("\n", "
") | replace("|", "\|") -}} +|{{ item.example | default([]) | to_code(skip_list_len=1) | safe_join("
") | replace("\n", "
") | replace("|", "\|") -}} {% endif %} | {% endfor %} diff --git a/ansibledoctor/templates/readme/_vars_tabulated.j2 b/ansibledoctor/templates/readme/_vars_tabulated.j2 index 92fd685..96339e8 100644 --- a/ansibledoctor/templates/readme/_vars_tabulated.j2 +++ b/ansibledoctor/templates/readme/_vars_tabulated.j2 @@ -17,13 +17,13 @@ {% endfor %} | {% for key, item in var | dictsort %} -|{{ key -}} -|{{ (item.value | default({}))[key] | default -}} +|{{ key | to_code -}} +|{{ (item.value | default({}))[key] | default | to_code -}} {% if "description" in found_columns %} |{{ item.description | default([]) | safe_join("
") | replace("\n", "
") | replace("|", "\|") -}} {% endif %} {% if "type" in found_columns %} -|{{ item.type | default([]) | join("
") -}} +|{{ item.type | default([]) | to_code(skip_list_len=1) | safe_join("
") -}} {% endif %} {% if "deprecated" in found_columns %} | @@ -42,7 +42,7 @@ False {% endif %} {% endif %} {% if "example" in found_columns %} -|{{ item.example | default([]) | safe_join("
") | replace("\n", "
") | replace("|", "\|") -}} +|{{ item.example | default([]) | to_code(skip_list_len=1) | safe_join("
") | replace("\n", "
") | replace("|", "\|") -}} {% endif %} | {% endfor %} diff --git a/example/other-role/README.md b/example/other-role/README.md index 387921a..fa2c911 100644 --- a/example/other-role/README.md +++ b/example/other-role/README.md @@ -9,7 +9,19 @@ Role to demonstrate ansible-doctor. - [Requirements](#requirements) - [Default Variables](#default-variables) - - [demo_role_unset](#demo_role_unset) + - [demo_bool](#demo_bool) + - [other_role_deprecated](#other_role_deprecated) + - [other_role_deprecated_info](#other_role_deprecated_info) + - [other_role_dict](#other_role_dict) + - [other_role_empty](#other_role_empty) + - [other_role_empty_dict](#other_role_empty_dict) + - [other_role_multiline_type](#other_role_multiline_type) + - [other_role_other_tags](#other_role_other_tags) + - [other_role_override](#other_role_override) + - [other_role_override_complex](#other_role_override_complex) + - [other_role_single](#other_role_single) + - [other_role_undefined_var](#other_role_undefined_var) + - [other_role_unset](#other_role_unset) - [Discovered Tags](#discovered-tags) - [Open Tasks](#open-tasks) - [Dependencies](#dependencies) @@ -24,20 +36,183 @@ Role to demonstrate ansible-doctor. ## Default Variables -### demo_role_unset +### demo_bool + +#### Default value + +```YAML +demo_bool: true +``` + +#### Example usage + +```YAML +demo_bool: false +``` + +### other_role_deprecated + +**_Deprecated_**
+ +#### Default value + +```YAML +other_role_deprecated: b +``` + +### other_role_deprecated_info + +**_Deprecated:_** This variable is deprected since `v2.0.0` and will be removed in a future release.
+**_Type:_** string
+ +#### Default value + +```YAML +other_role_deprecated_info: a +``` + +### other_role_dict + +#### Default value + +```YAML +other_role_dict: + key1: + sub: some value +``` + +#### Example usage + +```YAML +other_role_dict: + key1: + sub: some value + + # Inline description + key2: + sublist: + - subval1 + - subval2 +``` + +### other_role_empty + +#### Default value + +```YAML +other_role_empty: '' +``` + +### other_role_empty_dict + +... or valid json can be used. In this case, the json will be automatically prefixed with the annotation key +and filters like `to_nice_yaml` can be used in templates. To get it working, the json need to be prefixed with a `$`. + +#### Default value + +```YAML +other_role_empty_dict: {} +``` + +#### Example usage + +```YAML +other_role_empty_dict: + key1: + sub: some value + key2: + sublist: + - subval1 + - subval2 +``` + +### other_role_multiline_type + +**_Type:_** string +list +dict
+ +#### Default value + +```YAML +other_role_multiline_type: a +``` + +### other_role_other_tags + +If a variable need some more explanation, this is a good place to do so. + +#### Default value + +```YAML +other_role_other_tags: + - package1 + - package2 +``` + +#### Example usage + +```YAML +other_role_other_tags: + - package1 + - package2 +``` + +### other_role_override + +#### Default value + +```YAML +other_role_override: test +``` + +### other_role_override_complex + +#### Default value + +```YAML +other_role_override_complex: + foo: bar + second: value +``` + +### other_role_single + +#### Default value + +```YAML +other_role_single: b +``` + +### other_role_undefined_var + +To highlight a variable that has not set a value by default, this is one way to achieve it. +Make sure to flag it as json value: `@var other_role_undefined_var: $ "_unset_"` + +| Attribute | Description | +| --- | --- | +| value1 | desc1 | + +#### Default value + +```YAML +other_role_undefined_var: _unset_ +``` + +### other_role_unset Values can be plain strings, but there is no magic or autoformatting... #### Default value ```YAML -demo_role_unset: +other_role_unset: ``` #### Example usage ```YAML -demo_role_unset: some_value +other_role_unset: some_value ``` ## Discovered Tags diff --git a/example/other-role/defaults/main.yml b/example/other-role/defaults/main.yml index 0453c62..a2de3a0 100644 --- a/example/other-role/defaults/main.yml +++ b/example/other-role/defaults/main.yml @@ -1,4 +1,78 @@ --- -# @var demo_role_unset:description: Values can be plain strings, but there is no magic or autoformatting... -# @var demo_role_unset:example: demo_role_unset: some_value -demo_role_unset: +# @var other_role_unset:description: Values can be plain strings, but there is no magic or autoformatting... +# @var other_role_unset:example: other_role_unset: some_value +other_role_unset: + +other_role_empty: "" +other_role_single: "b" + +# @var demo_bool:example: $ false +demo_bool: true + +# @var other_role_empty_dict:description: > +# ... or valid json can be used. In this case, the json will be automatically prefixed with the annotation key +# and filters like `to_nice_yaml` can be used in templates. To get it working, the json need to be prefixed with a `$`. +# @end +# @var other_role_empty_dict:example: $ {"key1": {"sub": "some value"}, "key2": {"sublist": ["subval1", "subval2"]}} +other_role_empty_dict: {} + +# @var other_role_dict:example: > +# other_role_dict: +# key1: +# sub: some value +# +# # Inline description +# key2: +# sublist: +# - subval1 +# - subval2 +# @end +other_role_dict: + key1: + sub: some value + +# @var other_role_undefined_var:description: > +# To highlight a variable that has not set a value by default, this is one way to achieve it. +# Make sure to flag it as json value: `@var other_role_undefined_var: $ "_unset_"` +# +# | Attribute | Description | +# | --- | --- | +# | value1 | desc1 | +# +# @end +# @var other_role_undefined_var: $ "_unset_" + +# @var other_role_other_tags:description: > +# If a variable need some more explanation, this is a good place to do so. +# @end +# @var other_role_other_tags:example: $> +# [ +# "package1", +# "package2" +# ] +# @end +# @var other_role_other_tags:value: $ ["package1", "package2"] +other_role_other_tags: [] + +## Simple value +# @var other_role_override: $ "test" +other_role_override: original + +## Complex value +# @var other_role_override_complex:value: $ {"foo":"bar", "second":"value"} +other_role_override_complex: {} + +# @var other_role_deprecated:deprecated: +other_role_deprecated: "b" + +# @var other_role_deprecated_info:deprecated: > +# This variable is deprected since `v2.0.0` and will be removed in a future release. +# @var other_role_deprecated_info:type: string +other_role_deprecated_info: "a" + +# @var other_role_multiline_type:type: > +# string +# list +# dict +# @end +other_role_multiline_type: "a"