Compare commits

...

17 commits

5245 changed files with 8217 additions and 6320 deletions

View file

@ -1,403 +1,64 @@
## 0.2.0a50 (2026-06-11) ## 1.0.3 (2026-06-28)
### Fix
- help line with only a space in family description
## 1.0.2 (2026-06-27)
### Fix
- hidden family in dynamic family with a sub root
## 1.0.1 (2026-06-21)
### Fix
- dependencies
## 1.0.0 (2026-06-21)
### Feat ### Feat
- better ansible documentation
- leadership => sequence - leadership => sequence
### Fix
- test example with mode
## 0.2.0a49 (2026-05-06)
### Fix
- example for partial documentation
## 0.2.0a48 (2026-05-04)
### Fix
- get unrestraint default value
## 0.2.0a47 (2026-04-30)
### Feat
- add dot if needed - add dot if needed
- better documentation generation - better documentation generation
### Fix
- better identifier documentation
- better display of path
- better description informations
- do not display {{ identifier }} in description
- better identifier support
- support mode
- root config with identifier
## 0.2.0a46 (2026-01-29)
### Feat
- support transitive - support transitive
### Fix
- better transitive documentation
- update translation
## 0.2.0a45 (2026-01-21)
### Feat
- doc transitive properties - doc transitive properties
### Fix
- root could be a variable
- path
## 0.2.0a44 (2026-01-14)
### Fix
- yaml in output format do not convert object to str
## 0.2.0a43 (2026-01-14)
### Feat
- add 'document_a_type' option - add 'document_a_type' option
## 0.2.0a42 (2026-01-04)
### Feat
- remove doc.root, pass directly the family to doc output (be careful, add true_config parameter too) - remove doc.root, pass directly the family to doc output (be careful, add true_config parameter too)
## 0.2.0a41 (2025-12-30)
### Fix
- update tests
- read_write is a boolean
## 0.2.0a40 (2025-12-22)
### Feat
- personalise column number - personalise column number
- document commandline and environment variable - document commandline and environment variable
### Fix
- better documentation
- better commandline doc + params description is now in rougail
## 0.2.0a39 (2025-11-21)
### Feat
- change path in description - change path in description
- add anchor to markdown format and remove unsupported character in anchor id - add anchor to markdown format and remove unsupported character in anchor id
- use blockquote for family description - use blockquote for family description
### Fix
- dynamic variables with identifier in description
- gitlab id in anchor with dynamic variables
## 0.2.0a38 (2025-11-10)
### Feat
- better enter support - better enter support
## 0.2.0a37 (2025-11-06)
### Feat
- delete/underline is inside tag for some format - delete/underline is inside tag for some format
- can reload formatter - can reload formatter
- can document part by part with reloading structure - can document part by part with reloading structure
## 0.2.0a36 (2025-10-29)
### Feat
- anchor in gitlab output_format - anchor in gitlab output_format
- can had comments with family/variable description in examples doc - can had comments with family/variable description in examples doc
- comment variables from a family - comment variables from a family
## 0.2.0a35 (2025-10-27)
### Feat
- tags documentation - tags documentation
### Fix
- add changelog support for github/gitlab format
- tests
## 0.2.0a34 (2025-10-22)
### Feat
- ca force true_color terminal when export to console - ca force true_color terminal when export to console
### Fix
- parse subtree for a dynamic
- adapt api for rougail-web-ui
- undocumented variable in dynamic
## 0.2.0a33 (2025-10-16)
### Feat
- can document a variable for a specified identifier - can document a variable for a specified identifier
- can remove header when generate a table - can remove header when generate a table
- add html output - add html output
- changelog for variables - changelog for variables
### Fix
- support rougail-web-ui
- black
- remove extra '*'
- always use name for informations key (sometime path was used)
- update tests
- translation for property is now in rougail
## 0.2.0a32 (2025-10-03)
### Fix
- property calculated with disabled variable
- better disabled support
## 0.2.0a31 (2025-10-02)
### Feat
- limit warning when asked - limit warning when asked
## 0.2.0a30 (2025-10-02)
### Feat
- better support variable calculation for property - better support variable calculation for property
## 0.2.0a29 (2025-10-02)
### Fix
- property for namespace
## 0.2.0a28 (2025-10-02)
### Feat
- add gitlab plugin - add gitlab plugin
### Fix
- tests for formatter
- update translation
## 0.2.0a27 (2025-09-29)
### Fix
- doc network with CIDR format
- better doc for calculation with unknown variable
## 0.2.0a26 (2025-09-29)
### Feat
- default value for a calculated variable with an unknown optional variable - default value for a calculated variable with an unknown optional variable
- add integer type which will replace number type - add integer type which will replace number type
## 0.2.0a25 (2025-09-22)
### Feat
- adapt to tiramisu-web-ui - adapt to tiramisu-web-ui
## 0.2.0a24 (2025-06-19)
### Feat
- could not change default value during annotator - could not change default value during annotator
## 0.2.0a23 (2025-06-18)
### Fix
- separation
## 0.2.0a22 (2025-06-18)
### Fix
- rougail separation
## 0.2.0a21 (2025-05-12)
### Fix
- update translation
- black
- doc example with leader example lower than leader default value
## 0.2.0a20 (2025-05-09)
### Fix
- undefined is a rougail object
## 0.2.0a19 (2025-05-05)
### Fix
- update translation
## 0.2.0a18 (2025-05-05)
### Fix
- doc default value with undocumented variable
## 0.2.0a17 (2025-05-05)
### Fix
- description for all calculations
- better documentation variable with variable in default attribut
## 0.2.0a16 (2025-04-30)
### Fix
- update translation
- remove negative_description support
- better documentation with hidden variable in property calculation
- use new information ymlfiles
- update tests
- better dynamic support
## 0.2.0a15 (2025-04-09)
### Fix
- version
## 0.2.0a14 (2025-04-07)
### Fix
- calculation for dynamic ans leadership variables
## 0.2.0a13 (2025-04-02)
### Fix
- error in disabled dynamic variable
## 0.2.0a12 (2025-04-01)
### Fix
- update tests
- groups.namespace could be unexistant
## 0.2.0a11 (2025-03-31)
### Fix
- doc a param with a set but with only one item
## 0.2.0a10 (2025-03-30)
### Feat
- document unix file name parameters - document unix file name parameters
- better console output - better console output
- do not document reference to undocumented variable - do not document reference to undocumented variable
### Fix
- doc for param
- support NamespaceCalculation
- convert <ENV> to &lt;ENV&gt; for github plugin
## 0.2.0a9 (2025-02-19)
### Fix
- support suffix (in version 1.0 format) in calculation
## 0.2.0a8 (2025-02-19)
### Fix
- key is the path
## 0.2.0a7 (2025-02-19)
### Fix
- with_family => without_family and with_example => example
## 0.2.0a6 (2025-02-17)
### Feat
- add with_family parameter - add with_family parameter
## 0.2.0a5 (2025-02-17)
### Fix
- do not add multiple attribute several time in json export
## 0.2.0a4 (2025-02-10)
### Feat
- output return status too - output return status too
## 0.2.0a3 (2025-01-04)
### Fix
- detect_symlink => only_self
## 0.2.0a2 (2025-01-04)
### Feat
- create tests - create tests
### Fix
- do not document symlink
- remove prefix_path
## 0.2.0a1 (2024-11-28)
### Fix
- separation between run and print function
## 0.2.0a0 (2024-11-20)
### Feat
- personalize mode that we want disable documentation - personalize mode that we want disable documentation
- add console output - add console output
- better dynamique family support - better dynamique family support
@ -405,14 +66,90 @@
### Fix ### Fix
- rougail dependencies
- black
- tests
- update tests
- test example with mode
- example for partial documentation
- get unrestraint default value
- better identifier documentation
- better display of path
- better description informations
- do not display {{ identifier }} in description
- better identifier support
- support mode
- root config with identifier
- better transitive documentation
- update translation
- root could be a variable
- path
- yaml in output format do not convert object to str
- update tests
- read_write is a boolean
- better documentation
- better commandline doc + params description is now in rougail
- dynamic variables with identifier in description
- gitlab id in anchor with dynamic variables
- add changelog support for github/gitlab format
- tests
- parse subtree for a dynamic
- adapt api for rougail-web-ui
- undocumented variable in dynamic
- support rougail-web-ui
- black
- remove extra '*'
- always use name for informations key (sometime path was used)
- update tests
- translation for property is now in rougail
- property calculated with disabled variable
- better disabled support
- property for namespace
- tests for formatter
- update translation
- doc network with CIDR format
- better doc for calculation with unknown variable
- separation
- rougail separation
- update translation
- black
- doc example with leader example lower than leader default value
- undefined is a rougail object
- update translation
- doc default value with undocumented variable
- description for all calculations
- better documentation variable with variable in default attribut
- update translation
- remove negative_description support
- better documentation with hidden variable in property calculation
- use new information ymlfiles
- update tests
- better dynamic support
- version
- calculation for dynamic ans leadership variables
- error in disabled dynamic variable
- update tests
- groups.namespace could be unexistant
- doc a param with a set but with only one item
- doc for param
- support NamespaceCalculation
- convert <ENV> to &lt;ENV&gt; for github plugin
- support suffix (in version 1.0 format) in calculation
- key is the path
- with_family => without_family and with_example => example
- do not add multiple attribute several time in json export
- detect_symlink => only_self
- do not document symlink
- remove prefix_path
- separation between run and print function
- correction for properties in italic - correction for properties in italic
## 0.1.1a0 (2024-11-08)
### Fix
- generate documentation with force_optional configuration - generate documentation with force_optional configuration
### Refactor
- **locale-po**: locale translation
- **typo**: french translation type
## 0.1.0 (2024-11-06) ## 0.1.0 (2024-11-06)
## 0.1.0rc1 (2024-11-06) ## 0.1.0rc1 (2024-11-06)

View file

@ -391,8 +391,8 @@ msgid "Example with mandatory variables not filled in"
msgstr "Exemple avec des variables obligatoire non renseignée" msgstr "Exemple avec des variables obligatoire non renseignée"
#: src/rougail/output_doc/example.py:63 #: src/rougail/output_doc/example.py:63
msgid "Example with all variables modifiable" msgid "Example with all modifiable variables"
msgstr "Exemple avec toutes les variables modifiable" msgstr "Exemple avec toutes les variables modifiables"
#: src/rougail/output_doc/output/asciidoc.py:156 #: src/rougail/output_doc/output/asciidoc.py:156
#: src/rougail/output_doc/output/console.py:234 #: src/rougail/output_doc/output/console.py:234

View file

@ -341,7 +341,7 @@ msgid "Example with mandatory variables not filled in"
msgstr "" msgstr ""
#: src/rougail/output_doc/example.py:63 #: src/rougail/output_doc/example.py:63
msgid "Example with all variables modifiable" msgid "Example with all modifiable variables"
msgstr "" msgstr ""
#: src/rougail/output_doc/output/asciidoc.py:156 #: src/rougail/output_doc/output/asciidoc.py:156

View file

@ -4,7 +4,7 @@ requires = ["flit_core >=3.8.0,<4"]
[project] [project]
name = "rougail.output_doc" name = "rougail.output_doc"
version = "0.2.0a50" version = "1.0.3"
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}] authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
readme = "README.md" readme = "README.md"
description = "Rougail output doc" description = "Rougail output doc"
@ -24,8 +24,8 @@ classifiers = [
] ]
dependencies = [ dependencies = [
"rougail-base > 1.1,<2", "rougail-base >= 1.2.0,<2",
"tabulate ~= 0.9.0", "tabulate ~= 0.10.0", # same as rougail-output-table
"rich ~= 13.9.3", "rich ~= 13.9.3",
] ]

View file

@ -1,7 +1,7 @@
""" """
Silique (https://www.silique.fr) Silique (https://www.silique.fr)
Copyright (C) 2024-2026 Copyright (C) 2024-2026
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the under the terms of the GNU Lesser General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your Free Software Foundation, either version 3 of the License, or (at your

View file

@ -1 +1 @@
__version__ = "0.2.0a50" __version__ = "1.0.3"

View file

@ -63,6 +63,12 @@ class Annotator(Walk):
self.default_values = kwargs["force_default_value"] self.default_values = kwargs["force_default_value"]
else: else:
self.default_values = self.objectspace.rougailconfig["doc.default_values"] self.default_values = self.objectspace.rougailconfig["doc.default_values"]
if "force_display_unknown_optional_variable" in kwargs:
self.display_unknown_optional_variable = kwargs[
"force_display_unknown_optional_variable"
]
else:
self.display_unknown_optional_variable = False
self.regexp_description_get_paths = None self.regexp_description_get_paths = None
self.populate_family() self.populate_family()
self.populate_variable() self.populate_variable()
@ -260,16 +266,19 @@ class Annotator(Walk):
values.xmlfiles, values.xmlfiles,
) )
if variable: if variable:
val_description = val_description.replace(f'"{r_path}"', f'{{{index}}}') val_description = val_description.replace(
f'"{r_path}"', f"{{{index}}}"
)
v = {"path": variable.path, "description": variable.description} v = {"path": variable.path, "description": variable.description}
if identifiers: if identifiers:
v["identifiers"] = [identifiers] v["identifiers"] = [identifiers]
v["identifier_type"] = "many" v["identifier_type"] = "many"
variables.append(v) variables.append(v)
index += 1 index += 1
description = {"description": True, description = {
"value": val_description, "description": True,
} "value": val_description,
}
if variables: if variables:
description["variables"] = variables description["variables"] = variables
else: else:
@ -334,16 +343,20 @@ class Annotator(Walk):
if not variable or ( if not variable or (
isinstance(values, VariableCalculation) and values.optional and not variable isinstance(values, VariableCalculation) and values.optional and not variable
): ):
return None if self.display_unknown_optional_variable and values.optional:
values_calculation = {"path": variable.path} values_calculation = {"path": variable_path}
if identifiers: else:
values_calculation["identifiers"] = identifiers values_calculation = None
values_calculation["identifier_type"] = "many"
if prop in PROPERTY_ATTRIBUTE:
# get comparative value
self.when_to_condition(values, values_calculation)
else: else:
values_calculation["type"] = "variable" values_calculation = {"path": variable.path}
if identifiers:
values_calculation["identifiers"] = identifiers
values_calculation["identifier_type"] = "many"
if prop in PROPERTY_ATTRIBUTE:
# get comparative value
self.when_to_condition(values, values_calculation)
else:
values_calculation["type"] = "variable"
return values_calculation return values_calculation
def when_to_condition(self, values, values_calculation): def when_to_condition(self, values, values_calculation):

View file

@ -1,7 +1,7 @@
""" """
Silique (https://www.silique.fr) Silique (https://www.silique.fr)
Copyright (C) 2025-2026 Copyright (C) 2025-2026
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the under the terms of the GNU Lesser General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your Free Software Foundation, either version 3 of the License, or (at your
@ -178,7 +178,9 @@ class Changelog: # pylint: disable=no-member,too-few-public-methods
else: else:
title = _("Deleted variables") title = _("Deleted variables")
lst.append(self.formatter.title(title, self.level)) lst.append(self.formatter.title(title, self.level))
lst.append(self.formatter.list(self._removed_variables, inside_tabular=False)) lst.append(
self.formatter.list(self._removed_variables, inside_tabular=False)
)
end = self.formatter.end_family(self.level) end = self.formatter.end_family(self.level)
if end: if end:
lst.append(end) lst.append(end)

View file

@ -24,7 +24,11 @@ from tiramisu.error import display_list, PropertiesOptionError
from tiramisu.config import get_common_path from tiramisu.config import get_common_path
from rougail.tiramisu import display_xmlfiles from rougail.tiramisu import display_xmlfiles
from rougail.utils import PROPERTY_ATTRIBUTE from rougail.utils import PROPERTY_ATTRIBUTE
from rougail.error import VariableCalculationDependencyError, RougailWarning, ExtensionError from rougail.error import (
VariableCalculationDependencyError,
RougailWarning,
ExtensionError,
)
from .utils import dump, to_phrase, calc_path, add_dot, doc_path from .utils import dump, to_phrase, calc_path, add_dot, doc_path
from .i18n import _ from .i18n import _
@ -67,7 +71,9 @@ class _ToString:
return ret[0] return ret[0]
return ret return ret
def _calculation_to_string(self, child, calculation, attribute_type, inside_list=True): def _calculation_to_string(
self, child, calculation, attribute_type, inside_list=True
):
if calculation.get("description", False): if calculation.get("description", False):
values = calculation.copy() values = calculation.copy()
if self.document_a_type and "variables" in values: if self.document_a_type and "variables" in values:
@ -110,7 +116,9 @@ class _ToString:
if not inside_list: if not inside_list:
msg = add_dot(msg) msg = add_dot(msg)
variable = self.true_config.unrestraint.option(calculation["path"]) variable = self.true_config.unrestraint.option(calculation["path"])
values = self._calculation_with_variable(child, variable, calculation, msg) values = self._calculation_with_variable(
child, variable, calculation, msg
)
else: else:
values = _('the value of the global information "{0}"').format( values = _('the value of the global information "{0}"').format(
calculation["information"] calculation["information"]
@ -153,12 +161,18 @@ class _ToString:
variable_path = condition["path"] variable_path = condition["path"]
values = [] values = []
option = self.true_config.option(variable_path) option = self.true_config.option(variable_path)
if option.isdynamic(): try:
option.get()
except AttributeError:
defined = False
else:
defined = True
if defined and option.isdynamic():
variables = self._get_annotation_variable( variables = self._get_annotation_variable(
child, option, condition.get("identifiers") child, option, condition.get("identifiers")
) )
else: else:
option = self.true_config.option(variable_path) # option = self.true_config.option(variable_path)
try: try:
is_inaccessible = self.is_inaccessible_user_data(option) is_inaccessible = self.is_inaccessible_user_data(option)
except AttributeError as err: except AttributeError as err:
@ -173,10 +187,10 @@ class _ToString:
for cpath, description, identifiers, identifier_type in variables: for cpath, description, identifiers, identifier_type in variables:
if not cpath: if not cpath:
# we cannot access to this variable, so try with permissive # we cannot access to this variable, so try with permissive
if condition["type"] == "transitive": if condition.get("type") == "transitive":
value = None value = None
else: else:
value = condition["value"] value = condition.get("value")
option = self.true_config.forcepermissive.option(variable_path) option = self.true_config.forcepermissive.option(variable_path)
try: try:
variable_value = self._get_unmodified_default_value(option) variable_value = self._get_unmodified_default_value(option)
@ -225,7 +239,7 @@ class _ToString:
submsg = display_list( submsg = display_list(
[_("is {0}").format(prop), submsg], separator="or", sort=False [_("is {0}").format(prop), submsg], separator="or", sort=False
) )
msg = _('when the variable {{0}} {0}.').format(submsg) msg = _("when the variable {{0}} {0}.").format(submsg)
path_obj = { path_obj = {
"path": doc_path(variable_path, self.document_a_type), "path": doc_path(variable_path, self.document_a_type),
} }
@ -247,16 +261,27 @@ class _ToString:
def _calculation_variable_to_string_not_property( def _calculation_variable_to_string_not_property(
self, child, calculation, attribute_type self, child, calculation, attribute_type
): ):
variable = self.true_config.unrestraint.option(calculation["value"]["path"]) path = calculation["value"]["path"]
variable = self.true_config.unrestraint.option(path)
defined = True
if calculation["optional"]: if calculation["optional"]:
# option?
try: try:
variable.get() variable.get()
except AttributeError: except AttributeError:
return None defined = False
true_msg = _('the value of the variable {0} if it is defined') true_msg = _("the value of the variable {0} if it is defined")
else: else:
true_msg = _('the value of the variable {0}') true_msg = _("the value of the variable {0}")
return self._calculation_with_variable(child, variable, calculation["value"], true_msg) if defined:
return self._calculation_with_variable(
child, variable, calculation["value"], true_msg
)
return {
"message": true_msg,
"path": calculation["value"],
"description": None,
}
def _calculation_with_variable(self, child, variable, calculation, msg): def _calculation_with_variable(self, child, variable, calculation, msg):
if not variable.isdynamic(): if not variable.isdynamic():
@ -265,9 +290,7 @@ class _ToString:
func = self._calculation_dynamic_variable_with_variable func = self._calculation_dynamic_variable_with_variable
return func(child, variable, calculation, msg) return func(child, variable, calculation, msg)
def _calculation_normal_with_variable( def _calculation_normal_with_variable(self, child, variable, obj, msg):
self, child, variable, obj, msg
):
isfollower = not variable.isoptiondescription() and variable.isfollower() isfollower = not variable.isoptiondescription() and variable.isfollower()
if not isfollower and self.is_inaccessible_user_data(variable): if not isfollower and self.is_inaccessible_user_data(variable):
uncalculated = variable.unrestraint.value.default(uncalculated=True) uncalculated = variable.unrestraint.value.default(uncalculated=True)
@ -280,9 +303,7 @@ class _ToString:
else: else:
if not isinstance(uncalculated, str): if not isinstance(uncalculated, str):
uncalculated = dump(uncalculated) uncalculated = dump(uncalculated)
msg = _("{0} (from an undocumented variable)").format( msg = _("{0} (from an undocumented variable)").format(uncalculated)
uncalculated
)
else: else:
msg = _("the value of an undocumented variable") msg = _("the value of an undocumented variable")
try: try:
@ -295,13 +316,14 @@ class _ToString:
"description": description, "description": description,
} }
def _calculation_dynamic_variable_with_variable( def _calculation_dynamic_variable_with_variable(self, child, variable, obj, msg):
self, child, variable, obj, msg
):
values = [] values = []
for path, description, identifiers, identifier_type in self._get_annotation_variable( for (
child, variable, obj.get("identifiers") path,
): description,
identifiers,
identifier_type,
) in self._get_annotation_variable(child, variable, obj.get("identifiers")):
variable = self.true_config.option(path) variable = self.true_config.option(path)
path_obj = { path_obj = {
"path": doc_path(path, self.document_a_type), "path": doc_path(path, self.document_a_type),
@ -310,9 +332,7 @@ class _ToString:
path_obj["identifiers"] = identifiers path_obj["identifiers"] = identifiers
path_obj["identifier_type"] = identifier_type path_obj["identifier_type"] = identifier_type
values.append( values.append(
self._calculation_normal_with_variable( self._calculation_normal_with_variable(child, variable, path_obj, msg)
child, variable, path_obj, msg
)
) )
return values return values
@ -335,13 +355,13 @@ class _ToString:
if ori_identifiers: if ori_identifiers:
if path.count("{{ identifier }}") == len(ori_identifiers): if path.count("{{ identifier }}") == len(ori_identifiers):
identifier_type = "one" identifier_type = "one"
elif "{{ identifier }}" in path[len(get_common_path(child_path, path)):]: elif "{{ identifier }}" in path[len(get_common_path(child_path, path)) :]:
identifier_type = "outside" identifier_type = "outside"
else: else:
identifier_type = "inside" identifier_type = "inside"
else: else:
common_path = get_common_path(child_path, path) common_path = get_common_path(child_path, path)
if common_path and "{{ identifier }}" in path[len(common_path):]: if common_path and "{{ identifier }}" in path[len(common_path) :]:
identifier_type = "outside" identifier_type = "outside"
else: else:
identifier_type = "inside" identifier_type = "inside"
@ -420,7 +440,7 @@ class Collect(_ToString):
path = family.path(uncalculated=True) path = family.path(uncalculated=True)
informations = {} informations = {}
if not self._collect(family, informations, family_type=family_type): if not self._collect(family, informations, family_type=family_type):
return False, [] return False
if family_type == "sequence": if family_type == "sequence":
informations.setdefault("help", []).append( informations.setdefault("help", []).append(
_("This family contains lists of variable blocks") _("This family contains lists of variable blocks")
@ -625,7 +645,11 @@ class Collect(_ToString):
annotation = False annotation = False
if child.information.get(f"{prop}_calculation", False): if child.information.get(f"{prop}_calculation", False):
annotation = self._to_string(child, prop) annotation = self._to_string(child, prop)
if not self.only_disabled and annotation is None and prop in HIDDEN_PROPERTIES: if (
not self.only_disabled
and annotation is None
and prop in HIDDEN_PROPERTIES
):
return False, [] return False, []
if annotation is True and prop in DISABLED_PROPERTIES: if annotation is True and prop in DISABLED_PROPERTIES:
return False, [] return False, []
@ -682,9 +706,7 @@ class Collect(_ToString):
) )
return None return None
var_type = "variable" if family_type is None else "family" var_type = "variable" if family_type is None else "family"
return self._convert_description( return self._convert_description(child.description(uncalculated=True), var_type)
child.description(uncalculated=True), var_type
)
def _convert_description(self, description, type_): def _convert_description(self, description, type_):
return to_phrase(description, type_) return to_phrase(description, type_)
@ -718,9 +740,7 @@ class Collect(_ToString):
variable.value.get() variable.value.get()
except AttributeError: except AttributeError:
variable = None variable = None
if variable and self.is_inaccessible_user_data( if variable and self.is_inaccessible_user_data(variable):
variable
):
try: try:
variable_value = self._get_unmodified_default_value( variable_value = self._get_unmodified_default_value(
variable variable

View file

@ -87,7 +87,9 @@ class RougailOutputDoc(Collect, Examples, Changelog):
def load_formatter(self) -> str: def load_formatter(self) -> str:
output_format = self.rougailconfig["doc.output_format"] output_format = self.rougailconfig["doc.output_format"]
self.formatter = self.outputs[output_format]( self.formatter = self.outputs[output_format](
self.rougailconfig, support_namespace=self.support_namespace, document_a_type=self.document_a_type self.rougailconfig,
support_namespace=self.support_namespace,
document_a_type=self.document_a_type,
) )
def print(self) -> None: def print(self) -> None:
@ -115,8 +117,8 @@ class RougailOutputDoc(Collect, Examples, Changelog):
self.dynamic_paths = {} self.dynamic_paths = {}
if self.config.isoptiondescription(): if self.config.isoptiondescription():
informations = self.collect_families(self.config.unrestraint) informations = self.collect_families(self.config.unrestraint)
# from pprint import pprint # from pprint import pprint
# pprint(informations) # pprint(informations)
else: else:
informations = {} informations = {}
self.collect_variable(self.config, informations) self.collect_variable(self.config, informations)

View file

@ -61,7 +61,7 @@ class Examples: # pylint: disable=no-member,too-few-public-methods
if only_modified: if only_modified:
title = _("Example with mandatory variables not filled in") title = _("Example with mandatory variables not filled in")
else: else:
title = _("Example with all variables modifiable") title = _("Example with all modifiable variables")
datas.append(self.formatter.title(title, self.level)) datas.append(self.formatter.title(title, self.level))
datas.append(self.formatter.yaml(dump(results))) datas.append(self.formatter.yaml(dump(results)))
end = self.formatter.end_family(self.level) end = self.formatter.end_family(self.level)
@ -82,7 +82,13 @@ class Examples: # pylint: disable=no-member,too-few-public-methods
self._set_mandatories(config) self._set_mandatories(config)
return config return config
def _gen_doc_examples(self, config, only_modified: bool): def _gen_doc_examples(
self,
config,
only_modified: bool,
with_secret_manager: bool = True,
with_calculated_value: bool = True,
) -> dict:
if not only_modified: if not only_modified:
self._set_examples(config) self._set_examples(config)
results = CommentedMap() results = CommentedMap()
@ -106,16 +112,27 @@ class Examples: # pylint: disable=no-member,too-few-public-methods
n_results[name] = new_results n_results[name] = new_results
n_results = n_results[name] n_results = n_results[name]
if only_modified: if only_modified:
dump_type = 'modified' if with_calculated_value:
dump_type = "modified"
else:
dump_type = "empty"
else: else:
dump_type = 'all' dump_type = "all"
if root_config.isoptiondescription(): if root_config.isoptiondescription():
self._example_parse_family( self._example_parse_family(
root_config.value.get(), results, dump_type root_config.value.get(),
results,
dump_type,
with_secret_manager=with_secret_manager,
) )
else: else:
self._set_example_value( self._set_example_value(
results, root_config, root_config.value.get(), dump_type results,
root_config,
root_config.value.get(),
dump_type,
with_secret_manager,
False,
) )
if true_results and results: if true_results and results:
n_results.update(results) n_results.update(results)
@ -200,31 +217,58 @@ class Examples: # pylint: disable=no-member,too-few-public-methods
return option.issubmulti() return option.issubmulti()
return option.ismulti() return option.ismulti()
def _example_parse_family(self, config, results, dump_type): def _example_parse_family(
self,
config,
results,
dump_type,
*,
with_secret_manager: bool = True,
with_true_path: bool = False,
) -> None:
for option, values in config.items(): for option, values in config.items():
if option.isoptiondescription(): if option.isoptiondescription():
if option.isleadership(): if option.isleadership():
subresults = self._example_parse_sequence(values, dump_type) subresults = self._example_parse_sequence(
values, dump_type, with_secret_manager, with_true_path
)
if subresults: if subresults:
name = option.name() name = option.name(uncalculated=with_true_path)
results[name] = subresults results[name] = subresults
self._set_description(results, name, option) self._set_description(results, name, option)
else: else:
subresults = CommentedMap() subresults = CommentedMap()
self._example_parse_family(values, subresults, dump_type) self._example_parse_family(
values,
subresults,
dump_type,
with_secret_manager=with_secret_manager,
with_true_path=with_true_path,
)
if subresults: if subresults:
name = option.name() name = option.name(uncalculated=with_true_path)
results[name] = subresults results[name] = subresults
self._set_description(results, name, option) self._set_description(results, name, option)
else: else:
self._set_example_value(results, option, values, dump_type) self._set_example_value(
results,
option,
values,
dump_type,
with_secret_manager,
with_true_path,
)
def _set_example_value(self, results, option, values, dump_type): def _set_example_value(
self, results, option, values, dump_type, with_secret_manager, with_true_path
):
if not self._is_valid_owner(option, dump_type): if not self._is_valid_owner(option, dump_type):
return return
if dump_type == "hidden" and values is None: if not with_secret_manager and option.information.get("secret_manager", False):
return
if dump_type in ["hidden", "empty"] and values is None:
values = self._get_an_example(option) values = self._get_an_example(option)
name = option.name() name = option.name(uncalculated=with_true_path)
results[name] = values results[name] = values
self._set_description(results, name, option) self._set_description(results, name, option)
@ -237,21 +281,50 @@ class Examples: # pylint: disable=no-member,too-few-public-methods
return "hidden" in option.property.get() return "hidden" in option.property.get()
is_default = option.owner.isdefault() is_default = option.owner.isdefault()
return ( return (
(dump_type == 'modified' and not is_default and option.owner.get() != owners.forced) (
or (dump_type == 'default' and is_default) dump_type == "modified"
and not is_default
and option.owner.get() != owners.forced
)
or (
dump_type == "empty"
and "hidden" in option.property.get()
and not option.information.get("default_calculation", None)
and (
option.value.default(uncalculated=True) in [None, []]
or not option.information.get("default_value_makes_sense", True)
)
)
or (dump_type == "default" and is_default)
) )
def _example_parse_sequence(self, values, dump_type): def _example_parse_sequence(
self, values, dump_type, with_secret_manager, with_true_path
):
sequence_iter = iter(values.items()) sequence_iter = iter(values.items())
leader, leader_values = next(sequence_iter) leader, leader_values = next(sequence_iter)
if not self._is_valid_owner(leader, dump_type): if not self._is_valid_owner(leader, dump_type):
return None return None
sequence = [CommentedMap() for idx in range(len(leader_values))] sequence = [CommentedMap() for idx in range(len(leader_values))]
for idx, value in enumerate(leader_values): for idx, value in enumerate(leader_values):
self._set_example_value(sequence[idx], leader, value, dump_type) self._set_example_value(
sequence[idx],
leader,
value,
dump_type,
with_secret_manager,
with_true_path,
)
for option, value in sequence_iter: for option, value in sequence_iter:
idx = option.index() idx = option.index()
self._set_example_value(sequence[idx], option, value, dump_type) self._set_example_value(
sequence[idx],
option,
value,
dump_type,
with_secret_manager,
with_true_path,
)
return sequence return sequence
def _set_description(self, results, name, option): def _set_description(self, results, name, option):

View file

@ -21,6 +21,7 @@ from typing import List
from ..i18n import _ from ..i18n import _
from rougail.error import ExtensionError from rougail.error import ExtensionError
from ..utils import dump, CommonFormatter from ..utils import dump, CommonFormatter
try: try:
from rich.jupyter import JupyterMixin from rich.jupyter import JupyterMixin
from rich.segment import Segment from rich.segment import Segment
@ -34,6 +35,7 @@ except ModuleNotFoundError:
if Console: if Console:
class BlockQuote(JupyterMixin): class BlockQuote(JupyterMixin):
def __init__( def __init__(
self, self,
@ -72,7 +74,9 @@ class Formatter(CommonFormatter):
def __init__(self, rougailconfig, **kwargs) -> None: def __init__(self, rougailconfig, **kwargs) -> None:
if not Console: if not Console:
raise ExtensionError(_("cannot find Python module Rich, please install it!")) raise ExtensionError(
_("cannot find Python module Rich, please install it!")
)
self.custom_theme = Theme(self.titles_color) self.custom_theme = Theme(self.titles_color)
self.max_line = 0 self.max_line = 0
super().__init__(rougailconfig, **kwargs) super().__init__(rougailconfig, **kwargs)
@ -87,9 +91,7 @@ class Formatter(CommonFormatter):
force_terminal = "xterm-256color" force_terminal = "xterm-256color"
else: else:
force_terminal = None force_terminal = None
console = Console( console = Console(theme=self.custom_theme, force_terminal=force_terminal)
theme=self.custom_theme, force_terminal=force_terminal
)
with console.capture() as capture: with console.capture() as capture:
for data in dico: for data in dico:
console.print(data) console.print(data)
@ -100,7 +102,7 @@ class Formatter(CommonFormatter):
self, self,
title: str, title: str,
level: int, level: int,
collapse: bool=True, collapse: bool = True,
) -> str: ) -> str:
"""Display family name as a title""" """Display family name as a title"""
space = " " * (2 * (level - 1)) space = " " * (2 * (level - 1))

View file

@ -1,7 +1,7 @@
""" """
Silique (https://www.silique.fr) Silique (https://www.silique.fr)
Copyright (C) 2024-2026 Copyright (C) 2024-2026
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the under the terms of the GNU Lesser General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your Free Software Foundation, either version 3 of the License, or (at your
@ -45,7 +45,7 @@ class Formatter(CommonFormatter):
self, self,
title: str, title: str,
level: int, level: int,
collapse: bool=True, collapse: bool = True,
) -> str: ) -> str:
"""Display family name as a title""" """Display family name as a title"""
char = "#" char = "#"

View file

@ -1,7 +1,7 @@
""" """
Silique (https://www.silique.fr) Silique (https://www.silique.fr)
Copyright (C) 2025-2026 Copyright (C) 2025-2026
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the under the terms of the GNU Lesser General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your Free Software Foundation, either version 3 of the License, or (at your
@ -29,16 +29,17 @@ class Formatter(GithubFormatter):
level = 51 level = 51
format_in_title = False format_in_title = False
def title(self, def title(
title: str, self,
level: int, title: str,
collapse: bool=True, level: int,
) -> str: collapse: bool = True,
) -> str:
if collapse: if collapse:
return "<details><summary>" + title + "</summary>" return "<details><summary>" + title + "</summary>"
return super().title(title, level, collapse) return super().title(title, level, collapse)
def end_family(self, level, collapse: bool=True): def end_family(self, level, collapse: bool = True):
if collapse: if collapse:
return "</details>" return "</details>"
return None return None
@ -61,8 +62,9 @@ class Formatter(GithubFormatter):
def family_informations_starts_line(self) -> str: def family_informations_starts_line(self) -> str:
return "\n> " return "\n> "
# def list(self, *args, **kwargs):
# return super().list(*args, **kwargs) + "\n" # def list(self, *args, **kwargs):
# return super().list(*args, **kwargs) + "\n"
def family_informations_starts_list_first(self): def family_informations_starts_list_first(self):
return "" return ""

View file

@ -55,10 +55,10 @@ def dump(informations):
def to_phrase(msg, type_="variable"): def to_phrase(msg, type_="variable"):
"""Add maj for the first character and ends with dot""" """Add maj for the first character and ends with dot"""
msg = str(msg).strip()
if not msg: if not msg:
# replace None to empty string # replace None to empty string
return "" return ""
msg = str(msg).strip()
# a phrase must ends with a dot # a phrase must ends with a dot
if type_ == "variable": if type_ == "variable":
msg = add_dot(msg) msg = add_dot(msg)
@ -200,8 +200,12 @@ class CommonTabular:
+ gen_argument_name(alternative_name, True, True, False) + gen_argument_name(alternative_name, True, True, False)
+ f", {commandlines[1]}" + f", {commandlines[1]}"
) )
if "full_path" in self.informations:
full_path = self.informations["full_path"]
else:
full_path = self.informations["path"]
self.commandlines = self.formatter.section( self.commandlines = self.formatter.section(
_("Command line"), commandlines, force_enter=True full_path, _("Command line"), commandlines, force_enter=True
) )
else: else:
self.commandlines = None self.commandlines = None
@ -218,8 +222,12 @@ class CommonTabular:
variable_prefix=self.formatter.prefix, variable_prefix=self.formatter.prefix,
with_anchor=False, with_anchor=False,
) )
if "full_path" in self.informations:
full_path = self.informations["full_path"]
else:
full_path = self.informations["path"]
self.environments = self.formatter.section( self.environments = self.formatter.section(
_("Environment variable"), environments full_path, _("Environment variable"), environments
) )
else: else:
self.environments = None self.environments = None
@ -278,11 +286,11 @@ class CommonFormatter:
if not self.rougailconfig["main_namespace"] and self.with_environment: if not self.rougailconfig["main_namespace"] and self.with_environment:
environment_prefix = self.rougailconfig["doc.tabulars.environment_prefix"] environment_prefix = self.rougailconfig["doc.tabulars.environment_prefix"]
if environment_prefix: if environment_prefix:
self.prefix = ( self.prefix = environment_prefix + "_"
environment_prefix + "_"
)
self.with_family = not self.rougailconfig["doc.tabulars.without_family"] self.with_family = not self.rougailconfig["doc.tabulars.without_family"]
self.other_root_filenames = dict(self.rougailconfig["doc.other_root_filenames"].items()) self.other_root_filenames = dict(
self.rougailconfig["doc.other_root_filenames"].items()
)
tabular_template = self.rougailconfig["doc.tabular_template"] tabular_template = self.rougailconfig["doc.tabular_template"]
self.tabular_datas = Tabulars().get()[tabular_template](self) self.tabular_datas = Tabulars().get()[tabular_template](self)
@ -294,7 +302,7 @@ class CommonFormatter:
self, self,
title: str, title: str,
level: int, level: int,
collapse: bool=True, collapse: bool = True,
) -> str: ) -> str:
"""Display family name as a title""" """Display family name as a title"""
raise NotImplementedError() raise NotImplementedError()
@ -336,8 +344,8 @@ class CommonFormatter:
filename: Optional[str], filename: Optional[str],
) -> str: ) -> str:
"""Set a text link to variable anchor""" """Set a text link to variable anchor"""
# return f'"{description}"' if not description:
# FIXME OPTION POUR METTRE LE PATH return f'"{path}"'
return f'"{description}" ({path})' return f'"{description}" ({path})'
def stripped( def stripped(
@ -377,10 +385,10 @@ class CommonFormatter:
"""Add a link""" """Add a link"""
raise NotImplementedError() raise NotImplementedError()
def yaml(self, _dump: str, yaml_version: str="1.1"): def yaml(self, _dump: str, yaml_version: str = "1.1"):
output = f"---\n{_dump}" output = f"---\n{_dump}"
if yaml_version == "1.2": if yaml_version == "1.2":
output = f'%YAML 1.2\n{output}\n...' output = f"%YAML 1.2\n{output}\n..."
return self._yaml(output) return self._yaml(output)
################## ##################
@ -406,6 +414,7 @@ class CommonFormatter:
def anchor(path, true_path): def anchor(path, true_path):
return path return path
ret_paths = [] ret_paths = []
path = informations["path"] path = informations["path"]
if not path: if not path:
@ -449,7 +458,7 @@ class CommonFormatter:
if "full_path" in informations: if "full_path" in informations:
full_path = informations["full_path"] full_path = informations["full_path"]
else: else:
full_path = path full_path = informations["path"]
if "identifiers" in informations: if "identifiers" in informations:
for idx, identifier in enumerate(informations["identifiers"]): for idx, identifier in enumerate(informations["identifiers"]):
if force_identifiers and identifier != force_identifiers: if force_identifiers and identifier != force_identifiers:
@ -529,7 +538,8 @@ class CommonFormatter:
else: else:
ret = [ ret = [
self.title( self.title(
self.get_description(informations, {}, title=True), level, self.get_description(informations, {}, title=True),
level,
) )
] ]
msg = [] msg = []
@ -541,7 +551,11 @@ class CommonFormatter:
informations, {}, None, with_anchor=False, is_bold=False informations, {}, None, with_anchor=False, is_bold=False
) )
if path: if path:
msg.append(self.section(_("Path"), path, type_="family")) if "full_path" in informations:
full_path = informations["full_path"]
else:
full_path = informations["path"]
msg.append(self.section(full_path, _("Path"), path, type_="family"))
calculated_properties = [] calculated_properties = []
property_str = self.property_to_string(informations, calculated_properties, {}) property_str = self.property_to_string(informations, calculated_properties, {})
if property_str: if property_str:
@ -549,9 +563,16 @@ class CommonFormatter:
if calculated_properties: if calculated_properties:
msg.append(self.join(calculated_properties)) msg.append(self.join(calculated_properties))
if "identifier" in informations: if "identifier" in informations:
if "full_path" in informations:
full_path = informations["full_path"]
else:
full_path = informations["path"]
msg.append( msg.append(
self.section( self.section(
_("Identifiers"), informations["identifier"], type_="family" full_path,
_("Identifiers"),
informations["identifier"],
type_="family",
) )
) )
if msg: if msg:
@ -577,7 +598,7 @@ class CommonFormatter:
def family_informations_ends_line(self) -> str: def family_informations_ends_line(self) -> str:
return "" return ""
def end_family(self, level: int, collapse: bool=True) -> str: def end_family(self, level: int, collapse: bool = True) -> str:
return None return None
def convert_list_to_string( def convert_list_to_string(
@ -611,14 +632,21 @@ class CommonFormatter:
informations: dict, informations: dict,
modified_attributes: dict, modified_attributes: dict,
*, *,
force_identifiers: Optional[list]=None, force_identifiers: Optional[list] = None,
with_to_phrase: bool=True, with_to_phrase: bool = True,
title: bool=False, title: bool = False,
) -> str: ) -> str:
add_new_description = True add_new_description = True
def _get_description(description, identifiers, delete=False, new=[], previous_identifiers=[], new_identifiers=[], its_a_name=False):
# if new_identifiers: def _get_description(
# new_identifiers = new_identifiers[0] description,
identifiers,
delete=False,
new=[],
previous_identifiers=[],
new_identifiers=[],
its_a_name=False,
):
if identifiers and "{{ identifier }}" in description: if identifiers and "{{ identifier }}" in description:
if its_a_name: if its_a_name:
information_type = "name" information_type = "name"
@ -639,14 +667,15 @@ class CommonFormatter:
formatter = self formatter = self
else: else:
formatter = None formatter = None
description = get_path_from_identifiers(description, description = get_path_from_identifiers(
identifiers, description,
previous_identifiers, identifiers,
new_identifiers, previous_identifiers,
identifier_type, new_identifiers,
formatter=formatter, identifier_type,
information_type=information_type, formatter=formatter,
) information_type=information_type,
)
elif with_to_phrase: elif with_to_phrase:
description = self.to_phrase(description) description = self.to_phrase(description)
if description in new: if description in new:
@ -671,15 +700,25 @@ class CommonFormatter:
) )
else: else:
modified_description = None modified_description = None
elif "identifiers" in modified_attributes and "{{ identifier }}" in informations["description"]: elif (
"identifiers" in modified_attributes
and "{{ identifier }}" in informations["description"]
):
# FIXME aussi au dessus ! # FIXME aussi au dessus !
name, previous, new = modified_attributes["identifiers"] name, previous, new = modified_attributes["identifiers"]
previous_identifiers = previous[-1] if previous else [] previous_identifiers = previous[-1] if previous else []
new_identifiers = new[-1] if new else [] new_identifiers = new[-1] if new else []
if new_identifiers: if new_identifiers:
all_identifiers = [identifier for identifier in all_identifiers if identifier != new_identifiers] all_identifiers = [
identifier
for identifier in all_identifiers
if identifier != new_identifiers
]
modified_description = _get_description( modified_description = _get_description(
informations["description"], all_identifiers, previous_identifiers=previous_identifiers, new_identifiers=new_identifiers informations["description"],
all_identifiers,
previous_identifiers=previous_identifiers,
new_identifiers=new_identifiers,
) )
add_new_description = False add_new_description = False
else: else:
@ -692,7 +731,10 @@ class CommonFormatter:
) )
else: else:
description = _get_description( description = _get_description(
informations["name"], all_identifiers, new=new, its_a_name=True, informations["name"],
all_identifiers,
new=new,
its_a_name=True,
) )
else: else:
description = None description = None
@ -727,14 +769,20 @@ class CommonFormatter:
) -> str(): ) -> str():
values = [] values = []
submessage = "" submessage = ""
if "full_path" in informations:
full_path = informations["full_path"]
else:
full_path = informations["path"]
if modified_attributes and attribute in modified_attributes: if modified_attributes and attribute in modified_attributes:
name, previous, new = modified_attributes[attribute] name, previous, new = modified_attributes[attribute]
if isinstance(previous, list): if isinstance(previous, list):
for p in previous: for p in previous:
submessage, m = self.message_to_string(p, submessage) submessage, m = self.message_to_string(full_path, p, submessage)
values.append(self.delete(m)) values.append(self.delete(m))
else: else:
submessage, old_values = self.message_to_string(previous, submessage) submessage, old_values = self.message_to_string(
full_path, previous, submessage
)
values.append(self.delete(old_values)) values.append(self.delete(old_values))
else: else:
new = [] new = []
@ -743,7 +791,15 @@ class CommonFormatter:
name = old["name"] name = old["name"]
if isinstance(old["values"], list): if isinstance(old["values"], list):
for value in old["values"]: for value in old["values"]:
submessage, old_value = self.message_to_string(value, submessage) if "identifiers" in informations and (
not isinstance(value, dict) or "identifiers" not in value
):
identifiers = informations["identifiers"]
else:
identifiers = []
submessage, old_value = self.message_to_string(
full_path, value, submessage, force_identifiers=identifiers
)
if value in new: if value in new:
old_value = self.underline(old_value) old_value = self.underline(old_value)
values.append(old_value) values.append(old_value)
@ -753,17 +809,29 @@ class CommonFormatter:
values = self.join(values) values = self.join(values)
elif values: elif values:
old_values = old["values"] old_values = old["values"]
submessage, old_values = self.message_to_string(old_values, submessage) submessage, old_values = self.message_to_string(
full_path, old_values, submessage
)
if old["values"] in new: if old["values"] in new:
old_values = self.underline(old_values) old_values = self.underline(old_values)
values.append(old_values) values.append(old_values)
values = self.join(values) values = self.join(values)
else: else:
submessage, values = self.message_to_string(old["values"], submessage) old_values = old["values"]
if "identifiers" in informations and (
not isinstance(old_values, dict) or "identifiers" not in old_values
):
identifiers = informations["identifiers"]
else:
identifiers = []
submessage, values = self.message_to_string(
full_path, old_values, submessage, force_identifiers=identifiers
)
if old["values"] in new: if old["values"] in new:
values = self.underline(values) values = self.underline(values)
if values != []: if values != []:
return self.section( return self.section(
full_path,
name, name,
values, values,
submessage=submessage, submessage=submessage,
@ -786,9 +854,15 @@ class CommonFormatter:
default_is_a_list = False default_is_a_list = False
else: else:
default_is_a_list = True default_is_a_list = True
if "full_path" in informations:
full_path = informations["full_path"]
else:
full_path = informations["path"]
for idx, choice in enumerate(choices_values.copy()): for idx, choice in enumerate(choices_values.copy()):
if isinstance(choice, dict): if isinstance(choice, dict):
choices_values[idx] = self.message_to_string(choice, None)[1] choices_values[idx] = self.message_to_string(
full_path, choice, None
)[1]
if "default" in modified_attributes: if "default" in modified_attributes:
name, old_default, new_default = modified_attributes["default"] name, old_default, new_default = modified_attributes["default"]
if not old_default: if not old_default:
@ -814,7 +888,7 @@ class CommonFormatter:
default = [default] default = [default]
for idx, value in enumerate(default.copy()): for idx, value in enumerate(default.copy()):
if isinstance(value, dict): if isinstance(value, dict):
default[idx] = self.message_to_string(value, None)[1] default[idx] = self.message_to_string(full_path, value, None)[1]
default_value_not_in_choices = set(default) - set(choices_values) default_value_not_in_choices = set(default) - set(choices_values)
if default_value_not_in_choices: if default_value_not_in_choices:
default_is_changed = False default_is_changed = False
@ -842,7 +916,7 @@ class CommonFormatter:
name, previous, new = modified_attributes["choices"] name, previous, new = modified_attributes["choices"]
for choice in reversed(previous): for choice in reversed(previous):
if isinstance(choice, dict): if isinstance(choice, dict):
choice = self.message_to_string(choice, None)[1] choice = self.message_to_string(full_path, choice, None)[1]
if with_default and choice in old_default: if with_default and choice in old_default:
choices_values.insert( choices_values.insert(
0, self.delete(dump(choice) + "" + _("(default)")) 0, self.delete(dump(choice) + "" + _("(default)"))
@ -877,7 +951,9 @@ class CommonFormatter:
# if old value and new value is a list, display a list # if old value and new value is a list, display a list
if not default_is_a_list and len(choices_values) == 1: if not default_is_a_list and len(choices_values) == 1:
choices_values = choices_values[0] choices_values = choices_values[0]
return default_is_already_set, self.section(choices["name"], choices_values) return default_is_already_set, self.section(
full_path, choices["name"], choices_values
)
return default_is_already_set, None return default_is_already_set, None
# OTHERs # OTHERs
@ -905,13 +981,20 @@ class CommonFormatter:
) )
) )
if "multiple" in modified_attributes: if "multiple" in modified_attributes:
if modified_attributes["multiple"][1] and modified_attributes["multiple"][1][0]: if (
modified_attributes["multiple"][1]
and modified_attributes["multiple"][1][0]
):
properties.append( properties.append(
self.prop("multiple", italic=False, delete=True, underline=False) self.prop(
"multiple", italic=False, delete=True, underline=False
)
) )
else: else:
properties.append( properties.append(
self.prop("multiple", italic=False, delete=False, underline=True) self.prop(
"multiple", italic=False, delete=False, underline=True
)
) )
if "properties" not in contents and "properties" in modified_attributes: if "properties" not in contents and "properties" in modified_attributes:
for prop in modified_attributes["properties"]: for prop in modified_attributes["properties"]:
@ -1044,13 +1127,19 @@ class CommonFormatter:
) )
) )
if local_calculated_properties: if local_calculated_properties:
if "full_path" in informations:
full_path = informations["full_path"]
else:
full_path = informations["path"]
for ( for (
calculated_property_name, calculated_property_name,
calculated_property, calculated_property,
) in local_calculated_properties.items(): ) in local_calculated_properties.items():
data = [] data = []
for calc in calculated_property: for calc in calculated_property:
annotation = self.message_to_string(calc["annotation"], None)[1] annotation = self.message_to_string(
full_path, calc["annotation"], None
)[1]
if calc.get("underline", False): if calc.get("underline", False):
annotation = self.underline(annotation) annotation = self.underline(annotation)
if calc.get("delete", False): if calc.get("delete", False):
@ -1062,7 +1151,9 @@ class CommonFormatter:
calculated_property = data[0] calculated_property = data[0]
calculated_properties.append( calculated_properties.append(
self.section( self.section(
calculated_property_name.capitalize(), calculated_property full_path,
calculated_property_name.capitalize(),
calculated_property,
) )
) )
if not properties: if not properties:
@ -1090,16 +1181,14 @@ class CommonFormatter:
headers = self.tabular_header(self.tabular_datas.headers()) headers = self.tabular_header(self.tabular_datas.headers())
else: else:
headers = () headers = ()
msg = ( msg = tabulate(
tabulate( self.tabular_datas.get(),
self.tabular_datas.get(), headers=headers,
headers=headers, tablefmt=self._tabular_name,
tablefmt=self._tabular_name,
)
) )
return msg return msg
def message_to_string(self, msg, ret, *, identifiers=[]): def message_to_string(self, full_path, msg, ret, *, force_identifiers=[]):
if isinstance(msg, dict): if isinstance(msg, dict):
if "submessage" in msg: if "submessage" in msg:
ret += msg["submessage"] ret += msg["submessage"]
@ -1117,18 +1206,36 @@ class CommonFormatter:
filename = self.other_root_filenames["."] filename = self.other_root_filenames["."]
if "identifiers" in msg["path"]: if "identifiers" in msg["path"]:
msg["identifiers"] = msg["path"]["identifiers"] msg["identifiers"] = msg["path"]["identifiers"]
calculated_paths = calc_path(msg["path"], formatter=self, identifiers=identifiers) calculated_paths = calc_path(
msg["path"], formatter=self, identifiers=force_identifiers
)
if self.support_namespace and self.document_a_type:
namespace = full_path.split(".", 1)[0]
else:
namespace = None
if isinstance(calculated_paths, list): if isinstance(calculated_paths, list):
msgs = [msg["message"].format(self.link_variable( msgs = [
doc_path(calculated_path, self.document_a_type), msg["message"].format(
msg["path"]["path"], self.link_variable(
self.get_description(msg, {}, force_identifiers=[msg["path"]["identifiers"][idx]], with_to_phrase=False), doc_path(
filename=filename, calculated_path, self.document_a_type, namespace
)) for idx, calculated_path in enumerate(calculated_paths)] ),
msg["path"]["path"],
self.get_description(
msg,
{},
force_identifiers=[msg["path"]["identifiers"][idx]],
with_to_phrase=False,
),
filename=filename,
)
)
for idx, calculated_path in enumerate(calculated_paths)
]
msg = self.list(msgs) msg = self.list(msgs)
else: else:
path = self.link_variable( path = self.link_variable(
doc_path(calculated_paths, self.document_a_type), doc_path(calculated_paths, self.document_a_type, namespace),
msg["path"]["path"], msg["path"]["path"],
self.get_description(msg, {}, with_to_phrase=False), self.get_description(msg, {}, with_to_phrase=False),
filename=filename, filename=filename,
@ -1149,6 +1256,8 @@ class CommonFormatter:
if "." in self.other_root_filenames: if "." in self.other_root_filenames:
filename = self.other_root_filenames["."] filename = self.other_root_filenames["."]
identifiers = variable.get("identifiers") identifiers = variable.get("identifiers")
if identifiers is None and force_identifiers:
identifiers = force_identifiers
if self.format_in_title: if self.format_in_title:
formatter = self formatter = self
else: else:
@ -1176,6 +1285,7 @@ class CommonFormatter:
def section( def section(
self, self,
full_path: str,
name: str, name: str,
msg: str, msg: str,
submessage: str = "", submessage: str = "",
@ -1185,10 +1295,10 @@ class CommonFormatter:
force_enter=False, force_enter=False,
) -> str: ) -> str:
"""Return something like Name: msg""" """Return something like Name: msg"""
submessage, msg = self.message_to_string(msg, submessage) submessage, msg = self.message_to_string(full_path, msg, submessage)
if isinstance(msg, list): if isinstance(msg, list):
if len(msg) == 1: if len(msg) == 1:
submessage, elt = self.message_to_string(msg[0], submessage) submessage, elt = self.message_to_string(full_path, msg[0], submessage)
if isinstance(elt, list): if isinstance(elt, list):
submessage += self.list(elt, type_=type_, with_enter=section_name) submessage += self.list(elt, type_=type_, with_enter=section_name)
elif force_enter: elif force_enter:
@ -1198,7 +1308,7 @@ class CommonFormatter:
else: else:
lst = [] lst = []
for p in msg: for p in msg:
submessage, elt = self.message_to_string(p, submessage) submessage, elt = self.message_to_string(full_path, p, submessage)
lst.append(elt) lst.append(elt)
submessage += self.list(lst, type_=type_, with_enter=section_name) submessage += self.list(lst, type_=type_, with_enter=section_name)
msg = "" msg = ""
@ -1226,7 +1336,17 @@ def calc_path(path, *, formatter=None, identifiers: List[str] = None) -> str:
if isinstance(path, dict): if isinstance(path, dict):
path_ = path["path"] path_ = path["path"]
if "identifiers" in path: if "identifiers" in path:
path_ = get_path_from_identifiers(path["path"], path["identifiers"], [], [], path["identifier_type"], formatter) path_ = get_path_from_identifiers(
path["path"],
path["identifiers"],
[],
[],
path["identifier_type"],
formatter,
)
elif identifiers:
for identifier in identifiers[0]:
path_ = _path_with_identifier(path_, identifier)
elif identifiers: elif identifiers:
path_ = path path_ = path
for identifier in identifiers: for identifier in identifiers:
@ -1237,33 +1357,36 @@ def calc_path(path, *, formatter=None, identifiers: List[str] = None) -> str:
return path_ return path_
def doc_path(path, document_a_type): def doc_path(path, document_a_type, namespace: Optional[str] = None) -> str:
if document_a_type: if document_a_type:
if "." not in path: if "." not in path:
return None return None
return path.split(".", 1)[-1] if not namespace or path.startswith(namespace + "."):
return path.split(".", 1)[-1]
return path return path
def get_path_from_identifiers(text: str, def get_path_from_identifiers(
all_identifiers: list, text: str,
previous_identifiers: list, all_identifiers: list,
new_identifiers: list, previous_identifiers: list,
identifier_type: str, new_identifiers: list,
formatter: Optional[object]=None, identifier_type: str,
information_type="path", formatter: Optional[object] = None,
) -> str: information_type="path",
) -> str:
if not isinstance(all_identifiers, list): if not isinstance(all_identifiers, list):
raise Exception('hu1?') raise Exception("hu1?")
if all_identifiers: if all_identifiers:
for i in all_identifiers: for i in all_identifiers:
if not isinstance(i, list): if not isinstance(i, list):
raise Exception('hu2?') raise Exception("hu2?")
for j in i: for j in i:
if isinstance(j, list): if isinstance(j, list):
raise Exception('hu3?') raise Exception("hu3?")
if not isinstance(new_identifiers, list): if not isinstance(new_identifiers, list):
raise Exception('hu?') raise Exception("hu?")
def _text_with_identifier(information, identifier, delete=False, underline=False): def _text_with_identifier(information, identifier, delete=False, underline=False):
if identifier is None: if identifier is None:
identifier = "{{ __identifier__ }}" identifier = "{{ __identifier__ }}"
@ -1278,6 +1401,7 @@ def get_path_from_identifiers(text: str,
identifier = formatter.underline(identifier) identifier = formatter.underline(identifier)
identifier = formatter.italic(identifier) identifier = formatter.italic(identifier)
return information.replace("{{ identifier }}", identifier, 1) return information.replace("{{ identifier }}", identifier, 1)
if identifier_type == "outside": if identifier_type == "outside":
separator = "and" separator = "and"
else: else:
@ -1318,9 +1442,7 @@ def get_path_from_identifiers(text: str,
separator=separator, separator=separator,
sort=False, sort=False,
) )
return text.replace( return text.replace("{{ identifier }}", identifiers_text)
"{{ identifier }}", identifiers_text if identifier_type == "outside":
)
if identifier_type == 'outside':
return paths return paths
return display_list(paths, separator=separator, sort=False) return display_list(paths, separator=separator, sort=False)

View file

@ -17,12 +17,12 @@
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[choice]` `mandatory` | My var6. + `https://rougail.readthedocs.io/en/latest/variable.html#variables-types[choice]` `mandatory` | My var6. +
**Choices**: **Choices**:
* *
| **var7** + | **var7** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[choice]` `mandatory` | My var7. + `https://rougail.readthedocs.io/en/latest/variable.html#variables-types[choice]` `mandatory` | My var7. +
**Choices**: **Choices**:
* *
| **var8** + | **var8** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[choice]` `mandatory` | My var8. + `https://rougail.readthedocs.io/en/latest/variable.html#variables-types[choice]` `mandatory` | My var8. +
**Choices**: values of "a.unknown.variable". **Choices**: values of "a.unknown.variable".

View file

@ -12,5 +12,12 @@ With useful information.
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `basic` `mandatory` | The second variable. + `https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `basic` `mandatory` | The second variable. +
Multi line Multi line
Help Help
With useful information.
| **var3** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `basic` `mandatory` | The third variable with spaces. +
Multi line with space.
Help.
With useful information. With useful information.
|==== |====

View file

@ -1,4 +1,5 @@
| Variable | Description | | Variable | Description |
|--------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------| |--------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
| **<a id="var1" name="var1">var1</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | The first variable.<br/>Multi line<br/><br/>Help<br/><br/>With useful information. | | **<a id="var1" name="var1">var1</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | The first variable.<br/>Multi line<br/><br/>Help<br/><br/>With useful information. |
| **<a id="var2" name="var2">var2</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | The second variable.<br/>Multi line<br/>Help<br/>With useful information. | | **<a id="var2" name="var2">var2</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | The second variable.<br/>Multi line<br/>Help<br/>With useful information. |
| **<a id="var3" name="var3">var3</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | The third variable with spaces.<br/>Multi line with space.<br/> <br/>Help.<br/><br/>With useful information. |

View file

@ -10,6 +10,11 @@ Help
With useful information. </td></tr> With useful information. </td></tr>
<tr><td><b>var2</b><br/><mark><a href='https://rougail.readthedocs.io/en/latest/variable.html#variables-types'>string</a></mark> <mark>basic</mark> <mark>mandatory</mark></td><td>The second variable.<br/>Multi line <tr><td><b>var2</b><br/><mark><a href='https://rougail.readthedocs.io/en/latest/variable.html#variables-types'>string</a></mark> <mark>basic</mark> <mark>mandatory</mark></td><td>The second variable.<br/>Multi line
Help Help
With useful information. </td></tr>
<tr><td><b>var3</b><br/><mark><a href='https://rougail.readthedocs.io/en/latest/variable.html#variables-types'>string</a></mark> <mark>basic</mark> <mark>mandatory</mark></td><td>The third variable with spaces.<br/>Multi line with space.
Help.
With useful information. </td></tr> With useful information. </td></tr>
</tbody> </tbody>
</table> </table>

View file

@ -36,5 +36,24 @@
"mode": "basic", "mode": "basic",
"type": "variable", "type": "variable",
"variable_type": "string" "variable_type": "string"
},
"var3": {
"path": "var3",
"name": "var3",
"description": "The third variable with spaces.",
"help": [
"Multi line with space.\n \nHelp.\n\nWith useful information."
],
"properties": [
{
"type": "property",
"name": "mandatory",
"ori_name": "mandatory",
"access_control": false
}
],
"mode": "basic",
"type": "variable",
"variable_type": "string"
} }
} }

View file

@ -1,4 +1,5 @@
| Variable | Description | | Variable | Description |
|--------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------| |--------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
| **<a id="var1" name="var1">var1</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | The first variable.<br/>Multi line<br/><br/>Help<br/><br/>With useful information. | | **<a id="var1" name="var1">var1</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | The first variable.<br/>Multi line<br/><br/>Help<br/><br/>With useful information. |
| **<a id="var2" name="var2">var2</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | The second variable.<br/>Multi line<br/>Help<br/>With useful information. | | **<a id="var2" name="var2">var2</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | The second variable.<br/>Multi line<br/>Help<br/>With useful information. |
| **<a id="var3" name="var3">var3</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | The third variable with spaces.<br/>Multi line with space.<br/> <br/>Help.<br/><br/>With useful information. |

View file

@ -12,5 +12,12 @@
 string   basic   mandatory  │ Multi line │  string   basic   mandatory  │ Multi line │
│ │ Help │ │ │ Help │
│ │ With useful information. │ │ │ With useful information. │
├───────────────────────────────────────┼──────────────────────────────────────┤
var3 │ The third variable with spaces. │
 string   basic   mandatory  │ Multi line with space. │
│ │ │
│ │ Help. │
│ │ │
│ │ With useful information. │
└───────────────────────────────────────┴──────────────────────────────────────┘ └───────────────────────────────────────┴──────────────────────────────────────┘

View file

@ -38,4 +38,25 @@ With useful information. +
| Variable | Variable
| **family2.var** + | **family2.var** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `basic` `mandatory` `https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `basic` `mandatory`
|====
== The third family with space
====
**🛈 Informations**
Multi line. +
+
Help. +
With useful information. +
**Path**: family3 +
`basic`
====
[cols="1a,1a"]
|====
| Variable | Description
| **family3.var** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `basic` `mandatory` | A variable.
|==== |====

View file

@ -38,4 +38,25 @@
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **<a id="family2.var" name="family2.var">family2.var</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | | **<a id="family2.var" name="family2.var">family2.var</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` |
</details>
<details><summary>The third family with space</summary>
> [!note] 🛈 Informations
> Multi line.
>
>
>
> Help.
>
> With useful information.
>
> **Path**: family3
>
> `basic`
| Variable | Description |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
| **<a id="family3.var" name="family3.var">family3.var</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | A variable. |
</details> </details>

View file

@ -22,4 +22,17 @@ Multi line.<br/>Help.<br/>With useful information.<br/><b>Path</b>: family2<br/>
<tbody> <tbody>
<tr><td><b>family2.var</b><br/><mark><a href='https://rougail.readthedocs.io/en/latest/variable.html#variables-types'>string</a></mark> <mark>basic</mark> <mark>mandatory</mark></td></tr> <tr><td><b>family2.var</b><br/><mark><a href='https://rougail.readthedocs.io/en/latest/variable.html#variables-types'>string</a></mark> <mark>basic</mark> <mark>mandatory</mark></td></tr>
</tbody> </tbody>
</table>
<h1>The third family with space</h1>
Multi line.<br/><br/>Help.<br/>With useful information.<br/><b>Path</b>: family3<br/><mark>basic</mark>
<table>
<thead>
<tr><th>Variable </th><th>Description </th></tr>
</thead>
<tbody>
<tr><td><b>family3.var</b><br/><mark><a href='https://rougail.readthedocs.io/en/latest/variable.html#variables-types'>string</a></mark> <mark>basic</mark> <mark>mandatory</mark></td><td>A variable. </td></tr>
</tbody>
</table> </table>

View file

@ -58,5 +58,36 @@
"variable_type": "string" "variable_type": "string"
} }
} }
},
"family3": {
"type": "family",
"informations": {
"path": "family3",
"name": "family3",
"description": "The third family with space",
"help": [
"Multi line\n \nHelp\nWith useful information."
],
"properties": [],
"mode": "basic"
},
"children": {
"var": {
"path": "family3.var",
"name": "var",
"description": "A variable.",
"properties": [
{
"type": "property",
"name": "mandatory",
"ori_name": "mandatory",
"access_control": false
}
],
"mode": "basic",
"type": "variable",
"variable_type": "string"
}
}
} }
} }

View file

@ -26,4 +26,19 @@
| Variable | | Variable |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **<a id="family2.var" name="family2.var">family2.var</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | | **<a id="family2.var" name="family2.var">family2.var</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` |
# The third family with space
> [!NOTE]
>
> Multi line.\
> \
> Help.\
> With useful information.\
> **Path**: family3\
> `basic`
| Variable | Description |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
| **<a id="family3.var" name="family3.var">family3.var</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | A variable. |

View file

@ -34,3 +34,21 @@
 string   basic   mandatory  │  string   basic   mandatory  │
└──────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────┘
The third family with space
▌ 🛈 Informations
▌ 
▌ Multi line.
▌ 
▌ Help.
▌ With useful information.
▌ Path: family3
▌  basic 
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
 Variable  ┃ Description  ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
family3.var │ A variable. │
 string   basic   mandatory  │ │
└───────────────────────────────────────┴──────────────────────────────────────┘

View file

@ -0,0 +1,33 @@
[cols="1a,1a"]
|====
| Variable | Description
| **var** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `multiple` `standard` `mandatory` `unique` | A suffix variable. +
**Default**:
* val1
* val2
|====
== A dynamic family
====
**🛈 Informations**
This family builds families dynamically. +
**Path**:
* dyn__val1__
* dyn__val2__ +
`basic` +
**Identifiers**: the value of the variable "A suffix variable" (var).
====
[cols="1a,1a"]
|====
| Variable | Description
| **dyn__val1__.variable** +
**dyn__val2__.variable** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `basic` `mandatory` | A dynamic variable.
|====

View file

@ -0,0 +1,22 @@
| Variable | Description |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------|
| **<a id="var" name="var">var</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` `standard` `mandatory` `unique` | A suffix variable.<br/>**Default**: <br/>&nbsp;val1<br/>&nbsp;val2 |
<details><summary>A dynamic family</summary>
> [!note] 🛈 Informations
> This family builds families dynamically.
>
> **Path**:
> - dyn*val1*
> - dyn*val2*
>
> `basic`
>
> **Identifiers**: the value of the variable "[A suffix variable](#var)".
| Variable | Description |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------|
| **<a id="dyn:::identifier:::.variable" name="dyn:::identifier:::.variable">dyn*val1*.variable</a>**<br/>**dyn*val2*.variable**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | A dynamic variable. |
</details>

View file

@ -0,0 +1,23 @@
<table>
<thead>
<tr><th>Variable </th><th>Description </th></tr>
</thead>
<tbody>
<tr><td><b>var</b><br/><mark><a href='https://rougail.readthedocs.io/en/latest/variable.html#variables-types'>string</a></mark> <mark>multiple</mark> <mark>standard</mark> <mark>mandatory</mark> <mark>unique</mark></td><td>A suffix variable.<br/><b>Default</b>: <ul><li>val1</li>
<li>val2</li></ul> </td></tr>
</tbody>
</table>
<h1>A dynamic family</h1>
This family builds families dynamically.<br/><b>Path</b>: <ul><li>dyn<i>val1</i></li>
<li>dyn<i>val2</i></li></ul><br/><mark>basic</mark><br/><b>Identifiers</b>: the value of the variable "A suffix variable" (var).
<table>
<thead>
<tr><th>Variable </th><th>Description </th></tr>
</thead>
<tbody>
<tr><td><b>dyn<i>val1</i>.variable</b><br/><b>dyn<i>val2</i>.variable</b><br/><mark><a href='https://rougail.readthedocs.io/en/latest/variable.html#variables-types'>string</a></mark> <mark>basic</mark> <mark>mandatory</mark></td><td>A dynamic variable.</td></tr>
</tbody>
</table>

View file

@ -0,0 +1,91 @@
{
"var": {
"path": "var",
"name": "var",
"description": "A suffix variable.",
"properties": [
{
"type": "property",
"name": "mandatory",
"ori_name": "mandatory",
"access_control": false
},
{
"type": "property",
"name": "unique",
"ori_name": "unique",
"access_control": false
}
],
"mode": "standard",
"type": "variable",
"default": {
"name": "Default",
"values": [
"val1",
"val2"
]
},
"variable_type": "string",
"multiple": true
},
"dyn{{ identifier }}": {
"type": "dynamic",
"informations": {
"path": "dyn{{ identifier }}",
"name": "dyn{{ identifier }}",
"description": "A dynamic family",
"properties": [],
"mode": "basic",
"identifiers": [
[
"val1"
],
[
"val2"
]
],
"identifier_type": "many",
"help": [
"This family builds families dynamically"
],
"identifier": [
{
"message": "the value of the variable {0}.",
"path": {
"path": "var",
"type": "variable"
},
"description": "A suffix variable"
}
]
},
"children": {
"variable": {
"path": "dyn{{ identifier }}.variable",
"name": "variable",
"description": "A dynamic variable.",
"properties": [
{
"type": "property",
"name": "mandatory",
"ori_name": "mandatory",
"access_control": false
}
],
"mode": "basic",
"identifiers": [
[
"val1"
],
[
"val2"
]
],
"identifier_type": "many",
"type": "variable",
"variable_type": "string"
}
}
}
}

View file

@ -0,0 +1,19 @@
| Variable | Description |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------|
| **<a id="var" name="var">var</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` `standard` `mandatory` `unique` | A suffix variable.<br/>**Default**: <br/>&nbsp;val1<br/>&nbsp;val2 |
# A dynamic family
> [!NOTE]
>
> This family builds families dynamically.\
> **Path**: \
> - dyn*val1*\
> - dyn*val2*\
> `basic`\
> **Identifiers**: the value of the variable "[A suffix variable](#var)".
| Variable | Description |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------|
| **<a id="dyn:::identifier:::.variable" name="dyn:::identifier:::.variable">dyn*val1*.variable</a>**<br/>**dyn*val2*.variable**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | A dynamic variable. |

View file

@ -0,0 +1,28 @@
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
 Variable  ┃ Description  ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
var │ A suffix variable. │
 string   multiple   standard    │ Default: │
mandatory   unique  │ • val1 │
│ │ • val2 │
└───────────────────────────────────────┴──────────────────────────────────────┘
A dynamic family
▌ 🛈 Informations
▌ 
▌ This family builds families dynamically.
▌ Path:
▌  • dynval1
▌  • dynval2
▌  basic 
▌ Identifiers: the value of the variable "A suffix variable" (var).
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
 Variable  ┃ Description  ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
dynval1.variable │ A dynamic variable. │
dynval2.variable │ │
 string   basic   mandatory  │ │
└───────────────────────────────────────┴──────────────────────────────────────┘

View file

@ -0,0 +1 @@
[]

View file

@ -7,7 +7,7 @@ version: example
---- ----
== Example with all variables modifiable == Example with all modifiable variables
[,yaml] [,yaml]
---- ----

View file

@ -7,7 +7,7 @@ version: example
</details> </details>
<details><summary>Example with all variables modifiable</summary> <details><summary>Example with all modifiable variables</summary>
```yaml ```yaml
--- ---

View file

@ -3,7 +3,7 @@
<pre>--- <pre>---
version: example</pre> version: example</pre>
<h1>Example with all variables modifiable</h1> <h1>Example with all modifiable variables</h1>
<pre>--- <pre>---
version: example</pre> version: example</pre>

View file

@ -5,7 +5,7 @@
version: example version: example
``` ```
# Example with all variables modifiable # Example with all modifiable variables
```yaml ```yaml
--- ---

View file

@ -3,7 +3,7 @@
---  --- 
version: example  version: example 
Example with all variables modifiable Example with all modifiable variables
---  --- 
version: example  version: example 

View file

@ -7,7 +7,7 @@ empty: example
---- ----
== Example with all variables modifiable == Example with all modifiable variables
[,yaml] [,yaml]
---- ----

View file

@ -7,7 +7,7 @@ empty: example
</details> </details>
<details><summary>Example with all variables modifiable</summary> <details><summary>Example with all modifiable variables</summary>
```yaml ```yaml
--- ---

View file

@ -3,7 +3,7 @@
<pre>--- <pre>---
empty: example</pre> empty: example</pre>
<h1>Example with all variables modifiable</h1> <h1>Example with all modifiable variables</h1>
<pre>--- <pre>---
empty: example</pre> empty: example</pre>

View file

@ -5,7 +5,7 @@
empty: example empty: example
``` ```
# Example with all variables modifiable # Example with all modifiable variables
```yaml ```yaml
--- ---

View file

@ -3,7 +3,7 @@
---  --- 
empty: example  empty: example 
Example with all variables modifiable Example with all modifiable variables
---  --- 
empty: example  empty: example 

View file

@ -1,4 +1,4 @@
== Example with all variables modifiable == Example with all modifiable variables
[,yaml] [,yaml]
---- ----

View file

@ -1,4 +1,4 @@
<details><summary>Example with all variables modifiable</summary> <details><summary>Example with all modifiable variables</summary>
```yaml ```yaml
--- ---

View file

@ -1,4 +1,4 @@
<h1>Example with all variables modifiable</h1> <h1>Example with all modifiable variables</h1>
<pre>--- <pre>---
var1: no var1: no

View file

@ -1,4 +1,4 @@
# Example with all variables modifiable # Example with all modifiable variables
```yaml ```yaml
--- ---

View file

@ -1,4 +1,4 @@
Example with all variables modifiable Example with all modifiable variables
---  --- 
var1: no  var1: no 

View file

@ -1,4 +1,4 @@
== Example with all variables modifiable == Example with all modifiable variables
[,yaml] [,yaml]
---- ----

View file

@ -1,4 +1,4 @@
<details><summary>Example with all variables modifiable</summary> <details><summary>Example with all modifiable variables</summary>
```yaml ```yaml
--- ---

View file

@ -1,4 +1,4 @@
<h1>Example with all variables modifiable</h1> <h1>Example with all modifiable variables</h1>
<pre>--- <pre>---
var1: var1:

View file

@ -1,4 +1,4 @@
# Example with all variables modifiable # Example with all modifiable variables
```yaml ```yaml
--- ---

View file

@ -1,4 +1,4 @@
Example with all variables modifiable Example with all modifiable variables
---  --- 
var1:  var1: 

View file

@ -1,4 +1,4 @@
== Example with all variables modifiable == Example with all modifiable variables
[,yaml] [,yaml]
---- ----

View file

@ -1,4 +1,4 @@
<details><summary>Example with all variables modifiable</summary> <details><summary>Example with all modifiable variables</summary>
```yaml ```yaml
--- ---

View file

@ -1,4 +1,4 @@
<h1>Example with all variables modifiable</h1> <h1>Example with all modifiable variables</h1>
<pre>--- <pre>---
var2: a_value</pre> var2: a_value</pre>

View file

@ -1,4 +1,4 @@
# Example with all variables modifiable # Example with all modifiable variables
```yaml ```yaml
--- ---

View file

@ -1,4 +1,4 @@
Example with all variables modifiable Example with all modifiable variables
---  --- 
var2: a_value  var2: a_value 

View file

@ -8,7 +8,7 @@ var1:
---- ----
== Example with all variables modifiable == Example with all modifiable variables
[,yaml] [,yaml]
---- ----

View file

@ -8,7 +8,7 @@ var1:
</details> </details>
<details><summary>Example with all variables modifiable</summary> <details><summary>Example with all modifiable variables</summary>
```yaml ```yaml
--- ---

View file

@ -4,7 +4,7 @@
var1: var1:
- example.net</pre> - example.net</pre>
<h1>Example with all variables modifiable</h1> <h1>Example with all modifiable variables</h1>
<pre>--- <pre>---
var1: var1:

View file

@ -6,7 +6,7 @@ var1:
- example.net - example.net
``` ```
# Example with all variables modifiable # Example with all modifiable variables
```yaml ```yaml
--- ---

View file

@ -4,7 +4,7 @@
var1:  var1: 
 - example.net   - example.net 
Example with all variables modifiable Example with all modifiable variables
---  --- 
var1:  var1: 

View file

@ -7,7 +7,7 @@ var1: example
---- ----
== Example with all variables modifiable == Example with all modifiable variables
[,yaml] [,yaml]
---- ----

View file

@ -7,7 +7,7 @@ var1: example
</details> </details>
<details><summary>Example with all variables modifiable</summary> <details><summary>Example with all modifiable variables</summary>
```yaml ```yaml
--- ---

View file

@ -3,7 +3,7 @@
<pre>--- <pre>---
var1: example</pre> var1: example</pre>
<h1>Example with all variables modifiable</h1> <h1>Example with all modifiable variables</h1>
<pre>--- <pre>---
var1: example var1: example

View file

@ -5,7 +5,7 @@
var1: example var1: example
``` ```
# Example with all variables modifiable # Example with all modifiable variables
```yaml ```yaml
--- ---

View file

@ -3,7 +3,7 @@
---  --- 
var1: example  var1: example 
Example with all variables modifiable Example with all modifiable variables
---  --- 
var1: example  var1: example 

View file

@ -8,7 +8,7 @@ var3: example
---- ----
== Example with all variables modifiable == Example with all modifiable variables
[,yaml] [,yaml]
---- ----

View file

@ -8,7 +8,7 @@ var3: example
</details> </details>
<details><summary>Example with all variables modifiable</summary> <details><summary>Example with all modifiable variables</summary>
```yaml ```yaml
--- ---

View file

@ -4,7 +4,7 @@
var1: example var1: example
var3: example</pre> var3: example</pre>
<h1>Example with all variables modifiable</h1> <h1>Example with all modifiable variables</h1>
<pre>--- <pre>---
var1: example var1: example

View file

@ -6,7 +6,7 @@ var1: example
var3: example var3: example
``` ```
# Example with all variables modifiable # Example with all modifiable variables
```yaml ```yaml
--- ---

View file

@ -4,7 +4,7 @@
var1: example  var1: example 
var3: example  var3: example 
Example with all variables modifiable Example with all modifiable variables
---  --- 
var1: example  var1: example 

View file

@ -8,7 +8,7 @@ var1:
---- ----
== Example with all variables modifiable == Example with all modifiable variables
[,yaml] [,yaml]
---- ----

View file

@ -8,7 +8,7 @@ var1:
</details> </details>
<details><summary>Example with all variables modifiable</summary> <details><summary>Example with all modifiable variables</summary>
```yaml ```yaml
--- ---

View file

@ -4,7 +4,7 @@
var1: var1:
- example.net</pre> - example.net</pre>
<h1>Example with all variables modifiable</h1> <h1>Example with all modifiable variables</h1>
<pre>--- <pre>---
var1: var1:

View file

@ -6,7 +6,7 @@ var1:
- example.net - example.net
``` ```
# Example with all variables modifiable # Example with all modifiable variables
```yaml ```yaml
--- ---

View file

@ -4,7 +4,7 @@
var1:  var1: 
 - example.net   - example.net 
Example with all variables modifiable Example with all modifiable variables
---  --- 
var1:  var1: 

View file

@ -8,7 +8,7 @@ var2: example
---- ----
== Example with all variables modifiable == Example with all modifiable variables
[,yaml] [,yaml]
---- ----

View file

@ -8,7 +8,7 @@ var2: example
</details> </details>
<details><summary>Example with all variables modifiable</summary> <details><summary>Example with all modifiable variables</summary>
```yaml ```yaml
--- ---

View file

@ -4,7 +4,7 @@
var1: example var1: example
var2: example</pre> var2: example</pre>
<h1>Example with all variables modifiable</h1> <h1>Example with all modifiable variables</h1>
<pre>--- <pre>---
var1: example var1: example

View file

@ -6,7 +6,7 @@ var1: example
var2: example var2: example
``` ```
# Example with all variables modifiable # Example with all modifiable variables
```yaml ```yaml
--- ---

View file

@ -4,7 +4,7 @@
var1: example  var1: example 
var2: example  var2: example 
Example with all variables modifiable Example with all modifiable variables
---  --- 
var1: example  var1: example 

View file

@ -1,4 +1,4 @@
== Example with all variables modifiable == Example with all modifiable variables
[,yaml] [,yaml]
---- ----

View file

@ -1,4 +1,4 @@
<details><summary>Example with all variables modifiable</summary> <details><summary>Example with all modifiable variables</summary>
```yaml ```yaml
--- ---

View file

@ -1,4 +1,4 @@
<h1>Example with all variables modifiable</h1> <h1>Example with all modifiable variables</h1>
<pre>--- <pre>---
without_type: non</pre> without_type: non</pre>

View file

@ -1,4 +1,4 @@
# Example with all variables modifiable # Example with all modifiable variables
```yaml ```yaml
--- ---

View file

@ -1,4 +1,4 @@
Example with all variables modifiable Example with all modifiable variables
---  --- 
without_type: non  without_type: non 

View file

@ -1,4 +1,4 @@
== Example with all variables modifiable == Example with all modifiable variables
[,yaml] [,yaml]
---- ----

View file

@ -1,4 +1,4 @@
<details><summary>Example with all variables modifiable</summary> <details><summary>Example with all modifiable variables</summary>
```yaml ```yaml
--- ---

View file

@ -1,4 +1,4 @@
<h1>Example with all variables modifiable</h1> <h1>Example with all modifiable variables</h1>
<pre>--- <pre>---
var1: true var1: true

View file

@ -1,4 +1,4 @@
# Example with all variables modifiable # Example with all modifiable variables
```yaml ```yaml
--- ---

View file

@ -1,4 +1,4 @@
Example with all variables modifiable Example with all modifiable variables
---  --- 
var1: true  var1: true 

View file

@ -1,4 +1,4 @@
== Example with all variables modifiable == Example with all modifiable variables
[,yaml] [,yaml]
---- ----

View file

@ -1,4 +1,4 @@
<details><summary>Example with all variables modifiable</summary> <details><summary>Example with all modifiable variables</summary>
```yaml ```yaml
--- ---

View file

@ -1,4 +1,4 @@
<h1>Example with all variables modifiable</h1> <h1>Example with all modifiable variables</h1>
<pre>--- <pre>---
variable: true</pre> variable: true</pre>

View file

@ -1,4 +1,4 @@
# Example with all variables modifiable # Example with all modifiable variables
```yaml ```yaml
--- ---

Some files were not shown because too many files have changed in this diff Show more