Compare commits

..

No commits in common. "0.2.0a47" and "main" have entirely different histories.

18313 changed files with 26165 additions and 305890 deletions

View file

@ -1,398 +1,3 @@
## 0.2.0a47 (2026-04-30)
### Feat
- add dot if needed
- 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
### Fix
- better transitive documentation
- update translation
## 0.2.0a45 (2026-01-21)
### Feat
- 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
## 0.2.0a42 (2026-01-04)
### Feat
- 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
- 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
- add anchor to markdown format and remove unsupported character in anchor id
- 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
## 0.2.0a37 (2025-11-06)
### Feat
- delete/underline is inside tag for some format
- can reload formatter
- can document part by part with reloading structure
## 0.2.0a36 (2025-10-29)
### Feat
- anchor in gitlab output_format
- can had comments with family/variable description in examples doc
- comment variables from a family
## 0.2.0a35 (2025-10-27)
### Feat
- 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
### 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 remove header when generate a table
- add html output
- 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
## 0.2.0a30 (2025-10-02)
### Feat
- 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
### 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
- add integer type which will replace number type
## 0.2.0a25 (2025-09-22)
### Feat
- adapt to tiramisu-web-ui
## 0.2.0a24 (2025-06-19)
### Feat
- 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
- better console output
- 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
## 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
## 0.2.0a3 (2025-01-04)
### Fix
- detect_symlink => only_self
## 0.2.0a2 (2025-01-04)
### Feat
- 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
- add console output
- better dynamique family support
- add json output
### Fix
- correction for properties in italic
## 0.1.1a0 (2024-11-08)
### Fix
- generate documentation with force_optional configuration
## 0.1.0 (2024-11-06)
## 0.1.0rc1 (2024-11-06)
### Fix

View file

@ -1,80 +0,0 @@
---
gitea: none
include_toc: true
---
[🇬🇧 (EN)](README.md) - [🇫🇷 (FR)](README.fr.md)
## Générer la documentation depuis les fichiers de structure
> [!NOTE]
>
> Les fichiers de structure contiennent toutes les informations relatif aux variables. Cette sortie génère la documentation pour tout ou partie de ces variables.\
> **Chemin** : doc\
> *`désactivé`*\
> **Désactivé** : si "[sélection pour sortie](#step.output)" n'est pas doc.
| Variable | Description | Valeur par défaut | Type | Contrôle des accès | Validateur |
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------|-------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
| **<a id="doc.output_format" name="doc.output_format">doc.output_format</a>**<br/>**Ligne de commande** : <br/>-do, --doc.output_format<br/>**Variable d'environnement** : DOC.OUTPUT_FORMAT | Le format de sortie de la documentation générée. | console | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` | | **Choix** : <br/>&nbsp;console<br/>&nbsp;asciidoc<br/>&nbsp;html<br/>&nbsp;github<br/>&nbsp;gitlab<br/>&nbsp;json |
| **<a id="doc.tabular_template" name="doc.tabular_template">doc.tabular_template</a>**<br/>**Ligne de commande** : <br/>-dm, --doc.tabular_template<br/>**Variable d'environnement** : DOC.TABULAR_TEMPLATE | Génère la documentation avec ce modèle de tableau.<br/>Les variables sont documentées avec une vue tableau. Une sélection de modèle vous permet de choisir le contenu de chaque colonne. | two_columns | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` | *`désactivé`*<br/>**Désactivé** : "[le format de sortie de la documentation générée](#doc.output_format)" json n\'est pas compatible avec cette variable. | **Choix** : <br/>&nbsp;two_columns<br/>&nbsp;three_columns<br/>&nbsp;four_columns<br/>&nbsp;five_columns<br/>&nbsp;six_columns |
| **<a id="doc.contents" name="doc.contents">doc.contents</a>**<br/>**Ligne de commande** : <br/>-dc, --doc.contents<br/>**Variable d'environnement** : DOC.CONTENTS | Contenu généré.<br/>Vous pouvez générer trois type de documentation. Toutes les variables (&quot;variables&quot;), un exemple de fichier au format YAML (&quot;example&quot;) ou le journal des changements (&quot;changelog&quot;). | •&nbsp;variables | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` `obligatoire` | *`cachée`*<br/>**Cachée** : "[le format de sortie de la documentation générée](#doc.output_format)" json n'est pas compatible avec le "[contenu généré](#doc.contents)" changelog ou example. | `unique`<br/>**Choix** : <br/>&nbsp;variables<br/>&nbsp;example<br/>&nbsp;changelog |
| **<a id="doc.title_level" name="doc.title_level">doc.title_level</a>**<br/>**Ligne de commande** : <br/>-dt, --doc.title_level<br/>**Variable d'environnement** : DOC.TITLE_LEVEL | Niveau de titre de départ. | 1 | [`integer`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` | | |
| **<a id="doc.default_values" name="doc.default_values">doc.default_values</a>**<br/>**Ligne de commande** : <br/>&nbsp;--doc.default_values<br/>&nbsp;--doc.no-default_values<br/>**Variable d'environnement** : DOC.DEFAULT_VALUES | Modifier les valeurs pour documenter toutes les variables.<br/>Pour documenter les variables des leadership ou des familles dynamiques, il est parfois nécessaire de générer des valeurs, qui peuvent modifier les valeurs de la configuration. Soyez vigilent si vous réutilisez cette configuration. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` | | |
| **<a id="doc.true_color" name="doc.true_color">doc.true_color</a>**<br/>**Ligne de commande** : <br/>&nbsp;--doc.true_color<br/>&nbsp;--doc.no-true_color<br/>**Variable d'environnement** : DOC.TRUE_COLOR | Afficher la documentation dans la console en permanence avec un terminal en couleurs réelles. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` | *`désactivé`*<br/>**Désactivé** : lorsque la variable "[le format de sortie de la documentation générée](#doc.output_format)" n'a pas la valeur "console". | |
### Les variables pour cette famille sont documentés dans un autre fichier
> [!NOTE]
>
> Si vous séparez les variables dans différents fichiers, le lien entre les variables va être cassé. Dans ce cas, vous devez définit différents nom de fichiers pour les fichiers contenant ces variables.\
> Cette famille contient des listes de bloc de variable.\
> **Chemin** : doc.other_root_filenames
| Variable | Description | Type | Validateur |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------|-----------------------------------------------------------------------------------------------|--------------|
| **<a id="doc.other_root_filenames.root_path" name="doc.other_root_filenames.root_path">doc.other_root_filenames.root_path</a>**<br/>**Ligne de commande** : <br/>--doc.other_root_filenames.root_path<br/>**Variable d'environnement** : DOC.OTHER_ROOT_FILENAMES.ROOT_PATH | Ce fichier contient les variables enfants de la famille. | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `unique` |
| **<a id="doc.other_root_filenames.root_doc_path" name="doc.other_root_filenames.root_doc_path">doc.other_root_filenames.root_doc_path</a>**<br/>**Ligne de commande** : <br/>--doc.other_root_filenames.root_doc_path<br/>**Variable d'environnement** : DOC.OTHER_ROOT_FILENAMES.ROOT_DOC_PATH | Nom du fichier. | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | |
| Variable | Description | Valeur par défaut | Type |
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------|---------------------|---------------------------------------------------------------------------------------------------|
| **<a id="doc.document_a_type" name="doc.document_a_type">doc.document_a_type</a>**<br/>**Ligne de commande** : <br/>&nbsp;--doc.document_a_type<br/>&nbsp;--doc.no-document_a_type<br/>**Variable d'environnement** : DOC.DOCUMENT_A_TYPE | Documenter un type de structure. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` |
### Documentation des variables et journal de changements
> [!NOTE]
>
> **Chemin** : doc.tabulars\
> *`désactivé`*\
> **Désactivé** : si "[le format de sortie de la documentation générée](#doc.output_format)" en json ou si "[contenu généré](#doc.contents)" n'est pas variables ou changelog.
| Variable | Description | Valeur par défaut | Type | Contrôle des accès | Validateur |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------|---------------------|---------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------|
| **<a id="doc.tabulars.without_family" name="doc.tabulars.without_family">doc.tabulars.without_family</a>**<br/>**Ligne de commande** : <br/>&nbsp;-df, --doc.tabulars.without_family<br/>&nbsp;-ndf, --doc.tabulars.no-without_family<br/>**Variable d'environnement** : DOC.TABULARS.WITHOUT_FAMILY | Ne pas ajouter les familles dans la documentation. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` | | |
| **<a id="doc.tabulars.with_commandline" name="doc.tabulars.with_commandline">doc.tabulars.with_commandline</a>**<br/>**Variable d'environnement** : DOC.TABULARS.WITH_COMMANDLINE | Ajoute les informations de la ligne de commande dans la documentation. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` | | |
| **<a id="doc.tabulars.with_environment" name="doc.tabulars.with_environment">doc.tabulars.with_environment</a>**<br/>**Ligne de commande** : <br/>&nbsp;-de, --doc.tabulars.with_environment<br/>&nbsp;-nde, --doc.tabulars.no-with_environment<br/>**Variable d'environnement** : DOC.TABULARS.WITH_ENVIRONMENT | Ajoute les informations de variable d&#x27;environnement dans la documentation. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` | | |
| **<a id="doc.tabulars.environment_prefix" name="doc.tabulars.environment_prefix">doc.tabulars.environment_prefix</a>**<br/>**Ligne de commande** : <br/>-dv, --doc.tabulars.environment_prefix<br/>**Variable d'environnement** : DOC.TABULARS.ENVIRONMENT_PREFIX | Préfixe du nom des variables d&#x27;environnement. | ROUGAIL | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` | *`désactivé`*<br/>**Désactivé** : si "main_namespace" n'est pas défini ou "[ajoute les informations de variable d'environnement dans la documentation](#doc.tabulars.with_environment)" est false. | Doit seulement utilise des caractères en majuscule. |
### Documentation du journal des changements
> [!NOTE]
>
> **Chemin** : doc.changelog\
> *`désactivé`*\
> **Désactivé** : changelog n'est pas défini dans "[contenu généré](#doc.contents)".
| Variable | Description | Type |
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------|
| **<a id="doc.changelog.previous_json_file" name="doc.changelog.previous_json_file">doc.changelog.previous_json_file</a>**<br/>**Ligne de commande** : <br/>-dp, --doc.changelog.previous_json_file<br/>**Variable d'environnement** : DOC.CHANGELOG.PREVIOUS_JSON_FILE | Précédent fichier de description au format JSON.<br/>Pour générer le journal des changements, vous devez comparer l&#x27;ancienne liste des variables (au format json) avec les variables courantes. | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` |
### Configuration des exemples
> [!NOTE]
>
> **Chemin** : doc.examples\
> *`désactivé`*\
> **Désactivé** : si example n'est pas défini dans "[contenu généré](#doc.contents)".
| Variable | Description | Valeur par défaut | Type | Contrôle des accès |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------|---------------------|---------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **<a id="doc.examples.comment" name="doc.examples.comment">doc.examples.comment</a>**<br/>**Ligne de commande** : <br/>&nbsp;-dx, --doc.examples.comment<br/>&nbsp;-ndx, --doc.examples.no-comment<br/>**Variable d'environnement** : DOC.EXAMPLES.COMMENT | Ajouter la description des variables et des familles lorsqu&#x27;on génère des exemples. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` | |
| **<a id="doc.examples.comment_column" name="doc.examples.comment_column">doc.examples.comment_column</a>**<br/>**Ligne de commande** : <br/>--doc.examples.comment_column<br/>**Variable d'environnement** : DOC.EXAMPLES.COMMENT_COLUMN | Commentaire dans les exemples commence à la colonne. | 30 | [`integer`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` | *`désactivé`*<br/>**Désactivé** : lorsque la variable "[ajouter la description des variables et des familles lorsqu'on génère des exemples](#doc.examples.comment)" a la valeur "false". |

View file

@ -1,80 +1,2 @@
---
gitea: none
include_toc: true
---
[🇬🇧 (EN)](README.md) - [🇫🇷 (FR)](README.fr.md)
# rougaildoc
## Generate documentation from structural files
> [!NOTE]
>
> The structural files contain all the information related to the variables. This output generates the documentation for all or some of these variables.\
> **Path**: doc\
> *`disabled`*\
> **Disabled**: if "[select for output](#step.output)" is not doc.
| Variable | Description | Default value | Type | Access control | Validator |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------|-----------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
| **<a id="doc.output_format" name="doc.output_format">doc.output_format</a>**<br/>**Command line**: <br/>-do, --doc.output_format<br/>**Environment variable**: DOC.OUTPUT_FORMAT | The output format of the generated documentation. | console | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | | **Choices**: <br/>&nbsp;console<br/>&nbsp;asciidoc<br/>&nbsp;html<br/>&nbsp;github<br/>&nbsp;gitlab<br/>&nbsp;json |
| **<a id="doc.tabular_template" name="doc.tabular_template">doc.tabular_template</a>**<br/>**Command line**: <br/>-dm, --doc.tabular_template<br/>**Environment variable**: DOC.TABULAR_TEMPLATE | Generate document with this tabular model.<br/>The variables are documented with a tabular view. A template selection allows you to choose the content of each column. | two_columns | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | *`disabled`*<br/>**Disabled**: "[the output format of the generated documentation](#doc.output_format)" in json is not compatible with this variable. | **Choices**: <br/>&nbsp;two_columns<br/>&nbsp;three_columns<br/>&nbsp;four_columns<br/>&nbsp;five_columns<br/>&nbsp;six_columns |
| **<a id="doc.contents" name="doc.contents">doc.contents</a>**<br/>**Command line**: <br/>-dc, --doc.contents<br/>**Environment variable**: DOC.CONTENTS | Generated content.<br/>You can generate three type of document. All variables (&quot;variables&quot;), an example file in YAML format (&quot;example&quot;) or change log (&quot;changelog&quot;). | •&nbsp;variables | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` `mandatory` | *`hidden`*<br/>**Hidden**: "[the output format of the generated documentation](#doc.output_format)" in json is not compatible with changelog or example "[generated content](#doc.contents)". | `unique`<br/>**Choices**: <br/>&nbsp;variables<br/>&nbsp;example<br/>&nbsp;changelog |
| **<a id="doc.title_level" name="doc.title_level">doc.title_level</a>**<br/>**Command line**: <br/>-dt, --doc.title_level<br/>**Environment variable**: DOC.TITLE_LEVEL | Starting title level. | 1 | [`integer`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | | |
| **<a id="doc.default_values" name="doc.default_values">doc.default_values</a>**<br/>**Command line**: <br/>&nbsp;--doc.default_values<br/>&nbsp;--doc.no-default_values<br/>**Environment variable**: DOC.DEFAULT_VALUES | Modify values to document all variables.<br/>To document leadership or dynamic family variables, it is sometimes necessary to generate values, which can change the values in the configuration. Be careful if you reuse this configuration. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | | |
| **<a id="doc.true_color" name="doc.true_color">doc.true_color</a>**<br/>**Command line**: <br/>&nbsp;--doc.true_color<br/>&nbsp;--doc.no-true_color<br/>**Environment variable**: DOC.TRUE_COLOR | Display documentation in console always with true color terminal. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | *`disabled`*<br/>**Disabled**: when the variable "[the output format of the generated documentation](#doc.output_format)" hasn't the value "console". | |
### The variables in this family are documented in another file
> [!NOTE]
>
> If you separate the variables into different files, the links between the variables will break. Therefore, you must define different filenames for the files containing these variables.\
> This family contains lists of variable blocks.\
> **Path**: doc.other_root_filenames
| Variable | Description | Type | Validator |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------|-----------------------------------------------------------------------------------------------|-------------|
| **<a id="doc.other_root_filenames.root_path" name="doc.other_root_filenames.root_path">doc.other_root_filenames.root_path</a>**<br/>**Command line**: <br/>--doc.other_root_filenames.root_path<br/>**Environment variable**: DOC.OTHER_ROOT_FILENAMES.ROOT_PATH | This file contains child variables of the family. | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `unique` |
| **<a id="doc.other_root_filenames.root_doc_path" name="doc.other_root_filenames.root_doc_path">doc.other_root_filenames.root_doc_path</a>**<br/>**Command line**: <br/>--doc.other_root_filenames.root_doc_path<br/>**Environment variable**: DOC.OTHER_ROOT_FILENAMES.ROOT_DOC_PATH | Name of the file. | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | |
| Variable | Description | Default value | Type |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------|-----------------|-------------------------------------------------------------------------------------------------|
| **<a id="doc.document_a_type" name="doc.document_a_type">doc.document_a_type</a>**<br/>**Command line**: <br/>&nbsp;--doc.document_a_type<br/>&nbsp;--doc.no-document_a_type<br/>**Environment variable**: DOC.DOCUMENT_A_TYPE | Documentation a structural type. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` |
### Variables and changelog documentation
> [!NOTE]
>
> **Path**: doc.tabulars\
> *`disabled`*\
> **Disabled**: if "[the output format of the generated documentation](#doc.output_format)" is json or "[generated content](#doc.contents)" hasn't variables or changelog.
| Variable | Description | Default value | Type | Access control | Validator |
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------|-----------------|-------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------|
| **<a id="doc.tabulars.without_family" name="doc.tabulars.without_family">doc.tabulars.without_family</a>**<br/>**Command line**: <br/>&nbsp;-df, --doc.tabulars.without_family<br/>&nbsp;-ndf, --doc.tabulars.no-without_family<br/>**Environment variable**: DOC.TABULARS.WITHOUT_FAMILY | Do not add families in documentation. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | | |
| **<a id="doc.tabulars.with_commandline" name="doc.tabulars.with_commandline">doc.tabulars.with_commandline</a>**<br/>**Environment variable**: DOC.TABULARS.WITH_COMMANDLINE | Add command line informations in documentation. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | | |
| **<a id="doc.tabulars.with_environment" name="doc.tabulars.with_environment">doc.tabulars.with_environment</a>**<br/>**Command line**: <br/>&nbsp;-de, --doc.tabulars.with_environment<br/>&nbsp;-nde, --doc.tabulars.no-with_environment<br/>**Environment variable**: DOC.TABULARS.WITH_ENVIRONMENT | Add environment variable informations in documentation. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | | |
| **<a id="doc.tabulars.environment_prefix" name="doc.tabulars.environment_prefix">doc.tabulars.environment_prefix</a>**<br/>**Command line**: <br/>-dv, --doc.tabulars.environment_prefix<br/>**Environment variable**: DOC.TABULARS.ENVIRONMENT_PREFIX | Environment variables prefix name. | ROUGAIL | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | *`disabled`*<br/>**Disabled**: if "main_namespace" is not set or "[add environment variable informations in documentation](#doc.tabulars.with_environment)" is false. | Should only use uppercase characters. |
### Changelog documentation
> [!NOTE]
>
> **Path**: doc.changelog\
> *`disabled`*\
> **Disabled**: if changelog in not in "[generated content](#doc.contents)".
| Variable | Description | Type |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|
| **<a id="doc.changelog.previous_json_file" name="doc.changelog.previous_json_file">doc.changelog.previous_json_file</a>**<br/>**Command line**: <br/>-dp, --doc.changelog.previous_json_file<br/>**Environment variable**: DOC.CHANGELOG.PREVIOUS_JSON_FILE | Previous description file in JSON format.<br/>To generate the changelog, you need to compare the old list of variables (in json format) with the current variables. | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` |
### Examples configuration
> [!NOTE]
>
> **Path**: doc.examples\
> *`disabled`*\
> **Disabled**: if example is not in "[generated content](#doc.contents)".
| Variable | Description | Default value | Type | Access control |
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------|-----------------|-------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **<a id="doc.examples.comment" name="doc.examples.comment">doc.examples.comment</a>**<br/>**Command line**: <br/>&nbsp;-dx, --doc.examples.comment<br/>&nbsp;-ndx, --doc.examples.no-comment<br/>**Environment variable**: DOC.EXAMPLES.COMMENT | Add description of variables and families when generate examples. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | |
| **<a id="doc.examples.comment_column" name="doc.examples.comment_column">doc.examples.comment_column</a>**<br/>**Command line**: <br/>--doc.examples.comment_column<br/>**Environment variable**: DOC.EXAMPLES.COMMENT_COLUMN | Comment in examples starts at column. | 30 | [`integer`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | *`disabled`*<br/>**Disabled**: when the variable "[add description of variables and families when generate examples](#doc.examples.comment)" has the value "false". |

Binary file not shown.

View file

@ -5,8 +5,8 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2026-04-30 06:54+0200\n"
"PO-Revision-Date: 2026-04-30 06:55+0200\n"
"POT-Creation-Date: 2024-11-01 11:42+0100\n"
"PO-Revision-Date: 2024-11-01 11:42+0100\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: fr\n"
@ -14,616 +14,138 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 3.9\n"
"X-Generator: Poedit 3.5\n"
#: src/rougail/output_doc/changelog.py:153
msgid "New variable"
msgstr "Nouvelle variable"
#: src/rougail/output_doc/__init__.py:40
msgid "the domain name can starts by a dot"
msgstr "le nom de domaine peut commencé par un point"
#: src/rougail/output_doc/changelog.py:155
msgid "New variables"
msgstr "Nouvelles variables"
#: src/rougail/output_doc/__init__.py:41
msgid "the domain name can be a hostname"
msgstr "le nom de domaine peut être un nom d'hôte"
#: src/rougail/output_doc/changelog.py:165
msgid "Modified variable"
msgstr "Variable modifiée"
#: src/rougail/output_doc/__init__.py:42
msgid "the domain name can be an IP"
msgstr "le nom de domaine peut être une IP"
#: src/rougail/output_doc/changelog.py:167
msgid "Modified variables"
msgstr "Variables modifiées"
#: src/rougail/output_doc/__init__.py:43
msgid "the domain name can be network in CIDR format"
msgstr "le nom de domaine peut être un réseau au format CIDR"
#: src/rougail/output_doc/changelog.py:177
msgid "Deleted variable"
msgstr "Variable supprimée"
#: src/rougail/output_doc/__init__.py:48
msgid "the minimum value is {0}"
msgstr "le valeur minimal est {0}"
#: src/rougail/output_doc/changelog.py:179
msgid "Deleted variables"
msgstr "Variables supprimées"
#: src/rougail/output_doc/__init__.py:49
msgid "the maximum value is {0}"
msgstr "le valeur maximal est {0}"
#: src/rougail/output_doc/collect.py:53
msgid ""
"cannot find \"{0}_calculation\" information, do you have annotate this "
"configuration?"
msgstr ""
"ne peut trouver l'information \"{0}_calculation\", avez-vous annoté cette "
"configuration ?"
#: src/rougail/output_doc/__init__.py:55
msgid "IP must be in CIDR format"
msgstr "IP doit être au format CIDR"
#: src/rougail/output_doc/collect.py:107
msgid "the value of the information \"{0}\" of the variable {{0}}"
msgstr "la valeur de l'information \"{0}\" de la variable \"{{0}}\""
#: src/rougail/output_doc/__init__.py:56
msgid "private IP are allowed"
msgstr "les IP privées sont autorisés"
#: src/rougail/output_doc/collect.py:115
msgid "the value of the global information \"{0}\""
msgstr "la valeur de l'information globale \"{0}\""
#: src/rougail/output_doc/__init__.py:57
msgid "reserved IP are allowed"
msgstr "les IP réservés sont autorisés"
#: src/rougail/output_doc/collect.py:121
msgid "the value of the {0}"
msgstr "la valeur de l'{0}"
#: src/rougail/output_doc/__init__.py:62
msgid "the host name can be an IP"
msgstr "le nom d'hôte peut être une IP"
#: src/rougail/output_doc/collect.py:130
msgid "depends on a calculation"
msgstr "dépend d'un calcul"
#: src/rougail/output_doc/__init__.py:67
msgid "the domain name in web address can be an IP"
msgstr "le nom de domaine dans l'adresse web peut être une IP"
#: src/rougail/output_doc/collect.py:131
msgid "\"{0}\" is a calculation for {1} but has no description in {2}"
msgstr "\"{0}\" est un calcul pour {1} mais n'a pas de description dans {2}"
#: src/rougail/output_doc/__init__.py:68
msgid "the domain name in web address can be only a hostname"
msgstr "le nom de domaine dans l'adresse web ne peut être qu'un nom d'hôte"
#: src/rougail/output_doc/collect.py:190
msgid "depends on an undocumented variable"
msgstr "dépends d'une variable non documentée"
#: src/rougail/output_doc/__init__.py:75
msgid "can be range of port"
msgstr "peut être un range de port"
#: src/rougail/output_doc/collect.py:208
msgid "is \"{0}\""
msgstr "est \"{0}\""
#: src/rougail/output_doc/__init__.py:76
msgid "can have the protocol"
msgstr "peut avoir un protocole"
#: src/rougail/output_doc/collect.py:213
msgid "is accessible"
msgstr "est accessible"
#: src/rougail/output_doc/__init__.py:77
msgid "port 0 is allowed"
msgstr "le port 0 est autorisé"
#: src/rougail/output_doc/collect.py:215
msgid "is defined"
msgstr "est définie"
#: src/rougail/output_doc/__init__.py:78
msgid "ports 1 to 1023 are allowed"
msgstr "les ports entre 1 et 1023 sont autorisés"
#: src/rougail/output_doc/collect.py:220
msgid "hasn't the value \"{0}\""
msgstr "n'a pas la valeur \"{0}\""
#: src/rougail/output_doc/__init__.py:79
msgid "ports 1024 to 49151 are allowed"
msgstr "les ports entre 1024 et 49151 sont autorisés"
#: src/rougail/output_doc/collect.py:222
msgid "has the value \"{0}\""
msgstr "a la valeur \"{0}\""
#: src/rougail/output_doc/__init__.py:80
msgid "ports greater than 49152 are allowed"
msgstr "les ports supérieurs à 49152 sont autorisés"
#: src/rougail/output_doc/collect.py:226
msgid "is {0}"
msgstr "est {0}"
#: src/rougail/output_doc/__init__.py:125
msgid "mandatory"
msgstr "obligatoire"
#: src/rougail/output_doc/collect.py:228
msgid "when the variable {{0}} {0}."
msgstr "lorsque la variable {{0}} {0}."
#: src/rougail/output_doc/__init__.py:126
msgid "hidden"
msgstr "caché"
#: src/rougail/output_doc/collect.py:256
msgid "the value of the variable {0} if it is defined"
msgstr "la valeur de la variable {0} si elle est définie"
#: src/rougail/output_doc/__init__.py:127
msgid "disabled"
msgstr "désactivé"
#: src/rougail/output_doc/collect.py:258
msgid "the value of the variable {0}"
msgstr "la valeur de la variable {0}"
#: src/rougail/output_doc/__init__.py:128
msgid "unique"
msgstr "unique"
#: src/rougail/output_doc/collect.py:277
msgid "(from an undocumented variable)"
msgstr "(issue d'une variable non documentée)"
#: src/rougail/output_doc/__init__.py:129
msgid "auto modified"
msgstr "auto modifiée"
#: src/rougail/output_doc/collect.py:283
msgid "{0} (from an undocumented variable)"
msgstr "{0} (issue d'une variable non documentée)"
#: src/rougail/output_doc/__init__.py:163
msgid "Variables for \"{0}\""
msgstr "Variables pour \"{0}\""
#: src/rougail/output_doc/collect.py:287
msgid "the value of an undocumented variable"
msgstr "la valeur d'une variable non documentée"
#: src/rougail/output_doc/__init__.py:180
msgid "Variables"
msgstr "Variables"
#: src/rougail/output_doc/collect.py:322
msgid "when the identifier is \"{0}\""
msgstr "lorsque l'identifiant est \"{0}\""
#: src/rougail/output_doc/collect.py:324
msgid "when the identifier is not \"{0}\""
msgstr "lorsque l'identifiant n'est pas \"{0}\""
#: src/rougail/output_doc/collect.py:329
msgid "the value of the identifier"
msgstr "la valeur de l'identifiant"
#: src/rougail/output_doc/collect.py:426
msgid "This family contains lists of variable blocks"
msgstr "Cette famille contient des listes de bloc de variable"
#: src/rougail/output_doc/collect.py:430
msgid "This family builds families dynamically"
msgstr "Cette famille construit des familles dynamiquement"
#: src/rougail/output_doc/collect.py:440
msgid "This family is a namespace"
msgstr "Cette famille est un espace de nom"
#: src/rougail/output_doc/collect.py:489
msgid "Example"
msgstr "Exemple"
#: src/rougail/output_doc/collect.py:492
msgid "Examples"
msgstr "Exemples"
#: src/rougail/output_doc/collect.py:498
msgid "Tag"
msgstr "Étiquette"
#: src/rougail/output_doc/collect.py:501
msgid "Tags"
msgstr "Étiquettes"
#: src/rougail/output_doc/collect.py:597
msgid "text based with regular expressions \"{0}\""
msgstr "texte avec expression rationnelle \"{0}\""
#: src/rougail/output_doc/collect.py:601
#: src/rougail/output_doc/tabular/six_columns.py:83
msgid "Validator"
msgstr "Validateur"
#: src/rougail/output_doc/collect.py:604
msgid "Validators"
msgstr "Validateurs"
#: src/rougail/output_doc/collect.py:613
msgid "Choices"
msgstr "Choix"
#: src/rougail/output_doc/collect.py:665
msgid "Default"
msgstr "Défaut"
#: src/rougail/output_doc/collect.py:675
msgid "No attribute \"description\" for \"{0}\" in {1}"
msgstr "Aucun attribut \"description\" pour \"{0}\" dans {1}"
#: src/rougail/output_doc/config.py:54
msgid "duplicated level rougail-output-doc for {0} \"{1}\": {2} and {3}"
msgstr "niveau dupliqué pour rougail-doc pour {0} \"{1}\": {2} et {3}"
#: src/rougail/output_doc/config.py:60
msgid "duplicated name \"{0}\" in rougail-output-doc"
msgstr "nom dupliqué \"{0}\" dans rougail-output-doc"
#: src/rougail/output_doc/config.py:116
msgid "is true if doc is activate"
msgstr "est true si doc est activé"
#: src/rougail/output_doc/config.py:119
msgid "generate documentation from structural files"
msgstr "générer la documentation depuis les fichiers de structure"
#: src/rougail/output_doc/config.py:120
msgid ""
"The structural files contain all the information related to the variables. "
"This output generates the documentation for all or some of these variables."
msgstr ""
"Les fichiers de structure contiennent toutes les informations relatif aux "
"variables. Cette sortie génère la documentation pour tout ou partie de ces "
"variables."
#: src/rougail/output_doc/config.py:125
msgid "if \"step.output\" is not doc"
msgstr "si \"step.output\" n'est pas doc"
#: src/rougail/output_doc/config.py:128
msgid "the output format of the generated documentation"
msgstr "le format de sortie de la documentation générée"
#: src/rougail/output_doc/config.py:137
msgid "generate document with this tabular model"
msgstr "génère la documentation avec ce modèle de tableau"
#: src/rougail/output_doc/config.py:138
msgid ""
"The variables are documented with a tabular view. A template selection "
"allows you to choose the content of each column."
msgstr ""
"Les variables sont documentées avec une vue tableau. Une sélection de modèle "
"vous permet de choisir le contenu de chaque colonne."
#: src/rougail/output_doc/config.py:146
msgid "\"_.output_format\" in json is not compatible with this variable"
msgstr "\"_.output_format\" json n\\'est pas compatible avec cette variable"
#: src/rougail/output_doc/config.py:153
msgid "generated content"
msgstr "contenu généré"
#: src/rougail/output_doc/config.py:154
msgid ""
"You can generate three type of document. All variables (\"variables\"), an "
"example file in YAML format (\"example\") or change log (\"changelog\")."
msgstr ""
"Vous pouvez générer trois type de documentation. Toutes les variables "
"(\"variables\"), un exemple de fichier au format YAML (\"example\") ou le "
"journal des changements (\"changelog\")."
#: src/rougail/output_doc/config.py:167
msgid ""
"\"_.output_format\" in json is not compatible with changelog or example "
"\"_.contents\""
msgstr ""
"\"_.output_format\" json n'est pas compatible avec le \"_.contents\" "
"changelog ou example"
#: src/rougail/output_doc/config.py:170
msgid "Starting title level"
msgstr "Niveau de titre de départ"
#: src/rougail/output_doc/config.py:175
msgid "Modify values to document all variables"
msgstr "Modifier les valeurs pour documenter toutes les variables"
#: src/rougail/output_doc/config.py:176
msgid ""
"To document leadership or dynamic family variables, it is sometimes "
"necessary to generate values, which can change the values in the "
"configuration. Be careful if you reuse this configuration."
msgstr ""
"Pour documenter les variables des leadership ou des familles dynamiques, il "
"est parfois nécessaire de générer des valeurs, qui peuvent modifier les "
"valeurs de la configuration. Soyez vigilent si vous réutilisez cette "
"configuration."
#: src/rougail/output_doc/config.py:180
msgid "Display documentation in console always with true color terminal"
msgstr ""
"Afficher la documentation dans la console en permanence avec un terminal en "
"couleurs réelles"
#: src/rougail/output_doc/config.py:187
msgid "The variables in this family are documented in another file"
msgstr "Les variables pour cette famille sont documentés dans un autre fichier"
#: src/rougail/output_doc/config.py:188
msgid ""
"If you separate the variables into different files, the links between the "
"variables will break. Therefore, you must define different filenames for the "
"files containing these variables."
msgstr ""
"Si vous séparez les variables dans différents fichiers, le lien entre les "
"variables va être cassé. Dans ce cas, vous devez définit différents nom de "
"fichiers pour les fichiers contenant ces variables."
#: src/rougail/output_doc/config.py:192
msgid "This file contains child variables of the family"
msgstr "Ce fichier contient les variables enfants de la famille"
#: src/rougail/output_doc/config.py:196
msgid "Name of the file"
msgstr "Nom du fichier"
#: src/rougail/output_doc/config.py:200
msgid "Documentation a structural type"
msgstr "Documenter un type de structure"
#: src/rougail/output_doc/config.py:204
msgid "Variables and changelog documentation"
msgstr "Documentation des variables et journal de changements"
#: src/rougail/output_doc/config.py:209
msgid ""
"if \"_.output_format\" is json or \"_.contents\" hasn't variables or "
"changelog"
msgstr ""
"si \"_.output_format\" en json ou si \"_.contents\" n'est pas variables ou "
"changelog"
#: src/rougail/output_doc/config.py:212
msgid "Do not add families in documentation"
msgstr "Ne pas ajouter les familles dans la documentation"
#: src/rougail/output_doc/config.py:217
msgid "add command line informations in documentation"
msgstr "ajoute les informations de la ligne de commande dans la documentation"
#: src/rougail/output_doc/config.py:222
msgid "add environment variable informations in documentation"
msgstr ""
"ajoute les informations de variable d'environnement dans la documentation"
#: src/rougail/output_doc/config.py:227
msgid "Environment variables prefix name"
msgstr "Préfixe du nom des variables d'environnement"
#: src/rougail/output_doc/config.py:234
msgid "should only use uppercase characters"
msgstr "doit seulement utilise des caractères en majuscule"
#: src/rougail/output_doc/config.py:239
msgid "if \"main_namespace\" is not set or \"_.with_environment\" is false"
msgstr ""
"si \"main_namespace\" n'est pas défini ou \"_.with_environment\" est false"
#: src/rougail/output_doc/config.py:242
msgid "Changelog documentation"
msgstr "Documentation du journal des changements"
#: src/rougail/output_doc/config.py:247
msgid "if changelog in not in \"_.contents\""
msgstr "changelog n'est pas défini dans \"_.contents\""
#: src/rougail/output_doc/config.py:250
msgid "Previous description file in JSON format"
msgstr "Précédent fichier de description au format JSON"
#: src/rougail/output_doc/config.py:251
msgid ""
"To generate the changelog, you need to compare the old list of variables (in "
"json format) with the current variables."
msgstr ""
"Pour générer le journal des changements, vous devez comparer l'ancienne "
"liste des variables (au format json) avec les variables courantes."
#: src/rougail/output_doc/config.py:255
msgid "Examples configuration"
msgstr "Configuration des exemples"
#: src/rougail/output_doc/config.py:260
msgid "if example is not in \"_.contents\""
msgstr "si example n'est pas défini dans \"_.contents\""
#: src/rougail/output_doc/config.py:263
msgid "add description of variables and families when generate examples"
msgstr ""
"ajouter la description des variables et des familles lorsqu'on génère des "
"exemples"
#: src/rougail/output_doc/config.py:268
msgid "Comment in examples starts at column"
msgstr "Commentaire dans les exemples commence à la colonne"
#: src/rougail/output_doc/doc.py:58
msgid "{0} is not set as step.output"
msgstr "{0} n'est pas défini dans step.output"
#: src/rougail/output_doc/example.py:61
#: src/rougail/output_doc/__init__.py:187
msgid "Example with mandatory variables not filled in"
msgstr "Exemple avec des variables obligatoire non renseignée"
#: src/rougail/output_doc/example.py:63
msgid "Example with all variables modifiable"
msgstr "Exemple avec toutes les variables modifiable"
#: src/rougail/output_doc/output/asciidoc.py:156
#: src/rougail/output_doc/output/console.py:234
#: src/rougail/output_doc/output/gitlab.py:53
msgid "Informations"
msgstr "Informations"
#: src/rougail/output_doc/output/console.py:75
msgid "cannot find Python module Rich, please install it!"
msgstr "ne peut trouver le module Python Rich, veuillez l'installer !"
#: src/rougail/output_doc/tabular/five_columns.py:72
msgid "Access control"
msgstr "Contrôle des accès"
#: src/rougail/output_doc/tabular/four_columns.py:64
msgid "Type"
msgstr "Type"
#: src/rougail/output_doc/tabular/three_columns.py:54
msgid "Default value"
msgstr "Valeur par défaut"
#: src/rougail/output_doc/tabular/two_columns.py:56
msgid "Variable"
msgstr "Variable"
#: src/rougail/output_doc/tabular/two_columns.py:58
msgid "Description"
msgstr "Description"
#: src/rougail/output_doc/utils.py:204
msgid "Command line"
msgstr "Ligne de commande"
#: src/rougail/output_doc/utils.py:222
msgid "Environment variable"
msgstr "Variable d'environnement"
#: src/rougail/output_doc/utils.py:545
msgid "Path"
msgstr "Chemin"
#: src/rougail/output_doc/utils.py:555
msgid "Identifiers"
msgstr "Identifiants"
#: src/rougail/output_doc/utils.py:849 src/rougail/output_doc/utils.py:858
#: src/rougail/output_doc/utils.py:864 src/rougail/output_doc/utils.py:870
#: src/rougail/output_doc/utils.py:874
#: src/rougail/output_doc/__init__.py:493
msgid "(default)"
msgstr "(défaut)"
msgstr "(defaut)"
#: src/rougail/output_doc/utils.py:1211
msgid "{0}: {1}"
msgstr "{0} : {1}"
#: src/rougail/output_doc/__init__.py:498
msgid "Choices"
msgstr "Choix"
#~ msgid "if doc is not set in \"step.output\""
#~ msgstr "si doc n'est pas spécifié dans \"step.output\""
#: src/rougail/output_doc/__init__.py:501
msgid "Default"
msgstr "Défaut"
#~ msgid "the values of undocumented variables"
#~ msgstr "les valeurs de variables non documentées"
#: src/rougail/output_doc/__init__.py:559
msgid "the value of the variable \"{0}\""
msgstr "la valeur de la variable \"{0}\""
#~ msgid ""
#~ "when the variable \"{{0}}\" is defined, accessible and hasn't the value "
#~ "\"{0}\""
#~ msgstr ""
#~ "lorsque la variable \"{{0}}\" est définie, accessible et n'a pas la "
#~ "valeur \"{0}\""
#: src/rougail/output_doc/__init__.py:564
#: src/rougail/output_doc/__init__.py:566
msgid "value of the {0}"
msgstr "la valeur de {0}"
#~ msgid "when the variable \"{{0}}\" is defined and hasn't the value \"{0}\""
#~ msgstr ""
#~ "lorsque la variable \"{{0}}\" est définie et n'a pas la valeur \"{0}\""
#: src/rougail/output_doc/__init__.py:638
#: src/rougail/output_doc/__init__.py:651
msgid "Example"
msgstr "Exemple"
#~ msgid ""
#~ "when the variable \"{{0}}\" is accessible and hasn't the value \"{0}\""
#~ msgstr ""
#~ "lorsque la variable \"{{0}}\" est accessible et n'a pas la valeur \"{0}\""
#~ msgid "when the variable \"{{0}}\" hasn't the value \"{0}\""
#~ msgstr "lorsque la variable \"{{0}}\" n'a pas la valeur \"{0}\""
#~ msgid ""
#~ "when the variable \"{{0}}\" is defined, is accessible and has the value "
#~ "\"{0}\""
#~ msgstr ""
#~ "lorsque la variable \"{{0}}\" est définie, accessible et a la valeur "
#~ "\"{0}\""
#~ msgid "when the variable \"{{0}}\" is defined and has the value \"{0}\""
#~ msgstr "lorsque la variable \"{{0}}\" est définie et a la valeur \"{0}\""
#~ msgid "when the variable \"{{0}}\" is accessible and has the value \"{0}\""
#~ msgstr "lorsque la variable \"{{0}}\" est accessible et a la valeur \"{0}\""
#~ msgid "when the variable \"{{0}}\" has the value \"{0}\""
#~ msgstr "lorsque la variable \"{{0}}\" a la valeur \"{0}\""
#~ msgid "Document the child variables of the family"
#~ msgstr "Documenter les variables enfants de cette famille"
#~ msgid ""
#~ "By default, all accessible variables are included in the documentation. "
#~ "It is possible to define the family from which the documentation should "
#~ "be generated."
#~ msgstr ""
#~ "Par défaut, toute les variables accessibles sont incluent dans la "
#~ "documentation. Il est possible de définir une famille a partir de "
#~ "laquelle la documentation doit être générée."
#~ msgid "variables is not selected in \"_.contents\""
#~ msgstr "variables n'est pas sélectionné dans \"_.contents\""
#~ msgid "Name of the default environment prefix"
#~ msgstr "Nom du préfixe d'environnement par défaut"
#~ msgid "documentation must be splitted"
#~ msgstr "documentation doit être séparée"
#~ msgid "Root family name"
#~ msgstr "Nom de la famille racine"
#~ msgid "disabled when there is no mode available"
#~ msgstr "désactiver lorsqu'il n'y a pas de mode valable"
#~ msgid "verify if disable modes already exists"
#~ msgstr "vérifier si le mode existe déjà"
#~ msgid "Modify values to document leaderships and dynamics families"
#~ msgstr "Valeurs modifiées pour documenter les familles leader ou dynamique"
#~ msgid "Force true color terminal"
#~ msgstr "Force les vrais couleurs dans le terminal"
#~ msgid "multiple"
#~ msgstr "multiple"
#~ msgid "the domain name can starts by a dot"
#~ msgstr "le nom de domaine peut commencer par un point"
#~ msgid "the domain name can be a hostname"
#~ msgstr "le nom de domaine peut être un nom d'hôte"
#~ msgid "the domain name can be an IP"
#~ msgstr "le nom de domaine peut être une IP"
#~ msgid "the domain name can be network in CIDR format"
#~ msgstr "le nom de domaine peut être un réseau au format CIDR"
#~ msgid "the minimum value is {0}"
#~ msgstr "le valeur minimal est {0}"
#~ msgid "the maximum value is {0}"
#~ msgstr "le valeur maximal est {0}"
#~ msgid "IP must be in CIDR format"
#~ msgstr "IP doit être au format CIDR"
#~ msgid "private IP are allowed"
#~ msgstr "les IP privées sont autorisés"
#~ msgid "reserved IP are allowed"
#~ msgstr "les IP réservés sont autorisés"
#~ msgid "network must be in CIDR format"
#~ msgstr "réseau doit être au format CIDR"
#~ msgid "the host name can be an IP"
#~ msgstr "le nom d'hôte peut être une IP"
#~ msgid "the domain name in web address can be an IP"
#~ msgstr "le nom de domaine dans l'adresse web peut être une IP"
#~ msgid "the domain name in web address can be only a hostname"
#~ msgstr "le nom de domaine dans l'adresse web ne peut être qu'un nom d'hôte"
#~ msgid "can be range of port"
#~ msgstr "peut être un range de port"
#~ msgid "can have the protocol"
#~ msgstr "peut avoir un protocole"
#~ msgid "port 0 is allowed"
#~ msgstr "le port 0 est autorisé"
#~ msgid "well-known ports (1 to 1023) are allowed"
#~ msgstr "les ports connus (de 1 à 1023) sont autorisés"
#~ msgid "registred ports (1024 to 49151) are allowed"
#~ msgstr "les ports enregistrés (de 1024 à 49151) sont autorisés"
#~ msgid "private ports (greater than 49152) are allowed"
#~ msgstr "les ports privés (supérieurs à 49152) sont autorisés"
#~ msgid "minimum length for the secret is {0} characters"
#~ msgstr "longueur minimum pour le secret est de {0} caractères"
#~ msgid "maximum length for the secret is {0} characters"
#~ msgstr "longueur maximal pour le secret est de {0} caractères"
#~ msgid "forbidden characters: {0}"
#~ msgstr "caractères interdits: {0}"
#~ msgid "this filename could be a relative path"
#~ msgstr "ce nom de fichier peut être un chemin relative"
#~ msgid "this file must exists"
#~ msgstr "ce fichier doit exister"
#~ msgid "file type allowed: {0}"
#~ msgstr "type de fichier autorisé : {0}"
#~ msgid "Configuration rougail-doc"
#~ msgstr "Configuration de rougail-doc"
#~ msgid "Variables for \"{0}\""
#~ msgstr "Variables pour \"{0}\""
#~ msgid "Generate example"
#~ msgstr "Génération de l'exemple"
#~ msgid "Display example in documentation"
#~ msgstr "Afficher un exemple dans la documentation"
#~ msgid "Hide example in documentation"
#~ msgstr "Cacher l'exemple dans la documentation"
#, fuzzy
#~| msgid ":"
#~ msgid ": "
#~ msgstr " : "
#~ msgid "when the variable \"{0}\" has the value \"True\""
#~ msgstr "lorsque la variable \"{0}\" a la valeur \"True\""
#: src/rougail/output_doc/__init__.py:649
msgid "Examples"
msgstr "Exemples"

View file

@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2026-04-30 06:55+0200\n"
"POT-Creation-Date: 2024-11-01 11:42+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -15,388 +15,137 @@ msgstr ""
"Generated-By: pygettext.py 1.5\n"
#: src/rougail/output_doc/changelog.py:153
msgid "New variable"
#: src/rougail/output_doc/__init__.py:40
msgid "the domain name can starts by a dot"
msgstr ""
#: src/rougail/output_doc/changelog.py:155
msgid "New variables"
#: src/rougail/output_doc/__init__.py:41
msgid "the domain name can be a hostname"
msgstr ""
#: src/rougail/output_doc/changelog.py:165
msgid "Modified variable"
#: src/rougail/output_doc/__init__.py:42
msgid "the domain name can be an IP"
msgstr ""
#: src/rougail/output_doc/changelog.py:167
msgid "Modified variables"
#: src/rougail/output_doc/__init__.py:43
msgid "the domain name can be network in CIDR format"
msgstr ""
#: src/rougail/output_doc/changelog.py:177
msgid "Deleted variable"
#: src/rougail/output_doc/__init__.py:48
msgid "the minimum value is {0}"
msgstr ""
#: src/rougail/output_doc/changelog.py:179
msgid "Deleted variables"
#: src/rougail/output_doc/__init__.py:49
msgid "the maximum value is {0}"
msgstr ""
#: src/rougail/output_doc/collect.py:53
msgid "cannot find \"{0}_calculation\" information, do you have annotate this configuration?"
#: src/rougail/output_doc/__init__.py:55
msgid "IP must be in CIDR format"
msgstr ""
#: src/rougail/output_doc/collect.py:107
msgid "the value of the information \"{0}\" of the variable {{0}}"
#: src/rougail/output_doc/__init__.py:56
msgid "private IP are allowed"
msgstr ""
#: src/rougail/output_doc/collect.py:115
msgid "the value of the global information \"{0}\""
#: src/rougail/output_doc/__init__.py:57
msgid "reserved IP are allowed"
msgstr ""
#: src/rougail/output_doc/collect.py:121
msgid "the value of the {0}"
#: src/rougail/output_doc/__init__.py:62
msgid "the host name can be an IP"
msgstr ""
#: src/rougail/output_doc/collect.py:130
msgid "depends on a calculation"
#: src/rougail/output_doc/__init__.py:67
msgid "the domain name in web address can be an IP"
msgstr ""
#: src/rougail/output_doc/collect.py:131
msgid "\"{0}\" is a calculation for {1} but has no description in {2}"
#: src/rougail/output_doc/__init__.py:68
msgid "the domain name in web address can be only a hostname"
msgstr ""
#: src/rougail/output_doc/collect.py:190
msgid "depends on an undocumented variable"
#: src/rougail/output_doc/__init__.py:75
msgid "can be range of port"
msgstr ""
#: src/rougail/output_doc/collect.py:208
msgid "is \"{0}\""
#: src/rougail/output_doc/__init__.py:76
msgid "can have the protocol"
msgstr ""
#: src/rougail/output_doc/collect.py:213
msgid "is accessible"
#: src/rougail/output_doc/__init__.py:77
msgid "port 0 is allowed"
msgstr ""
#: src/rougail/output_doc/collect.py:215
msgid "is defined"
#: src/rougail/output_doc/__init__.py:78
msgid "ports 1 to 1023 are allowed"
msgstr ""
#: src/rougail/output_doc/collect.py:220
msgid "hasn't the value \"{0}\""
#: src/rougail/output_doc/__init__.py:79
msgid "ports 1024 to 49151 are allowed"
msgstr ""
#: src/rougail/output_doc/collect.py:222
msgid "has the value \"{0}\""
#: src/rougail/output_doc/__init__.py:80
msgid "ports greater than 49152 are allowed"
msgstr ""
#: src/rougail/output_doc/collect.py:226
msgid "is {0}"
#: src/rougail/output_doc/__init__.py:125
msgid "mandatory"
msgstr ""
#: src/rougail/output_doc/collect.py:228
msgid "when the variable {{0}} {0}."
#: src/rougail/output_doc/__init__.py:126
msgid "hidden"
msgstr ""
#: src/rougail/output_doc/collect.py:256
msgid "the value of the variable {0} if it is defined"
#: src/rougail/output_doc/__init__.py:127
msgid "disabled"
msgstr ""
#: src/rougail/output_doc/collect.py:258
msgid "the value of the variable {0}"
#: src/rougail/output_doc/__init__.py:128
msgid "unique"
msgstr ""
#: src/rougail/output_doc/collect.py:277
msgid "(from an undocumented variable)"
#: src/rougail/output_doc/__init__.py:129
msgid "auto modified"
msgstr ""
#: src/rougail/output_doc/collect.py:283
msgid "{0} (from an undocumented variable)"
#: src/rougail/output_doc/__init__.py:163
msgid "Variables for \"{0}\""
msgstr ""
#: src/rougail/output_doc/collect.py:287
msgid "the value of an undocumented variable"
#: src/rougail/output_doc/__init__.py:180
msgid "Variables"
msgstr ""
#: src/rougail/output_doc/collect.py:322
msgid "when the identifier is \"{0}\""
msgstr ""
#: src/rougail/output_doc/collect.py:324
msgid "when the identifier is not \"{0}\""
msgstr ""
#: src/rougail/output_doc/collect.py:329
msgid "the value of the identifier"
msgstr ""
#: src/rougail/output_doc/collect.py:426
msgid "This family contains lists of variable blocks"
msgstr ""
#: src/rougail/output_doc/collect.py:430
msgid "This family builds families dynamically"
msgstr ""
#: src/rougail/output_doc/collect.py:440
msgid "This family is a namespace"
msgstr ""
#: src/rougail/output_doc/collect.py:489
msgid "Example"
msgstr ""
#: src/rougail/output_doc/collect.py:492
msgid "Examples"
msgstr ""
#: src/rougail/output_doc/collect.py:498
msgid "Tag"
msgstr ""
#: src/rougail/output_doc/collect.py:501
msgid "Tags"
msgstr ""
#: src/rougail/output_doc/collect.py:597
msgid "text based with regular expressions \"{0}\""
msgstr ""
#: src/rougail/output_doc/collect.py:601
#: src/rougail/output_doc/tabular/six_columns.py:83
msgid "Validator"
msgstr ""
#: src/rougail/output_doc/collect.py:604
msgid "Validators"
msgstr ""
#: src/rougail/output_doc/collect.py:613
msgid "Choices"
msgstr ""
#: src/rougail/output_doc/collect.py:665
msgid "Default"
msgstr ""
#: src/rougail/output_doc/collect.py:675
msgid "No attribute \"description\" for \"{0}\" in {1}"
msgstr ""
#: src/rougail/output_doc/config.py:54
msgid "duplicated level rougail-output-doc for {0} \"{1}\": {2} and {3}"
msgstr ""
#: src/rougail/output_doc/config.py:60
msgid "duplicated name \"{0}\" in rougail-output-doc"
msgstr ""
#: src/rougail/output_doc/config.py:116
msgid "is true if doc is activate"
msgstr ""
#: src/rougail/output_doc/config.py:119
msgid "generate documentation from structural files"
msgstr ""
#: src/rougail/output_doc/config.py:120
msgid "The structural files contain all the information related to the variables. This output generates the documentation for all or some of these variables."
msgstr ""
#: src/rougail/output_doc/config.py:125
msgid "if \"step.output\" is not doc"
msgstr ""
#: src/rougail/output_doc/config.py:128
msgid "the output format of the generated documentation"
msgstr ""
#: src/rougail/output_doc/config.py:137
msgid "generate document with this tabular model"
msgstr ""
#: src/rougail/output_doc/config.py:138
msgid "The variables are documented with a tabular view. A template selection allows you to choose the content of each column."
msgstr ""
#: src/rougail/output_doc/config.py:146
msgid "\"_.output_format\" in json is not compatible with this variable"
msgstr ""
#: src/rougail/output_doc/config.py:153
msgid "generated content"
msgstr ""
#: src/rougail/output_doc/config.py:154
msgid "You can generate three type of document. All variables (\"variables\"), an example file in YAML format (\"example\") or change log (\"changelog\")."
msgstr ""
#: src/rougail/output_doc/config.py:167
msgid "\"_.output_format\" in json is not compatible with changelog or example \"_.contents\""
msgstr ""
#: src/rougail/output_doc/config.py:170
msgid "Starting title level"
msgstr ""
#: src/rougail/output_doc/config.py:175
msgid "Modify values to document all variables"
msgstr ""
#: src/rougail/output_doc/config.py:176
msgid "To document leadership or dynamic family variables, it is sometimes necessary to generate values, which can change the values in the configuration. Be careful if you reuse this configuration."
msgstr ""
#: src/rougail/output_doc/config.py:180
msgid "Display documentation in console always with true color terminal"
msgstr ""
#: src/rougail/output_doc/config.py:187
msgid "The variables in this family are documented in another file"
msgstr ""
#: src/rougail/output_doc/config.py:188
msgid "If you separate the variables into different files, the links between the variables will break. Therefore, you must define different filenames for the files containing these variables."
msgstr ""
#: src/rougail/output_doc/config.py:192
msgid "This file contains child variables of the family"
msgstr ""
#: src/rougail/output_doc/config.py:196
msgid "Name of the file"
msgstr ""
#: src/rougail/output_doc/config.py:200
msgid "Documentation a structural type"
msgstr ""
#: src/rougail/output_doc/config.py:204
msgid "Variables and changelog documentation"
msgstr ""
#: src/rougail/output_doc/config.py:209
msgid "if \"_.output_format\" is json or \"_.contents\" hasn't variables or changelog"
msgstr ""
#: src/rougail/output_doc/config.py:212
msgid "Do not add families in documentation"
msgstr ""
#: src/rougail/output_doc/config.py:217
msgid "add command line informations in documentation"
msgstr ""
#: src/rougail/output_doc/config.py:222
msgid "add environment variable informations in documentation"
msgstr ""
#: src/rougail/output_doc/config.py:227
msgid "Environment variables prefix name"
msgstr ""
#: src/rougail/output_doc/config.py:234
msgid "should only use uppercase characters"
msgstr ""
#: src/rougail/output_doc/config.py:239
msgid "if \"main_namespace\" is not set or \"_.with_environment\" is false"
msgstr ""
#: src/rougail/output_doc/config.py:242
msgid "Changelog documentation"
msgstr ""
#: src/rougail/output_doc/config.py:247
msgid "if changelog in not in \"_.contents\""
msgstr ""
#: src/rougail/output_doc/config.py:250
msgid "Previous description file in JSON format"
msgstr ""
#: src/rougail/output_doc/config.py:251
msgid "To generate the changelog, you need to compare the old list of variables (in json format) with the current variables."
msgstr ""
#: src/rougail/output_doc/config.py:255
msgid "Examples configuration"
msgstr ""
#: src/rougail/output_doc/config.py:260
msgid "if example is not in \"_.contents\""
msgstr ""
#: src/rougail/output_doc/config.py:263
msgid "add description of variables and families when generate examples"
msgstr ""
#: src/rougail/output_doc/config.py:268
msgid "Comment in examples starts at column"
msgstr ""
#: src/rougail/output_doc/doc.py:58
msgid "{0} is not set as step.output"
msgstr ""
#: src/rougail/output_doc/example.py:61
#: src/rougail/output_doc/__init__.py:187
msgid "Example with mandatory variables not filled in"
msgstr ""
#: src/rougail/output_doc/example.py:63
msgid "Example with all variables modifiable"
msgstr ""
#: src/rougail/output_doc/output/asciidoc.py:156
#: src/rougail/output_doc/output/console.py:234
#: src/rougail/output_doc/output/gitlab.py:53
msgid "Informations"
msgstr ""
#: src/rougail/output_doc/output/console.py:75
msgid "cannot find Python module Rich, please install it!"
msgstr ""
#: src/rougail/output_doc/tabular/five_columns.py:72
msgid "Access control"
msgstr ""
#: src/rougail/output_doc/tabular/four_columns.py:64
msgid "Type"
msgstr ""
#: src/rougail/output_doc/tabular/three_columns.py:54
msgid "Default value"
msgstr ""
#: src/rougail/output_doc/tabular/two_columns.py:56
msgid "Variable"
msgstr ""
#: src/rougail/output_doc/tabular/two_columns.py:58
msgid "Description"
msgstr ""
#: src/rougail/output_doc/utils.py:204
msgid "Command line"
msgstr ""
#: src/rougail/output_doc/utils.py:222
msgid "Environment variable"
msgstr ""
#: src/rougail/output_doc/utils.py:545
msgid "Path"
msgstr ""
#: src/rougail/output_doc/utils.py:555
msgid "Identifiers"
msgstr ""
#: src/rougail/output_doc/utils.py:849 src/rougail/output_doc/utils.py:858
#: src/rougail/output_doc/utils.py:864 src/rougail/output_doc/utils.py:870
#: src/rougail/output_doc/utils.py:874
#: src/rougail/output_doc/__init__.py:493
msgid "(default)"
msgstr ""
#: src/rougail/output_doc/utils.py:1211
msgid "{0}: {1}"
#: src/rougail/output_doc/__init__.py:498
msgid "Choices"
msgstr ""
#: src/rougail/output_doc/__init__.py:501
msgid "Default"
msgstr ""
#: src/rougail/output_doc/__init__.py:559
msgid "the value of the variable \"{0}\""
msgstr ""
#: src/rougail/output_doc/__init__.py:564
#: src/rougail/output_doc/__init__.py:566
msgid "value of the {0}"
msgstr ""
#: src/rougail/output_doc/__init__.py:638
#: src/rougail/output_doc/__init__.py:651
msgid "Example"
msgstr ""
#: src/rougail/output_doc/__init__.py:649
msgid "Examples"
msgstr ""

View file

@ -4,7 +4,7 @@ requires = ["flit_core >=3.8.0,<4"]
[project]
name = "rougail.output_doc"
version = "0.2.0a47"
version = "0.1.0"
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
readme = "README.md"
description = "Rougail output doc"
@ -13,10 +13,11 @@ license = {file = "LICENSE"}
classifiers = [
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
"Programming Language :: Python",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: 3",
"Operating System :: OS Independent",
"Natural Language :: English",
@ -24,9 +25,8 @@ classifiers = [
]
dependencies = [
"rougail-base > 1.1,<2",
"rougail ~= 1.1,<2",
"tabulate ~= 0.9.0",
"rich ~= 13.9.3",
]
[project.urls]
@ -37,9 +37,5 @@ name = "cz_conventional_commits"
tag_format = "$version"
version_scheme = "pep440"
version_provider = "pep621"
version_files = [
"src/rougail/output_doc/__version__.py",
"pyproject.toml:version"
]
update_changelog_on_bump = true
#update_changelog_on_bump = true
changelog_merge_prerelease = true

View file

@ -1,6 +1,7 @@
#!/usr/bin/env python3
"""
Silique (https://www.silique.fr)
Copyright (C) 2024-2026
Copyright (C) 2024
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
@ -15,9 +16,671 @@ details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
# FIXME si plusieurs example dont le 1er est none tester les autres : tests/dictionaries/00_8test_none
from tiramisu import Calculation
from tiramisu.error import display_list
import tabulate as tabulate_module
from tabulate import tabulate
from warnings import warn
from typing import Optional
from .doc import RougailOutputDoc
from .__version__ import __version__
from rougail.error import display_xmlfiles
from rougail import RougailConfig, Rougail, CONVERT_OPTION
from rougail.object_model import PROPERTY_ATTRIBUTE
from .config import OutPuts
from .i18n import _
ENTER = "\n\n"
DocTypes = {
"domainname": {
"params": {
"allow_startswith_dot": _("the domain name can starts by a dot"),
"allow_without_dot": _("the domain name can be a hostname"),
"allow_ip": _("the domain name can be an IP"),
"allow_cidr_network": _("the domain name can be network in CIDR format"),
},
},
"number": {
"params": {
"min_number": _("the minimum value is {0}"),
"max_number": _("the maximum value is {0}"),
},
},
"ip": {
"msg": "IP",
"params": {
"cidr": _("IP must be in CIDR format"),
"private_only": _("private IP are allowed"),
"allow_reserved": _("reserved IP are allowed"),
},
},
"hostname": {
"params": {
"allow_ip": _("the host name can be an IP"),
},
},
"web_address": {
"params": {
"allow_ip": _("the domain name in web address can be an IP"),
"allow_without_dot": _(
"the domain name in web address can be only a hostname"
),
},
},
"port": {
"params": {
"allow_range": _("can be range of port"),
"allow_protocol": _("can have the protocol"),
"allow_zero": _("port 0 is allowed"),
"allow_wellknown": _("ports 1 to 1023 are allowed"),
"allow_registred": _("ports 1024 to 49151 are allowed"),
"allow_private": _("ports greater than 49152 are allowed"),
},
},
}
ROUGAIL_VARIABLE_TYPE = (
"https://rougail.readthedocs.io/en/latest/variable.html#variables-types"
)
class RougailOutputDoc:
def __init__(
self,
*,
config: "Config" = None,
rougailconfig: RougailConfig = None,
**kwarg,
):
if rougailconfig is None:
rougailconfig = RougailConfig
if rougailconfig["step.output"] != "doc":
rougailconfig["step.output"] = "doc"
if rougailconfig["step.output"] != "doc":
raise Exception("doc is not set as step.output")
self.rougailconfig = rougailconfig
outputs = OutPuts().get()
output = self.rougailconfig["doc.output_format"]
if output not in outputs:
raise Exception(
f'cannot find output "{output}", available outputs: {list(outputs)}'
)
if config is None:
rougail = Rougail(self.rougailconfig)
rougail.converted.plugins.append("output_doc")
config = rougail.get_config()
self.conf = config
self.conf.property.setdefault(frozenset({"advanced"}), "read_write", "append")
self.conf.property.read_write()
self.conf.property.remove("cache")
self.dynamic_paths = {}
self.formater = outputs[output]()
self.level = self.rougailconfig["doc.title_level"]
# self.property_to_string = [('mandatory', 'obligatoire'), ('hidden', 'cachée'), ('disabled', 'désactivée'), ('unique', 'unique'), ('force_store_value', 'modifié automatiquement')]
self.property_to_string = [
("mandatory", _("mandatory")),
("hidden", _("hidden")),
("disabled", _("disabled")),
("unique", _("unique")),
("force_store_value", _("auto modified")),
]
def run(self):
print(self.gen_doc())
def gen_doc(self):
tabulate_module.PRESERVE_WHITESPACE = True
examples_mini = {}
examples_all = {}
return_string = self.formater.header()
if self.rougailconfig["main_namespace"]:
for namespace in self.conf.unrestraint.list():
name = namespace.name()
examples_mini[name] = {}
examples_all[name] = {}
doc = (
self._display_doc(
self.display_families(
namespace,
self.level + 1,
examples_mini[name],
examples_all[name],
),
[],
)
+ "\n"
)
if not examples_mini[name]:
del examples_mini[name]
if not examples_all[name]:
del examples_all[name]
else:
return_string += self.formater.title(
_('Variables for "{0}"').format(namespace.name()), self.level
)
return_string += doc
else:
doc = (
self._display_doc(
self.display_families(
self.conf.unrestraint,
self.level + 1,
examples_mini,
examples_all,
),
[],
)
+ "\n"
)
if examples_all:
return_string += self.formater.title(_("Variables"), self.level)
return_string += doc
if not examples_all:
return ""
if self.rougailconfig["doc.with_example"]:
if examples_mini:
return_string += self.formater.title(
_("Example with mandatory variables not filled in"), self.level
)
return_string += self.formater.yaml(examples_mini)
if examples_all:
return_string += self.formater.title(
"Example with all variables modifiable", self.level
)
return_string += self.formater.yaml(examples_all)
return return_string
def _display_doc(self, variables, add_paths):
return_string = ""
for variable in variables:
typ = variable["type"]
path = variable["path"]
if path in add_paths:
continue
if typ == "family":
return_string += variable["title"]
return_string += self._display_doc(variable["objects"], add_paths)
else:
for idx, path in enumerate(variable["paths"]):
if path in self.dynamic_paths:
paths_msg = display_list(
[
self.formater.bold(path_)
for path_ in self.dynamic_paths[path]["paths"]
],
separator="or",
)
variable["objects"][idx][0] = variable["objects"][idx][
0
].replace("{{ ROUGAIL_PATH }}", paths_msg)
identifiers = self.dynamic_paths[path]["identifiers"]
description = variable["objects"][idx][1][0]
if "{{ identifier }}" in description:
if description.endswith("."):
description = description[:-1]
comment_msg = self.to_phrase(
display_list(
[
description.replace(
"{{ identifier }}",
self.formater.italic(identifier),
)
for identifier in identifiers
],
separator="or",
add_quote=True,
)
)
variable["objects"][idx][1][0] = comment_msg
variable["objects"][idx][1] = self.formater.join(
variable["objects"][idx][1]
)
return_string += (
self.formater.table(
tabulate(
variable["objects"],
headers=self.formater.table_header(
["Variable", "Description"]
),
tablefmt=self.formater.name,
)
)
+ "\n\n"
)
add_paths.append(path)
return return_string
def is_hidden(self, child):
properties = child.property.get(uncalculated=True)
for hidden_property in ["hidden", "disabled", "advanced"]:
if hidden_property in properties:
return True
return False
def display_families(
self,
family,
level,
examples_mini,
examples_all,
):
variables = []
for child in family.list():
if self.is_hidden(child):
continue
if not child.isoptiondescription():
if child.isfollower() and child.index() != 0:
# only add to example
self.display_variable(
child,
examples_mini,
examples_all,
)
continue
path = child.path(uncalculated=True)
if child.isdynamic():
self.dynamic_paths.setdefault(
path, {"paths": [], "identifiers": []}
)["paths"].append(child.path())
self.dynamic_paths[path]["identifiers"].append(
child.identifiers()[-1]
)
if not variables or variables[-1]["type"] != "variables":
variables.append(
{
"type": "variables",
"objects": [],
"path": path,
"paths": [],
}
)
variables[-1]["objects"].append(
self.display_variable(
child,
examples_mini,
examples_all,
)
)
variables[-1]["paths"].append(path)
else:
name = child.name()
if child.isleadership():
examples_mini[name] = []
examples_all[name] = []
else:
examples_mini[name] = {}
examples_all[name] = {}
variables.append(
{
"type": "family",
"title": self.display_family(
child,
level,
),
"path": child.path(uncalculated=True),
"objects": self.display_families(
child,
level + 1,
examples_mini[name],
examples_all[name],
),
}
)
if not examples_mini[name]:
del examples_mini[name]
if not examples_all[name]:
del examples_all[name]
return variables
def display_family(
self,
family,
level,
):
if family.name() != family.description(uncalculated=True):
title = f"{family.description(uncalculated=True)}"
else:
warning = f'No attribute "description" for family "{family.path()}" in {display_xmlfiles(family.information.get("dictionaries"))}'
warn(warning)
title = f"{family.path()}"
isdynamic = family.isdynamic(only_self=True)
if isdynamic:
identifiers = family.identifiers(only_self=True)
if "{{ identifier }}" in title:
title = display_list(
[
title.replace(
"{{ identifier }}", self.formater.italic(identifier)
)
for identifier in identifiers
],
separator="or",
add_quote=True,
)
msg = self.formater.title(title, level)
subparameter = []
self.manage_properties(family, subparameter)
if subparameter:
msg += self.subparameter_to_string(subparameter) + ENTER
comment = []
self.subparameter_to_parameter(subparameter, comment)
if comment:
msg += "\n".join(comment) + ENTER
help = self.to_phrase(family.information.get("help", ""))
if help:
msg += "\n" + help + ENTER
if family.isleadership():
# help = "Cette famille contient des listes de bloc de variables."
help = "This family contains lists of variable blocks."
msg += "\n" + help + ENTER
if isdynamic:
identifiers = family.identifiers(only_self=True, uncalculated=True)
if isinstance(identifiers, Calculation):
identifiers = self.to_string(family, "dynamic")
if isinstance(identifiers, list):
for idx, val in enumerate(identifiers):
if not isinstance(val, Calculation):
continue
identifiers[idx] = self.to_string(family, "dynamic", f"_{idx}")
identifiers = self.formater.list(identifiers)
# help = f"Cette famille construit des familles dynamiquement.\n\n{self.formater.bold('Identifiers')}: {identifiers}"
help = f"This family builds families dynamically.\n\n{self.formater.bold('Identifiers')}: {identifiers}"
msg += "\n" + help + ENTER
return msg
def manage_properties(
self,
variable,
subparameter,
):
properties = variable.property.get(uncalculated=True)
for mode in self.rougailconfig["modes_level"]:
if mode in properties:
subparameter.append((self.formater.prop(mode), None, None))
break
for prop, msg in self.property_to_string:
if prop in properties:
subparameter.append((self.formater.prop(msg), None, None))
elif variable.information.get(f"{prop}_calculation", False):
subparameter.append(
(self.formater.prop(msg), msg, self.to_string(variable, prop))
)
def subparameter_to_string(
self,
subparameter,
):
subparameter_str = ""
for param in subparameter:
if param[1]:
subparameter_str += f"_{param[0]}_ "
else:
subparameter_str += f"{param[0]} "
return subparameter_str[:-1]
def subparameter_to_parameter(
self,
subparameter,
comment,
):
for param in subparameter:
if not param[1]:
continue
msg = param[2]
comment.append(f"{self.formater.bold(param[1].capitalize())}: {msg}")
def to_phrase(self, msg):
if not msg:
return ""
msg = str(msg).strip()
if not msg.endswith("."):
msg += "."
return msg[0].upper() + msg[1:]
def display_variable(
self,
variable,
examples_mini,
examples_all,
):
if variable.isdynamic():
parameter = ["{{ ROUGAIL_PATH }}"]
else:
parameter = [f"{self.formater.bold(variable.path())}"]
subparameter = []
description = variable.description(uncalculated=True)
comment = [self.to_phrase(description)]
help_ = self.to_phrase(variable.information.get("help", ""))
if help_:
comment.append(help_)
self.type_to_string(
variable,
subparameter,
comment,
)
self.manage_properties(
variable,
subparameter,
)
if variable.ismulti():
multi = not variable.isfollower() or variable.issubmulti()
else:
multi = False
if multi:
subparameter.append((self.formater.prop("multiple"), None, None))
if subparameter:
parameter.append(self.subparameter_to_string(subparameter))
if variable.name() == description:
warning = f'No attribute "description" for variable "{variable.path()}" in {display_xmlfiles(variable.information.get("dictionaries"))}'
warn(warning)
default = self.get_default(
variable,
comment,
)
default_in_choices = False
if variable.information.get("type") == "choice":
choices = variable.value.list(uncalculated=True)
if isinstance(choices, Calculation):
choices = self.to_string(variable, "choice")
if isinstance(choices, list):
for idx, val in enumerate(choices):
if not isinstance(val, Calculation):
if default is not None and val == default:
choices[idx] = str(val) + "" + _("(default)")
default_in_choices = True
continue
choices[idx] = self.to_string(variable, "choice", f"_{idx}")
choices = self.formater.list(choices)
comment.append(f'{self.formater.bold(_("Choices"))}: {choices}')
# choice
if default is not None and not default_in_choices:
comment.append(f"{self.formater.bold(_('Default'))}: {default}")
self.manage_exemples(
multi,
variable,
examples_all,
examples_mini,
comment,
)
self.subparameter_to_parameter(subparameter, comment)
self.formater.columns(parameter, comment)
return [self.formater.join(parameter), comment]
def get_default(
self,
variable,
comment,
):
if variable.information.get("fake_default", False):
default = None
else:
default = variable.value.get(uncalculated=True)
if default in [None, []]:
return
if isinstance(default, Calculation):
default = self.to_string(variable, "default")
if isinstance(default, list):
for idx, val in enumerate(default):
if not isinstance(val, Calculation):
continue
default[idx] = self.to_string(variable, "default", f"_{idx}")
default = self.formater.list(default)
return default
def to_string(
self,
variable,
prop,
identifier="",
):
calculation_type = variable.information.get(
f"{prop}_calculation_type{identifier}", None
)
if not calculation_type:
raise Exception(
f"cannot find {prop}_calculation_type{identifier} information, do you have declare doc has a plugins?"
)
calculation = variable.information.get(f"{prop}_calculation{identifier}")
if calculation_type == "jinja":
if calculation is not True:
values = self.formater.to_string(calculation)
else:
values = "depends on a calculation"
warning = f'"{prop}" is a calculation for {variable.path()} but has no description in {display_xmlfiles(variable.information.get("dictionaries"))}'
warn(warning)
elif calculation_type == "variable":
if prop in PROPERTY_ATTRIBUTE:
values = self.formater.to_string(calculation)
else:
values = _('the value of the variable "{0}"').format(calculation)
elif calculation_type == "identifier":
if prop in PROPERTY_ATTRIBUTE:
values = self.formater.to_string(calculation)
else:
values = _("value of the {0}").format(calculation_type)
else:
values = _("value of the {0}").format(calculation_type)
if not values.endswith("."):
values += "."
return values
def type_to_string(
self,
variable,
subparameter,
comment,
):
variable_type = variable.information.get("type")
doc_type = DocTypes.get(variable_type, {"params": {}})
subparameter.append(
(
self.formater.link(
doc_type.get("msg", variable_type), ROUGAIL_VARIABLE_TYPE
),
None,
)
)
option = variable.get()
validators = []
for param, msg in doc_type["params"].items():
value = option.impl_get_extra(f"_{param}")
if value is None:
value = option.impl_get_extra(param)
if value is not None and value is not False:
validators.append(msg.format(value))
valids = [
name
for name in variable.information.list()
if name.startswith("validators_calculation_type_")
]
if valids:
for idx in range(len(valids)):
validators.append(
self.to_string(
variable,
"validators",
f"_{idx}",
)
)
if validators:
if len(validators) == 1:
comment.append(f'{self.formater.bold("Validator")}: ' + validators[0])
else:
comment.append(
f'{self.formater.bold("Validators")}:'
+ self.formater.list(validators)
)
def manage_exemples(
self,
multi,
variable,
examples_all,
examples_mini,
comment,
):
example_mini = None
example_all = None
example = variable.information.get("examples", None)
if example is None:
example = variable.information.get("test", None)
default = variable.value.get()
if isinstance(example, tuple):
example = list(example)
mandatory = "mandatory" in variable.property.get(uncalculated=True)
if example:
if not multi:
example = example[0]
title = _("Example")
if mandatory:
example_mini = example
example_all = example
else:
if mandatory:
example_mini = "\n - example"
example_all = example
len_test = len(example)
example = self.formater.list(example)
if len_test > 1:
title = _("Examples")
else:
title = _("Example")
comment.append(f"{self.formater.bold(title)}: {example}")
elif default not in [None, []]:
example_all = default
else:
example = CONVERT_OPTION.get(variable.information.get("type"), {}).get(
"example", None
)
if example is None:
example = "xxx"
if multi:
example = [example]
if mandatory:
example_mini = example
example_all = example
if variable.isleader():
if example_mini is not None:
for mini in example_mini:
examples_mini.append({variable.name(): mini})
if example_all is not None:
for mall in example_all:
examples_all.append({variable.name(): mall})
elif variable.isfollower():
if example_mini is not None:
for idx in range(0, len(examples_mini)):
examples_mini[idx][variable.name()] = example_mini
if example_all is not None:
for idx in range(0, len(examples_all)):
examples_all[idx][variable.name()] = example_all
else:
if example_mini is not None:
examples_mini[variable.name()] = example_mini
examples_all[variable.name()] = example_all
RougailOutput = RougailOutputDoc

View file

@ -1 +0,0 @@
__version__ = "0.2.0a47"

View file

@ -1,6 +1,7 @@
"""
"""Annotate for documentation
Silique (https://www.silique.fr)
Copyright (C) 2024-2026
Copyright (C) 2024
distribued with GPL-2 or later license
@ -19,14 +20,12 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
from typing import Union
from re import compile
from rougail.utils import undefined, PROPERTY_ATTRIBUTE
from tiramisu import undefined
from rougail.annotator.variable import Walk
from rougail.output_doc.i18n import _
from rougail.convert.object_model import (
from rougail.i18n import _
from rougail.error import DictConsistencyError
from rougail.object_model import (
Calculation,
JinjaCalculation,
VariableCalculation,
@ -35,15 +34,10 @@ from rougail.convert.object_model import (
IdentifierPropertyCalculation,
InformationCalculation,
IndexCalculation,
NamespaceCalculation,
CONVERT_OPTION,
PROPERTY_ATTRIBUTE,
)
try:
from rougail.user_data_risotto.utils import RisottoCalculation
except ImportError as err:
RisottoCalculation = None
class Annotator(Walk):
"""Annotate for documentation"""
@ -53,147 +47,113 @@ class Annotator(Walk):
def __init__(
self,
objectspace,
*args, # pylint: disable=unused-argument
**kwargs,
*args,
) -> None:
if not objectspace.paths:
return
self.objectspace = objectspace
if "force_default_value" in kwargs:
self.default_values = kwargs["force_default_value"]
else:
self.default_values = self.objectspace.rougailconfig["doc.default_values"]
self.regexp_description_get_paths = None
self.populate_family()
self.populate_variable()
def populate_family(self) -> None:
"""Set doc, path, ... to family"""
for family in self.get_families():
self.add_informations_from_properties(family)
if family.type == "dynamic":
self.force_default_value_in_identifier_variable(family)
self.calculation_to_information(
family.path,
"dynamic",
family.dynamic,
family.version,
)
path = family.path
if path in self.objectspace.forced_descriptions:
self.objectspace.informations.add(
path,
"forced_description",
True,
)
def force_default_value_in_identifier_variable(self, family) -> None:
if not self.default_values:
return
if not isinstance(family.dynamic, list):
self._force_default_value_in_suffix_variable(family, family.dynamic)
else:
for value in family.dynamic:
self._force_default_value_in_suffix_variable(
family, value, return_a_list=False
)
def _force_default_value_in_suffix_variable(
self,
family,
value,
*,
return_a_list=True,
) -> None:
"""For dynamic we must have values to document it"""
if not isinstance(value, Calculation):
return
value_added = False
if isinstance(value, (VariableCalculation, VariablePropertyCalculation)):
variable = self.objectspace.paths.get_with_dynamic(
value.variable,
family.path,
value.version,
value.namespace,
value.xmlfiles,
)[0]
if variable and not variable.default:
values = self.add_examples_values(variable)
value_added = True
if not value_added:
default_values = ["example"]
if not return_a_list:
default_values = default_values[0]
value.default_values = default_values
def add_examples_values(self, variable) -> list:
"""Check examples or test information to define examples values in a variable"""
def get_examples_values(self, variable):
values = self.objectspace.informations.get(variable.path).get("examples", None)
if not values:
values = self.objectspace.informations.get(variable.path).get("test", None)
if isinstance(values, tuple):
values = list(values)
if values:
variable.default = list(values)
else:
variable.default = [CONVERT_OPTION[variable.type]["example"]]
self.objectspace.informations.add(
variable.path, "default_value_makes_sense", False
)
return values
def add_default_value(
self,
family,
value,
*,
inside_list=False,
) -> None:
if isinstance(value, Calculation):
default_values = "example"
if not inside_list:
default_values = [default_values]
if isinstance(value, (VariableCalculation, VariablePropertyCalculation)):
variable, identifier = self.objectspace.paths.get_with_dynamic(
value.variable,
value.path_prefix,
family.path,
value.version,
value.namespace,
value.xmlfiles,
)
values = self.get_examples_values(variable)
if values:
if inside_list:
default_values = list(values)
else:
default_values = values
value.default_values = default_values
def populate_family(self) -> None:
"""Set doc, path, ... to family"""
for family in self.get_families():
self.objectspace.informations.add(
family.path, "dictionaries", family.xmlfiles
)
self.convert_variable_property(family)
if family.type != "dynamic":
continue
if not isinstance(family.dynamic, list):
self.add_default_value(family, family.dynamic)
else:
for value in family.dynamic:
self.add_default_value(family, value, inside_list=True)
self.calculation_to_information(
family.path,
"dynamic",
family.dynamic,
family.version,
)
def populate_variable(self) -> None:
"""convert variables"""
for variable in self.get_variables():
if variable.type == "symlink":
continue
path = variable.path
if variable.type == "choice":
self.calculation_to_information(
path,
variable.path,
"choice",
variable.choices,
variable.version,
)
self.manage_test(variable)
default = variable.default
if default is None and path in self.objectspace.default_multi:
default = self.objectspace.default_multi[path]
self.calculation_to_information(
path,
variable.path,
"default",
default,
variable.default,
variable.version,
)
self.calculation_to_information(
path,
variable.path,
"validators",
variable.validators,
variable.version,
)
self.add_informations_from_properties(variable)
if path in self.objectspace.forced_descriptions:
self.objectspace.informations.add(
path,
"forced_description",
True,
)
if variable.path in self.objectspace.leaders and not variable.default:
values = self.get_examples_values(variable)
if values:
variable.default = list(values)
else:
variable.default = [CONVERT_OPTION[variable.type]["example"]]
self.objectspace.informations.add(variable.path, "fake_default", True)
self.objectspace.informations.add(
variable.path, "dictionaries", variable.xmlfiles
)
self.convert_variable_property(variable)
def manage_test(self, variable):
# for version 1.0 and 1.1
values = self.objectspace.informations.get(variable.path).get("examples", None)
if values:
return
values = self.objectspace.informations.get(variable.path).get("test", None)
if values:
self.objectspace.informations.add(variable.path, "examples", values)
def add_informations_from_properties(
def convert_variable_property(
self,
variable: dict,
) -> None:
"""convert properties"""
for prop in PROPERTY_ATTRIBUTE:
for prop in ["hidden", "disabled", "mandatory"]:
prop_value = getattr(variable, prop, None)
if not prop_value:
continue
@ -203,8 +163,6 @@ class Annotator(Walk):
prop_value,
variable.version,
)
if isinstance(prop_value, Calculation):
prop_value.default_values = False
def calculation_to_information(
self,
@ -213,183 +171,76 @@ class Annotator(Walk):
values,
version: str,
):
"""tranform calculation to an information"""
one_is_calculation = False
if not isinstance(values, list):
if not isinstance(values, Calculation):
return
one_is_calculation = True
datas = self.calculation_to_string(path, prop, values, version)
else:
datas = []
self._calculation_to_information(
path,
prop,
values,
version,
)
if isinstance(values, list):
for idx, val in enumerate(values):
data = self.calculation_to_string(path, prop, val, version)
if data is None:
continue
if "type" in data or "description" in data:
one_is_calculation = True
datas.append(data)
if one_is_calculation and datas:
self.objectspace.informations.add(
path,
f"{prop}_calculation",
datas,
)
self._calculation_to_information(
path,
prop,
val,
version,
identifier=f"_{idx}",
)
def calculation_to_string(
def _calculation_to_information(
self,
path: str,
prop: str,
values,
version: str,
*,
identifier: str = "",
):
if not isinstance(values, Calculation):
return {"value": values}
if values.description:
if not self.regexp_description_get_paths:
self.regexp_description_get_paths = compile('"(.*?)"')
index = 0
val_description = values.description
variables = []
for r_path in self.regexp_description_get_paths.findall(val_description):
variable, identifiers = self.objectspace.paths.get_with_dynamic(
r_path,
path,
values.version,
values.namespace,
values.xmlfiles,
)
if variable:
val_description = val_description.replace(f'"{r_path}"', f'{{{index}}}')
v = {"path": variable.path, "description": variable.description}
if identifiers:
v["identifiers"] = [identifiers]
v["identifier_type"] = "many"
variables.append(v)
index += 1
description = {"description": True,
"value": val_description,
}
if variables:
description["variables"] = variables
else:
description = {}
return
values_calculation = True
if isinstance(values, JinjaCalculation):
if not description:
description["value"] = True
description["type"] = "jinja"
return description
if isinstance(values, (VariableCalculation, VariablePropertyCalculation)):
variable_path = self.get_path_from_variable(values, version, path)
if not description:
value = self.calculation_to_information_variable(
variable_path, values, prop, version, path
if values.description:
values_calculation = values.description
values_calculation_type = "jinja"
elif isinstance(values, (VariableCalculation, VariablePropertyCalculation)):
values_calculation = values.variable
paths = self.objectspace.paths
if version != "1.0" and paths.regexp_relative.search(values_calculation):
calculation_path = paths.get_full_path(
values_calculation,
path,
)
if value is None:
return
description["value"] = value
description["type"] = "variable"
description["ori_path"] = variable_path
description["optional"] = values.optional
description["propertyerror"] = values.propertyerror
return description
if isinstance(values, InformationCalculation):
# FIXME
return self.calculation_to_information_information(values, version, path)
if isinstance(values, IdentifierPropertyCalculation):
self.when_to_condition(values, description)
description["type"] = "identifier"
return description
if isinstance(values, IdentifierCalculation):
description["type"] = "identifier"
return description
if isinstance(values, IndexCalculation):
if not description:
description["value"] = True
description["type"] = "index"
return description
if isinstance(values, NamespaceCalculation):
if not description:
description["value"] = True
description["type"] = "namespace"
return description
if RisottoCalculation and isinstance(values, RisottoCalculation):
# FIXME
if not description:
description["value"] = True
description["type"] = "risotto"
return description
raise Exception(f'unknown calculation {type(values)} "{values}"')
def calculation_to_information_variable(
self, variable_path: str, values, prop: str, version: str, path: str
) -> str:
variable, identifiers = self.objectspace.paths.get_with_dynamic(
variable_path,
if prop in PROPERTY_ATTRIBUTE:
if values.when is not undefined:
values_calculation = f'when the variable "{calculation_path}" has the value "{values.when}"'
elif values.when_not is not undefined:
values_calculation = f'when the variable "{calculation_path}" hasn\'t the value "{values.when_not}"'
else:
values_calculation = f'when the variable "{calculation_path}" has the value "True"'
else:
values_calculation = calculation_path
values_calculation_type = "variable"
elif isinstance(values, InformationCalculation):
values_calculation_type = "information"
elif isinstance(values, (IdentifierCalculation, IdentifierPropertyCalculation)):
if version != "1.0" and prop in PROPERTY_ATTRIBUTE:
if values.when is not undefined:
values_calculation = f'when the identifier is "{values.when}"'
elif values.when_not is not undefined:
values_calculation = (
f'when the identifier is not "{values.when_not}"'
)
values_calculation_type = "identifier"
elif isinstance(values, IndexCalculation):
values_calculation_type = "index"
self.objectspace.informations.add(
path,
values.version,
values.namespace,
values.xmlfiles,
f"{prop}_calculation_type{identifier}",
values_calculation_type,
)
self.objectspace.informations.add(
path,
f"{prop}_calculation{identifier}",
values_calculation,
)
if not variable or (
isinstance(values, VariableCalculation) and values.optional and not variable
):
return None
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
def when_to_condition(self, values, values_calculation):
if values.when_not is not undefined:
values_calculation["type"] = "condition"
values_calculation["value"] = values.when_not
values_calculation["condition"] = "when_not"
elif values.when is not undefined:
values_calculation["type"] = "condition"
values_calculation["value"] = values.when
values_calculation["condition"] = "when"
elif values.propertyerror == "transitive":
values_calculation["type"] = "transitive"
else:
values_calculation["type"] = "condition"
values_calculation["value"] = True
values_calculation["condition"] = "when"
def calculation_to_information_information(
self, values, version: str, path: str
) -> Union[str, bool]:
values_calculation = {
"type": "information",
"information": values.information,
}
if values.variable:
variable = self.objectspace.paths.get_with_dynamic(
values.variable,
path,
values.version,
values.namespace,
values.xmlfiles,
)[0]
if not variable:
return None
values_calculation["path"] = variable.path
return values_calculation
def get_path_from_variable(self, values, version: str, path: str) -> str:
variable_path = values.variable
paths = self.objectspace.paths
if version != "1.0" and paths.regexp_relative.search(variable_path):
variable_path = paths.get_full_path(
variable_path,
path,
)
elif version == "1.0" and "{{ suffix }}" in variable_path:
variable_path = variable_path.replace("{{ suffix }}", "{{ identifier }}")
return variable_path

View file

@ -1,191 +0,0 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2025-2026
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
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from pathlib import Path
from json import loads
from .config import OutPuts
from .i18n import _
from .utils import calc_path
class Changelog: # pylint: disable=no-member,too-few-public-methods
"""Build changelog"""
def gen_doc_changelog(self):
"""Return changelog"""
self.level = self.rougailconfig["doc.title_level"]
self.previous_json_file = self.rougailconfig["doc.changelog.previous_json_file"]
with Path(self.previous_json_file).open() as outfh:
previous_doc = loads(outfh.read())
self.load()
self._added_variables = []
self._modified_variables = []
self._removed_variables = []
informations = self.informations
self.formatter.options()
self.parser(previous_doc, informations)
return self.display()
def parser(self, previous_families, new_families):
done = []
for element in list(previous_families) + list(new_families):
if element in done:
continue
done.append(element)
previous = previous_families.get(element)
new = new_families.get(element)
if not previous:
if new["type"] == "variable":
self._added_variables.append(new)
else:
self.parser({}, new["children"])
elif not new:
if previous["type"] == "variable":
if "identifiers" in previous:
for identifiers in previous["identifiers"]:
self._removed_variables.append(
calc_path(
previous["path"],
formatter=self.formatter,
identifiers=identifiers,
)
)
else:
self._removed_variables.append(
calc_path(previous["path"], formatter=self.formatter)
)
else:
self.parser(previous["children"], {})
elif previous["type"] != new["type"]:
if previous["type"] == "variable":
if "identifiers" in previous:
for identifiers in previous["identifiers"]:
self._removed_variables.append(
calc_path(
previous["path"],
formatter=self.formatter,
identifiers=identifiers,
)
)
else:
self._removed_variables.append(
calc_path(previous["path"], formatter=self.formatter)
)
self.parser({}, new["children"])
else:
self._added_variables.append(new)
self.parser(previous["children"], {})
elif previous["type"] != "variable":
self.parser(previous["children"], new["children"])
else:
modified_attributes = {}
for prop in set(previous) | set(new):
prop_previous = previous.get(prop, [])
prop_new = new.get(prop, [])
if prop_previous != prop_new:
name = None
if (
isinstance(prop_previous, dict)
and "values" in prop_previous
):
name = prop_previous["name"]
local_prop_previous = prop_previous = prop_previous[
"values"
]
if not isinstance(prop_previous, list):
if prop == "default":
local_prop_previous = [prop_previous]
else:
local_prop_previous = prop_previous = [
prop_previous
]
elif isinstance(prop_previous, list):
local_prop_previous = prop_previous
else:
local_prop_previous = [prop_previous]
if isinstance(prop_new, dict) and "values" in prop_new:
name = prop_new["name"]
prop_new = prop_new["values"]
if not isinstance(prop_new, list):
prop_new = [prop_new]
if isinstance(prop_new, list):
prop_new = prop_new.copy()
else:
prop_new = [prop_new]
if isinstance(prop_previous, list):
prop_previous = [
p for p in prop_previous if p not in prop_new
]
elif prop_previous in prop_new:
prop_new.remove(prop_previous)
prop_previous = []
else:
prop_previous = [prop_previous]
prop_new = [p for p in prop_new if p not in local_prop_previous]
if prop_previous not in [None, []] or prop_new not in [
None,
[],
]:
modified_attributes[prop] = (name, prop_previous, prop_new)
if not modified_attributes:
continue
self._modified_variables.append((new, modified_attributes))
def display(self) -> str:
lst = []
if self._added_variables:
if len(self._added_variables) == 1:
title = _("New variable")
else:
title = _("New variables")
for add in self._added_variables:
self.formatter.variable_to_string(add)
lst.append(self.formatter.title(title, self.level))
lst.append(self.formatter.tabular())
end = self.formatter.end_family(self.level)
if end:
lst.append(end)
if self._modified_variables:
if len(self._modified_variables) == 1:
title = _("Modified variable")
else:
title = _("Modified variables")
for mod, modified_attributes in self._modified_variables:
self.formatter.variable_to_string(mod, modified_attributes)
lst.append(self.formatter.title(title, self.level))
lst.append(self.formatter.tabular())
end = self.formatter.end_family(self.level)
if end:
lst.append(end)
if self._removed_variables:
if len(self._removed_variables) == 1:
title = _("Deleted variable")
else:
title = _("Deleted variables")
lst.append(self.formatter.title(title, self.level))
lst.append(self.formatter.list(self._removed_variables, inside_tabular=False))
end = self.formatter.end_family(self.level)
if end:
lst.append(end)
if not lst:
return ""
return self.formatter._run(
lst,
self.level,
dico_is_already_treated=True,
)

View file

@ -1,764 +0,0 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2024-2026
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
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from warnings import warn
from typing import Optional
from tiramisu import Calculation, groups
from tiramisu.error import display_list, PropertiesOptionError
from tiramisu.config import get_common_path
from rougail.tiramisu import display_xmlfiles
from rougail.utils import PROPERTY_ATTRIBUTE
from rougail.error import VariableCalculationDependencyError, RougailWarning, ExtensionError
from .utils import dump, to_phrase, calc_path, add_dot, doc_path
from .i18n import _
HIDDEN_PROPERTIES = [
"hidden",
"disabled",
]
DISABLED_PROPERTIES = ["disabled"]
class _ToString:
def _to_string(
self,
child,
prop,
do_not_raise=False,
):
calculation = child.information.get(f"{prop}_calculation", None)
if not calculation:
if do_not_raise:
return None
raise ExtensionError(
_(
'cannot find "{0}_calculation" information, '
"do you have annotate this configuration?"
).format(prop)
)
if isinstance(calculation, list):
values = []
for cal in calculation:
value = self._calculation_to_string(child, cal, prop)
if value is not None:
values.append(value)
return values
ret = self._calculation_to_string(child, calculation, prop, inside_list=False)
if isinstance(ret, list) and len(ret) == 1:
return ret[0]
return ret
def _calculation_to_string(self, child, calculation, attribute_type, inside_list=True):
if calculation.get("description", False):
values = calculation.copy()
if self.document_a_type and "variables" in values:
for variable in list(values["variables"]):
variable["path"] = doc_path(variable["path"], self.document_a_type)
if not inside_list:
values["description"] = add_dot(values.pop("value"))
else:
values["description"] = values.pop("value")
elif "type" not in calculation:
values = calculation["value"]
if isinstance(values, str) and not inside_list:
values = add_dot(values)
elif calculation["type"] == "jinja":
values = self._calculation_jinja_to_string(
child, calculation, attribute_type
)
if isinstance(values, str) and not inside_list:
values = add_dot(values)
elif calculation["type"] == "variable":
values = self._calculation_variable_to_string(
child, calculation, attribute_type
)
if not inside_list:
if isinstance(values, str):
values = add_dot(values)
elif isinstance(values, dict) and "message" in values:
values["message"] = add_dot(values["message"])
elif calculation["type"] == "identifier":
values = self._calculation_identifier_to_string(
child, calculation, attribute_type
)
if isinstance(values, str) and not inside_list:
values = add_dot(values)
elif calculation["type"] == "information":
if "path" in calculation:
msg = _(
'the value of the information "{0}" of the variable {{0}}'
).format(calculation["information"])
if not inside_list:
msg = add_dot(msg)
variable = self.true_config.unrestraint.option(calculation["path"])
values = self._calculation_with_variable(child, variable, calculation, msg)
else:
values = _('the value of the global information "{0}"').format(
calculation["information"]
)
if not inside_list:
values = add_dot(values)
else:
values = _("the value of the {0}").format(calculation["type"])
if not inside_list:
values = add_dot(values)
return values
def _calculation_jinja_to_string(self, child, calculation, attribute_type):
if calculation["value"] is not True:
values = calculation["value"]
else:
values = _("depends on a calculation")
warning = _(
'"{0}" is a calculation for {1} but has no description in {2}'
).format(
attribute_type,
doc_path(child.path(uncalculated=True), self.document_a_type),
display_xmlfiles(child.information.get("ymlfiles")),
)
warn(
warning,
RougailWarning,
)
return values
def _calculation_variable_to_string(self, child, calculation, attribute_type):
if attribute_type in PROPERTY_ATTRIBUTE:
func = self._calculation_variable_to_string_property
else:
func = self._calculation_variable_to_string_not_property
return func(child, calculation, attribute_type)
def _calculation_variable_to_string_property(self, child, informations, prop):
condition = informations["value"]
variable_path = condition["path"]
values = []
option = self.true_config.option(variable_path)
if option.isdynamic():
variables = self._get_annotation_variable(
child, option, condition.get("identifiers")
)
else:
option = self.true_config.option(variable_path)
try:
is_inaccessible = self.is_inaccessible_user_data(option)
except AttributeError as err:
if err.code != "option-not-found":
raise err from err
is_inaccessible = True
if is_inaccessible:
variables = [[None, None, None, None]]
else:
description = option.description(uncalculated=True)
variables = [[variable_path, description, None, "one"]]
for cpath, description, identifiers, identifier_type in variables:
if not cpath:
# we cannot access to this variable, so try with permissive
if condition["type"] == "transitive":
value = None
else:
value = condition["value"]
option = self.true_config.forcepermissive.option(variable_path)
try:
variable_value = self._get_unmodified_default_value(option)
except PropertiesOptionError as err:
if informations["propertyerror"] is True:
raise err from err
if informations["propertyerror"] == "transitive":
return True
return False
except VariableCalculationDependencyError:
values.append(_("depends on an undocumented variable"))
continue
except AttributeError as err:
return informations.get("default", False)
if condition["type"] == "transitive":
return True
if prop in HIDDEN_PROPERTIES and not self.only_disabled:
condition_type = condition["condition"]
if (
condition_type == "when"
and value == variable_value
or condition_type == "when_not"
and value != variable_value
):
# always "prop"
return True
return False
if condition["type"] == "transitive":
submsg = _('is "{0}"').format(prop)
else:
condition_type = condition["condition"]
conditions = []
if not informations["propertyerror"]:
conditions.append(_("is accessible"))
if informations["optional"]:
conditions.append(_("is defined"))
value = condition["value"]
if not isinstance(value, str):
value = dump(value)
if condition_type == "when_not":
conditions.append(_('hasn\'t the value "{0}"').format(value))
else:
conditions.append(_('has the value "{0}"').format(value))
submsg = display_list(conditions, sort=False)
if informations["propertyerror"] == "transitive":
submsg = display_list(
[_("is {0}").format(prop), submsg], separator="or", sort=False
)
msg = _('when the variable {{0}} {0}.').format(submsg)
path_obj = {
"path": doc_path(variable_path, self.document_a_type),
}
if identifiers:
path_obj["identifiers"] = identifiers
path_obj["identifier_type"] = identifier_type
values.append(
{
"message": msg,
"path": path_obj,
"description": description,
}
)
if len(values) == 1:
return values[0]
return values
def _calculation_variable_to_string_not_property(
self, child, calculation, attribute_type
):
variable = self.true_config.unrestraint.option(calculation["value"]["path"])
if calculation["optional"]:
try:
variable.get()
except AttributeError:
return None
true_msg = _('the value of the variable {0} if it is defined')
else:
true_msg = _('the value of the variable {0}')
return self._calculation_with_variable(child, variable, calculation["value"], true_msg)
def _calculation_with_variable(self, child, variable, calculation, msg):
if not variable.isdynamic():
func = self._calculation_normal_with_variable
else:
func = self._calculation_dynamic_variable_with_variable
return func(child, variable, calculation, msg)
def _calculation_normal_with_variable(
self, child, variable, obj, msg
):
isfollower = not variable.isoptiondescription() and variable.isfollower()
if not isfollower and self.is_inaccessible_user_data(variable):
uncalculated = variable.value.default(uncalculated=True)
if uncalculated and not isinstance(uncalculated, Calculation):
if isinstance(uncalculated, list):
return {
"submessage": _("(from an undocumented variable)"),
"values": uncalculated,
}
else:
if not isinstance(uncalculated, str):
uncalculated = dump(uncalculated)
msg = _("{0} (from an undocumented variable)").format(
uncalculated
)
else:
msg = _("the value of an undocumented variable")
try:
description = variable.description(uncalculated=True)
except AttributeError:
description = path
return {
"message": msg,
"path": obj,
"description": description,
}
def _calculation_dynamic_variable_with_variable(
self, child, variable, obj, msg
):
values = []
for path, description, identifiers, identifier_type in self._get_annotation_variable(
child, variable, obj.get("identifiers")
):
variable = self.true_config.option(path)
path_obj = {
"path": doc_path(path, self.document_a_type),
}
if identifiers:
path_obj["identifiers"] = identifiers
path_obj["identifier_type"] = identifier_type
values.append(
self._calculation_normal_with_variable(
child, variable, path_obj, msg
)
)
return values
def _calculation_identifier_to_string(self, child, calculation, attribute_type):
if attribute_type in PROPERTY_ATTRIBUTE:
if calculation["condition"] == "when":
return _('when the identifier is "{0}"').format(calculation["value"])
if calculation["condition"] == "when_not":
return _('when the identifier is not "{0}"').format(
calculation["value"]
)
return True
else:
return _("the value of the identifier")
def _get_annotation_variable(self, child, variable, ori_identifiers):
path = variable.path(uncalculated=True)
description = variable.description(uncalculated=True)
child_path = child.path(uncalculated=True)
if ori_identifiers:
if path.count("{{ identifier }}") == len(ori_identifiers):
identifier_type = "one"
elif "{{ identifier }}" in path[len(get_common_path(child_path, path)):]:
identifier_type = "outside"
else:
identifier_type = "inside"
else:
common_path = get_common_path(child_path, path)
if common_path and "{{ identifier }}" in path[len(common_path):]:
identifier_type = "outside"
else:
identifier_type = "inside"
if ori_identifiers:
if None in ori_identifiers:
all_identifiers = self.true_config.option(
calc_path(path, identifiers=ori_identifiers)
).identifiers()
else:
all_identifiers = [ori_identifiers]
for identifiers in all_identifiers:
cpath = calc_path(path, identifiers=identifiers)
if variable.isdynamic():
yield path, description, [identifiers.copy()], identifier_type
else:
yield path, description, None, identifier_type
else:
if variable.isdynamic():
yield path, description, variable.identifiers().copy(), identifier_type
else:
yield path, description, None, identifier_type
class Collect(_ToString):
only_disabled = False
def collect_families(self, family) -> dict:
informations = {}
for child in family.list(uncalculated=True):
if child.type(only_self=True) == "symlink" or (
not child.isdynamic() and self.is_inaccessible_user_data(child)
):
# do not document symlink option or inacesssible variable
# (dynamic variable could be accessible only in one context)
continue
if child.isoptiondescription():
func = self.collect_family
else:
func = self.collect_variable
func(child, informations)
return informations
def collect_family(self, family, informations: dict) -> None:
family_type = self._get_family_type(family)
family_informations = self._collect_family(family, family_type)
if family_informations is False:
return
sub_informations = self.collect_families(family)
if not sub_informations:
# a family without subfamily/subvariable
return
name = family.name(uncalculated=True)
informations[name] = {
"type": family_type,
"informations": family_informations,
"children": sub_informations,
}
def _get_family_type(self, family) -> str:
if self.support_namespace and family.group_type() is groups.namespace:
return "namespace"
if family.isleadership():
return "leadership"
if family.isdynamic(only_self=True):
return "dynamic"
return "family"
def _collect_family(
self,
family,
family_type,
*,
with_identifier: bool = True,
current_identifier_only: bool = False,
) -> dict:
path = family.path(uncalculated=True)
informations = {}
if not self._collect(family, informations, family_type=family_type):
return False, []
if family_type == "leadership":
informations.setdefault("help", []).append(
_("This family contains lists of variable blocks")
)
elif family_type == "dynamic":
informations.setdefault("help", []).append(
_("This family builds families dynamically")
)
if with_identifier:
identifier = self._to_string(family, "dynamic", do_not_raise=True)
if identifier is None:
identifier = family.identifiers(only_self=True)
if not isinstance(identifier, list):
identifier = [identifier]
informations["identifier"] = identifier
elif family_type == "namespace":
informations.setdefault("help", []).append(_("This family is a namespace"))
return informations
def collect_variable(
self,
child,
informations: dict,
*,
only_one=False,
) -> Optional[dict]:
name = child.name(uncalculated=True)
sub_informations = {}
if not self._collect_variable(
child,
sub_informations,
):
return None
informations[name] = sub_informations
if child.isleader():
return sub_informations
return None
def _collect_variable(
self,
child,
informations: dict,
):
if not self._collect(child, informations):
return False
informations["type"] = "variable"
default = self._set_default(
child,
informations,
)
self._parse_type(
child,
informations,
)
if child.ismulti():
multi = not child.isfollower() or child.issubmulti()
else:
multi = False
if multi:
informations["multiple"] = True
examples = child.information.get("examples", None)
if examples is None:
examples = child.information.get("test", None)
if examples is not None:
if len(examples) == 1:
name = _("Example")
values = examples[0]
else:
name = _("Examples")
values = list(examples)
informations["examples"] = {"name": name, "values": values}
tags = child.information.get("tags", None)
if tags:
if len(tags) == 1:
name = _("Tag")
values = tags[0]
else:
name = _("Tags")
values = list(tags)
informations["tags"] = {
"name": name,
"values": values,
}
alternative_name = child.information.get("alternative_name", None)
if alternative_name:
informations["alternative_name"] = alternative_name
return True
def _collect(
self,
child,
informations: dict,
*,
family_type: str = None,
):
display, properties = self._get_properties(child, informations)
if not display:
return False
path = child.path(uncalculated=True)
informations["path"] = doc_path(path, self.document_a_type)
if path != informations["path"]:
informations["full_path"] = path
informations["name"] = child.name(uncalculated=True)
description = self._get_description(child, family_type)
if description is not None:
informations["description"] = description
help_ = child.information.get("help", None)
if help_:
informations["help"] = [to_phrase(help_)]
if "properties" in informations:
informations["properties"].extend(properties)
else:
informations["properties"] = properties
properties = child.property.get(uncalculated=True)
for mode in self.modes_level:
if mode not in properties:
continue
informations["mode"] = mode
break
if child.isdynamic():
informations["identifiers"] = []
informations["identifier_type"] = "many"
if child.has_identifiers():
identifiers = child.identifiers()
else:
identifiers = [child.identifiers()]
for identifier in identifiers:
cpath = calc_path(path, identifiers=identifier)
child_identifier = self.true_config.option(cpath)
if not self.is_inaccessible_user_data(child_identifier):
informations["identifiers"].append(identifier)
if not informations["identifiers"]:
# doc.default_values is false
informations["identifiers"] = [["example"]]
return True
def _parse_type(
self,
child,
informations,
):
variable_type = child.information.get("type")
doc_type = self.convert_option.get(variable_type, {"params": {}})
informations["variable_type"] = doc_type.get("msg", variable_type)
# extra parameters for types
option = child.get()
validators = []
if "params" in doc_type:
for param, msg in doc_type["params"].items():
value = option.impl_get_extra(f"_{param}")
if value is None:
value = option.impl_get_extra(param)
if value is not None and value is not False:
if isinstance(value, set):
value = list(value)
if isinstance(value, list):
value = display_list(value, add_quote=True)
if "doc" in msg:
validators.append(msg["doc"].format(value))
else:
validators.append(msg["description"].format(value))
# get validation information from annotator
calculation = child.information.get("validators_calculation", None)
if calculation:
validators.extend(
self._to_string(
child,
"validators",
)
)
if variable_type == "regexp":
validators.append(
_('text based with regular expressions "{0}"').format(child.pattern())
)
if validators:
if len(validators) == 1:
key = _("Validator")
validators = validators[0]
else:
key = _("Validators")
informations["validators"] = {"name": key, "values": validators}
if variable_type == "choice":
choices = self._to_string(child, "choice", do_not_raise=True)
if choices is None:
choices = child.value.list(uncalculated=True)
for idx, val in enumerate(choices):
if isinstance(val, Calculation):
choices[idx] = self._to_string(child, "choice", f"_{idx}")
informations["choices"] = {"name": _("Choices"), "values": choices}
def _get_properties(
self,
child,
child_informations,
):
informations = []
properties = child.property.get(uncalculated=True)
if "not_for_commandline" in properties:
child_informations["not_for_commandline"] = True
for prop, translated_prop in self.property_to_string:
annotation = False
if child.information.get(f"{prop}_calculation", False):
annotation = self._to_string(child, prop)
if not self.only_disabled and annotation is None and prop in HIDDEN_PROPERTIES:
return False, []
if annotation is True and prop in DISABLED_PROPERTIES:
return False, []
if not annotation:
continue
elif prop not in properties:
# this property is not in the variable so, do not comment it
continue
elif not self.only_disabled and prop in HIDDEN_PROPERTIES:
return False, []
elif prop in DISABLED_PROPERTIES:
return False, []
prop_obj = {
"type": "property",
"name": translated_prop,
"ori_name": prop,
"access_control": prop in HIDDEN_PROPERTIES,
}
if annotation:
prop_obj["annotation"] = annotation
informations.append(prop_obj)
return True, informations
def _set_default(
self,
child,
informations,
):
default = self._to_string(child, "default", do_not_raise=True)
if default is None and child.information.get("default_value_makes_sense", True):
default_ = child.value.default(uncalculated=True)
if not isinstance(default_, Calculation):
default = default_
if default == []:
default = None
if default is not None:
informations["default"] = {"name": _("Default"), "values": default}
def _get_description(self, child, family_type):
if child.information.get("forced_description", False):
if (
child.isoptiondescription()
or not child.isfollower()
or not child.index()
):
# all variables must have description but display error only for first slave
msg = _('No attribute "description" for "{0}" in {1}').format(
child.path(uncalculated=True),
display_xmlfiles(child.information.get("ymlfiles")),
)
warn(
msg,
RougailWarning,
)
return None
var_type = "variable" if family_type is None else "family"
return self._convert_description(
child.description(uncalculated=True), var_type
)
def _convert_description(self, description, type_):
return to_phrase(description, type_)
def is_inaccessible_user_data(self, child):
"""If family is not accessible in read_write mode (to load user_data),
do not comment this family
"""
properties = child.property.get(uncalculated=True)
if self.only_disabled:
hidden_properties = DISABLED_PROPERTIES
else:
hidden_properties = HIDDEN_PROPERTIES
for hidden_property in hidden_properties:
if hidden_property in properties:
return True
calculation = child.information.get(f"{hidden_property}_calculation", None)
if calculation:
calculation_type = calculation.get("type")
if (
calculation_type == "variable"
and calculation["value"]["type"] == "condition"
):
condition = calculation["value"]
variable = self.true_config.forcepermissive.option(
condition["path"]
)
try:
variable.value.get()
except AttributeError:
variable = None
if variable and self.is_inaccessible_user_data(
variable
):
try:
variable_value = self._get_unmodified_default_value(
variable
)
except VariableCalculationDependencyError:
pass
else:
condition_type = condition["condition"]
value = condition["value"]
if self.calc_condition_when(
condition_type, value, variable_value
):
return True
elif calculation_type == "identifier":
if self.calc_condition_when(
calculation["condition"],
calculation["value"],
child.identifiers()[-1],
):
return True
if not child.isoptiondescription():
for hidden_property in self.disabled_modes:
if hidden_property in properties:
return True
return False
def calc_condition_when(self, condition, value, current_value):
return (condition == "when" and value == current_value) or (
condition == "when_not" and value != current_value
)
def _get_unmodified_default_value(self, child):
calculation = child.information.get(f"default_calculation", None)
if not calculation:
return child.value.get()
if calculation["type"] == "variable":
variable = self.true_config.forcepermissive.option(
calculation["value"]["path"]
)
if variable and self.is_inaccessible_user_data(variable):
return self._get_unmodified_default_value(variable)
raise VariableCalculationDependencyError()

View file

@ -1,6 +1,8 @@
"""
Config file for Rougail-doc
Silique (https://www.silique.fr)
Copyright (C) 2024-2026
Copyright (C) 2024
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
@ -18,49 +20,27 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
from pathlib import Path
from rougail.utils import load_modules
from .i18n import _
ROUGAIL_VARIABLE_TYPE = (
"https://rougail.readthedocs.io/en/latest/variable.html#variables-types"
)
OUTPUTS = None
TABULARS = None
def get_outputs_or_tabulars(type_) -> None:
"""Load all outputs or tabulars"""
module_name = f"rougail.output_doc.{type_}"
def get_outputs() -> None:
module_name = "rougail.doc.output"
outputs = {}
names = []
for path in (Path(__file__).parent / type_).iterdir():
for path in (Path(__file__).parent / "output").iterdir():
name = path.name
if not name.endswith(".py") or name.endswith("__.py"):
continue
module = load_modules(module_name + "." + name[:-3], str(path))
if type_ == "output":
if "Formatter" not in dir(module):
continue
obj_class = module.Formatter
elif type_ == "tabular":
if "Tabular" not in dir(module):
continue
obj_class = module.Tabular
level = obj_class.level
module = load_modules(module_name + "." + name, str(path))
if "Formater" not in dir(module):
continue
level = module.Formater.level
if level in outputs:
raise ImportError(
_(
'duplicated level rougail-output-doc for {0} "{1}": {2} and {3}'
).format(type_, level, obj_class.name, outputs[level].name)
raise Exception(
f'duplicated level rougail-doc for output "{level}": {module.Formater.name} and {outputs[level].name}'
)
if obj_class.name in names:
raise ImportError(
_('duplicated name "{0}" in rougail-output-doc').format(obj_class.name)
)
names.append(obj_class.name)
outputs[level] = obj_class
outputs[module.Formater.level] = module.Formater
return {outputs[level].name: outputs[level] for level in sorted(outputs)}
@ -72,205 +52,46 @@ class OutPuts: # pylint: disable=R0903
) -> None:
global OUTPUTS
if OUTPUTS is None:
OUTPUTS = get_outputs_or_tabulars("output")
OUTPUTS = get_outputs()
def get(self) -> dict:
"""Get all outputs"""
return OUTPUTS
class Tabulars: # pylint: disable=R0903
"""Transformations applied on a object instance"""
def __init__(
self,
) -> None:
global TABULARS
if TABULARS is None:
TABULARS = get_outputs_or_tabulars("tabular")
def get(self) -> dict:
"""Get all tabulars"""
return TABULARS
def get_rougail_config(
*,
backward_compatibility=True, # pylint: disable=unused-argument
backward_compatibility=True,
) -> dict:
"""Get documentation for output_doc modules"""
outputs = list(OutPuts().get())
output_format_default = outputs[0]
tabulars = list(Tabulars().get())
tabular_default = tabulars[0]
rougail_options = f"""
cli:
read_write:
redefine: true
exists: true
type: boolean
default:
jinja: |-
{{{{ step.output is not propertyerror and step.output == "doc" }}}}
description: {_('is true if doc is activate')}
rougail_options = """
doc:
description: {_('generate documentation from structural files')}
help: {_('The structural files contain all the information related to the variables. This output generates the documentation for all or some of these variables.')}
description: Configuration rougail-doc
disabled:
jinja: |-
{{{{ step.output is propertyerror or step.output != 'doc' }}}}
return_type: boolean
description: {_('if "step.output" is not doc')}
output_format:
description: {_('the output format of the generated documentation')}
alternative_name: do
default: { output_format_default }
choices:
"""
for output in outputs:
rougail_options += f" - {output}\n"
rougail_options += f"""
tabular_template:
description: {_('generate document with this tabular model')}
help: {_("The variables are documented with a tabular view. A template selection allows you to choose the content of each column.")}
alternative_name: dm
default: { tabular_default }
disabled:
jinja: |-
{{{{ _.output_format == 'json' }}}}
return_type: boolean
description: >
{_('"_.output_format" in json is not compatible with this variable')}
choices:
"""
for tabular in tabulars:
rougail_options += f" - {tabular}\n"
rougail_options += f"""
contents:
description: {_('generated content')}
help: {_('You can generate three type of document. All variables ("variables"), an example file in YAML format ("example") or change log ("changelog").')}
alternative_name: dc
choices:
- variables
- example
- changelog
default:
- variables
hidden:
jinja: |-
{{{{ _.output_format == 'json' }}}}
return_type: boolean
description: >
{_('"_.output_format" in json is not compatible with changelog or example "_.contents"')}
type: jinja
jinja: |
{% if step.output != 'doc' %}
disabled
{% endif %}
title_level:
description: {_('Starting title level')}
description: Start title level
alternative_name: dt
default: 1
default_values:
description: {_('Modify values to document all variables')}
help: {_('To document leadership or dynamic family variables, it is sometimes necessary to generate values, which can change the values in the configuration. Be careful if you reuse this configuration.')}
default: true
true_color:
description: {_('Display documentation in console always with true color terminal')}
with_example:
description: Display example in documentation
negative_description: Hide example in documentation
alternative_name: de
default: false
disabled:
variable: _.output_format
when_not: console
other_root_filenames:
description: {_("The variables in this family are documented in another file")}
help: {_("If you separate the variables into different files, the links between the variables will break. Therefore, you must define different filenames for the files containing these variables.")}
type: leadership
root_path:
description: {_("This file contains child variables of the family")}
mandatory: false
root_doc_path:
description: {_("Name of the file")}
mandatory: false
document_a_type:
description: {_("Documentation a structural type")}
default: false
tabulars:
description: {_('Variables and changelog documentation')}
disabled:
jinja: |-
{{{{ step.output is propertyerror or step.output != "doc" or _.output_format == "json" or ("variables" not in _.contents and "changelog" not in _.contents) }}}}
return_type: boolean
description: {_('if "_.output_format" is json or "_.contents" hasn\'t variables or changelog')}
without_family:
description: {_('Do not add families in documentation')}
default: false
alternative_name: df
with_commandline:
description: {_('add command line informations in documentation')}
default: false
commandline: false
with_environment:
description: {_('add environment variable informations in documentation')}
alternative_name: de
default: false
environment_prefix:
description: {_("Environment variables prefix name")}
alternative_name: dv
default: ROUGAIL
validators:
- jinja: |-
{{{{ (_.environment_prefix | upper) != _.environment_prefix }}}}
return_type: boolean
description: {_("should only use uppercase characters")}
disabled:
jinja: |-
{{{{ ___.main_namespace is not defined or ___.main_namespace == none or _.with_environment is false }}}}
return_type: boolean
description: {_('if "main_namespace" is not set or "_.with_environment" is false')}
changelog:
description: {_('Changelog documentation')}
disabled:
jinja: |-
{{{{ step.output is propertyerror or step.output != "doc" or _.output_format == "json" or "changelog" not in _.contents }}}}
return_type: boolean
description: {_('if changelog in not in "_.contents"')}
previous_json_file:
description: {_('Previous description file in JSON format')}
help: {_('To generate the changelog, you need to compare the old list of variables (in json format) with the current variables.')}
alternative_name: dp
examples:
description: {_('Examples configuration')}
disabled:
jinja: |-
{{{{ step.output is propertyerror or step.output != "doc" or "example" not in _.contents }}}}
return_type: boolean
description: {_('if example is not in "_.contents"')}
comment:
description: {_('add description of variables and families when generate examples')}
alternative_name: dx
default: false
comment_column:
description: {_('Comment in examples starts at column')}
default: 30
disabled:
variable: _.comment
when: false
"""
output_format:
description: Generate document in format
alternative_name: do
default: output_format_default
choices:
""".replace(
"output_format_default", output_format_default
)
for output in outputs:
rougail_options += f" - {output}\n"
return {
"name": "doc",
"process": "output",

View file

@ -1,160 +0,0 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2024-2026
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
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from typing import Union
from tiramisu import groups
from rougail.utils import get_properties_to_string
from .config import OutPuts
from .i18n import _
from .collect import Collect
from .changelog import Changelog
from .example import Examples
class RougailOutputDoc(Collect, Examples, Changelog):
"""Rougail Output Doc:
Generate documentation from rougail description files
"""
output_name = "doc"
def __init__(
self,
config: Union["Config", "SubConfig"],
*,
rougailconfig: "RougailConfig" = None,
true_config: "Config" = None,
root_config: "Config" = None,
**kwargs,
):
# Import here to avoid circular import
from rougail.tiramisu import CONVERT_OPTION
self.convert_option = CONVERT_OPTION
if rougailconfig is None:
from rougail import RougailConfig
rougailconfig = RougailConfig
if rougailconfig["step.output"] != self.output_name:
rougailconfig["step.output"] = self.output_name
if rougailconfig["step.output"] != self.output_name:
raise Exception(_("{0} is not set as step.output").format(self.output_name))
self.config = config
if true_config is None:
self.true_config = config
else:
self.true_config = true_config
if root_config is None:
self.root_config = self.true_config
else:
self.root_config = root_config
self.rougailconfig = rougailconfig
self.informations = None
self.formatter = None
super().__init__()
def run(self) -> str:
"""Print documentation in stdout"""
self.load()
self.load_formatter()
return_string = ""
contents = self.rougailconfig["doc.contents"]
if "variables" in contents:
return_string += self.formatter.run(self.informations)
if "example" in contents:
return_string += self.gen_doc_examples()
if "changelog" in contents:
return_string += self.gen_doc_changelog()
return True, return_string
def load_formatter(self) -> str:
output_format = self.rougailconfig["doc.output_format"]
self.formatter = self.outputs[output_format](
self.rougailconfig, support_namespace=self.support_namespace, document_a_type=self.document_a_type
)
def print(self) -> None:
ret, data = self.run()
print(data)
return ret
def load(self):
self.document_a_type = self.rougailconfig["doc.document_a_type"]
self.modes_level = self.rougailconfig["modes_level"]
self.disabled_modes = []
if self.modes_level:
for mode in self.modes_level:
for prop in self.true_config.property.get():
if mode != prop:
continue
self.disabled_modes.append(prop)
try:
groups.namespace
self.support_namespace = True
except AttributeError:
self.support_namespace = False
self.property_to_string = get_properties_to_string()
self.outputs = OutPuts().get()
self.dynamic_paths = {}
if self.config.isoptiondescription():
informations = self.collect_families(self.config.unrestraint)
# from pprint import pprint
# pprint(informations)
else:
informations = {}
self.collect_variable(self.config, informations)
if informations is None:
informations = {}
if self.true_config != self.config:
# build cache for dyn family
root_informations = {}
infos = root_informations
family = self.root_config
for path in self.config.path().split("."):
family = family.option(path)
name = family.name(uncalculated=True)
if family.isoptiondescription():
infos[name] = self.get_root_family(family)
infos = infos[name]["children"]
else:
if name not in informations:
informations = {}
else:
infos[name] = informations[name]
break
else:
infos.update(informations)
informations = root_informations
self.informations = informations
def get_root_family(self, family):
family_type = self._get_family_type(family)
family_informations = self._collect_family(
family,
family_type,
with_identifier=False,
current_identifier_only=False,
)
if family_informations is not False:
return {
"type": family_type,
"informations": family_informations,
"children": {},
}

View file

@ -1,266 +0,0 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2024-2026
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
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from ruamel.yaml import CommentedMap
from ruamel.yaml.representer import RoundTripRepresenter
from tiramisu import Calculation, owners
from .utils import _, dump, to_phrase
# XXX explicit null (see rougail-output-formatter # pylint: disable=W0511
def represent_none(
self, data
): # pylint: disable=missing-function-docstring,unused-argument
return self.represent_scalar("tag:yaml.org,2002:null", "null")
def represent_str(self, data): # pylint: disable=missing-function-docstring
if data == "":
return self.represent_scalar("tag:yaml.org,2002:null", "")
return self.represent_scalar("tag:yaml.org,2002:str", data)
RoundTripRepresenter.add_representer(type(None), represent_none)
RoundTripRepresenter.add_representer(str, represent_str)
# XXX # pylint: disable=W0511
class Examples: # pylint: disable=no-member,too-few-public-methods
"""Build examples"""
def __init__(self):
self.comment_examples = None
self.level = None
self.comment_examples_column = None
def gen_doc_examples(self):
"""Return examples"""
datas = []
config = self._build_example_config()
for only_modified in [True, False]:
results = self._gen_doc_examples(config, only_modified)
if results:
if only_modified:
title = _("Example with mandatory variables not filled in")
else:
title = _("Example with all variables modifiable")
datas.append(self.formatter.title(title, self.level))
datas.append(self.formatter.yaml(dump(results)))
end = self.formatter.end_family(self.level)
if end:
datas.append(end)
return self.formatter.compute(datas)
def _build_example_config(self):
self.comment_examples = self.rougailconfig["doc.examples.comment"]
self.level = self.rougailconfig["doc.title_level"]
if self.comment_examples:
self.comment_examples_column = self.rougailconfig[
"doc.examples.comment_column"
]
config = self.true_config.config.copy()
config.information.set("description_type", "description")
config.property.read_write()
self._set_mandatories(config)
return config
def _gen_doc_examples(self, config, only_modified: bool):
if not only_modified:
self._set_examples(config)
results = CommentedMap()
if self.true_config == self.config:
root_config = config
true_results = None
n_results = None
else:
root_config = config.option(self.config.path())
current_option = self.true_config
subpaths = self.config.path().split(".")
n_results = CommentedMap()
true_results = n_results
if not self.config.isoptiondescription():
subpaths = subpaths[:-1]
for subpath in subpaths:
current_option = current_option.option(subpath)
name = current_option.name()
new_results = CommentedMap()
self._set_description(new_results, name, current_option)
n_results[name] = new_results
n_results = n_results[name]
if only_modified:
dump_type = 'modified'
else:
dump_type = 'all'
if root_config.isoptiondescription():
self._example_parse_family(
root_config.value.get(), results, dump_type
)
else:
self._set_example_value(
results, root_config, root_config.value.get(), dump_type
)
if true_results and results:
n_results.update(results)
else:
true_results = results
return true_results
def _set_mandatories(self, config):
for calculated_too in [False, True]:
for option in config.value.mandatory():
if not calculated_too:
uncalculated = option.value.default(uncalculated=True)
if isinstance(uncalculated, Calculation):
continue
self._set_value_example(option, self._get_an_example(option))
def _get_an_example(self, option):
value = self._get_value_from_example(option)
if value is None:
variable_type = option.information.get("type")
if variable_type == "choice":
value = option.value.list()
if not self._is_multi(option) and value:
if value[0] is not None:
value = value[0]
elif len(value) > 1:
value = value[1]
else:
value = self.convert_option.get(option.information.get("type"), {}).get(
"example"
)
if value is None:
value = "example"
if self._is_multi(option):
value = [value]
if option.isfollower() and option.index() and variable_type == "string":
value += str(option.index())
return value
def _set_examples(self, config):
def _set_example(subconfig):
for option in subconfig:
if option.isoptiondescription():
_set_example(option)
else:
# force examples value + do not let empty value
examples = self._get_value_from_example(option)
if examples is None:
if self._is_multi(option):
if not option.value.get():
examples = self._get_an_example(option)
elif option.value.get() is None:
examples = self._get_an_example(option)
if examples is None:
continue
self._set_value_example(option, examples)
_set_example(config)
self._set_mandatories(config)
def _set_value_example(self, option, value):
if option.isleader():
ori_len = option.value.len()
current_len = len(value)
if ori_len > current_len:
for idx in reversed(range(current_len, ori_len)):
option.value.pop(idx)
option.unrestraint.value.set(value)
def _get_value_from_example(self, option):
examples = option.information.get("examples", None)
if examples is None:
return None
if self._is_multi(option):
examples = list(examples)
else:
examples = examples[0]
return examples
def _is_multi(self, option):
if option.isfollower():
return option.issubmulti()
return option.ismulti()
def _example_parse_family(self, config, results, dump_type):
for option, values in config.items():
if option.isoptiondescription():
if option.isleadership():
subresults = self._example_parse_leadership(values, dump_type)
if subresults:
name = option.name()
results[name] = subresults
self._set_description(results, name, option)
else:
subresults = CommentedMap()
self._example_parse_family(values, subresults, dump_type)
if subresults:
name = option.name()
results[name] = subresults
self._set_description(results, name, option)
else:
self._set_example_value(results, option, values, dump_type)
def _set_example_value(self, results, option, values, dump_type):
if not self._is_valid_owner(option, dump_type):
return
if dump_type == "hidden" and values is None:
values = self._get_an_example(option)
name = option.name()
results[name] = values
self._set_description(results, name, option)
def _is_valid_owner(self, option, dump_type):
if option.type(only_self=True, translation=False) == "symlink":
return False
if dump_type == "all":
return True
if dump_type == "hidden":
return "hidden" in option.property.get()
is_default = option.owner.isdefault()
return (
(dump_type == 'modified' and not is_default and option.owner.get() != owners.forced)
or (dump_type == 'default' and is_default)
)
def _example_parse_leadership(self, values, dump_type):
leadership_iter = iter(values.items())
leader, leader_values = next(leadership_iter)
if not self._is_valid_owner(leader, dump_type):
return None
leadership = [CommentedMap() for idx in range(len(leader_values))]
for idx, value in enumerate(leader_values):
self._set_example_value(leadership[idx], leader, value, dump_type)
for option, value in leadership_iter:
idx = option.index()
self._set_example_value(leadership[idx], option, value, dump_type)
return leadership
def _set_description(self, results, name, option):
if not self.comment_examples or option.information.get(
"forced_description", False
):
return
description = to_phrase(option.description())
if description.endswith("."):
description = description[:-1]
results.yaml_add_eol_comment(
description, name, column=self.comment_examples_column
)

View file

@ -1,6 +1,6 @@
"""Internationalisation utilities
Silique (https://www.silique.fr)
Copyright (C) 2024-2026
Copyright (C) 2024
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
@ -19,8 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
from gettext import translation
from pathlib import Path
t = translation(
"rougail_output_doc", str(Path(__file__).parent / "locale"), fallback=True
)
t = translation("rougail_output_doc", str(Path(__file__).parent / "locale"), fallback=True)
_ = t.gettext

View file

@ -1,6 +1,6 @@
"""Loads output
Silique (https://www.silique.fr)
Copyright (C) 2024-2026
Copyright (C) 2024
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

View file

@ -1,6 +1,6 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2024-2026
Copyright (C) 2024
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
@ -16,148 +16,124 @@ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from io import BytesIO
from typing import List
from ..utils import CommonFormatter, dump
from ..i18n import _
from itertools import chain
from ruamel.yaml import YAML
class Formatter(CommonFormatter):
"""The asciidoc formatter"""
class Formater:
name = "asciidoc"
_tabular_name = "asciidoc"
level = 40
def __init__(self):
self._yaml = YAML()
self._yaml.indent(mapping=2, sequence=4, offset=2)
def header(self):
return ""
def title(
self,
title: str,
level: int,
) -> str:
"""Display family name as a title"""
char = "="
return f"{char * (level + 1)} {title}"
return f"{char * (level + 1)} {title}\n\n"
def yaml(self, dump: dict) -> str:
return f"[,yaml]\n----\n{self.dump(dump)}\n----\n"
def table(self, table: str) -> str:
# add 'a' option in cols to display list
stable = table.split("\n", 1)
return stable[0].replace("<", "a") + "\n" + stable[1]
def link(
self,
comment: str,
link: str,
) -> str:
return f"`{link}[{comment}]`"
def prop(
self,
prop: str,
) -> str:
return f"`{prop}`"
def list(
self,
choices: list,
) -> str:
prefix = "\n\n* "
char = "\n* "
return prefix + char.join([self.dump(choice) for choice in choices])
def is_list(
self,
txt: str,
) -> str:
return txt.startswith("* ")
def columns(
self,
col1: List[str],
col2: List[str],
) -> None:
self.max_line = 0
for params in chain(col1, col2):
for param in params.split("\n"):
self.max_line = max(self.max_line, len(param))
self.max_line += 1
def join(
self,
lst: List[str],
) -> str:
"""Display line in tabular from a list"""
string = ""
previous = ""
for line in lst:
if string:
if self.is_list(previous.split("\n", 1)[-1]):
if self.is_list(previous.split("\n")[-1]):
string += "\n\n"
else:
string += " +\n"
string += line
previous = line
return string
return "\n" + string
def to_string(
self,
text: str,
) -> str:
return text
def table_header(
self,
lst,
):
return lst[0] + " " * (self.max_line - len(lst[0])), lst[1] + " " * (
self.max_line - len(lst[1])
)
def bold(
self,
msg: str,
) -> str:
"""Set a text to bold"""
return f"**{msg}**"
def italic(
self,
msg: str,
) -> str:
"""Set a text to italic"""
return f"__{msg}__"
return f"_{msg}_"
def delete(
self,
msg: str,
) -> str:
"""Set a text to deleted"""
return f"+++{msg}+++"
def underline(
self,
msg: str,
) -> str:
"""Set a text to underline"""
return f"#{msg}#"
def stripped(
self,
text: str,
) -> str:
"""Return stripped text (as help)"""
return text.strip()
def list(
self,
choices: list,
*,
inside_tabular: bool = True,
type_: str = "variable",
with_enter: bool = True,
) -> str:
"""Display a liste of element"""
char = "\n* "
if with_enter:
prefix = "\n\n* "
else:
prefix = char
return prefix + char.join([dump(choice) for choice in choices])
def prop(
self,
prop: str,
italic: bool,
delete: bool,
underline: bool,
) -> str:
"""Display property"""
if italic:
prop = self.italic(prop)
if delete:
prop = self.delete(prop)
if underline:
prop = self.underline(prop)
return f"`{prop}`"
def _yaml(self, _dump: str) -> str:
"""Dump yaml part of documentation"""
return f"[,yaml]\n----\n{_dump}\n----\n"
def tabular(self, with_header: bool = True) -> str:
"""Transform list to a tabular in string format
we change the first line because we want that col has the same width
"""
tabular = super().tabular(with_header)
stable = tabular.split("\n", 1)
return '[cols="1a,1a"]\n' + stable[1]
def link(
self,
comment: str,
link: str,
underline: bool,
) -> str:
"""Add a link"""
if underline:
link = self.underline(link)
return f"`{link}[{comment}]`"
def is_list(
self,
txt: str,
) -> str:
"""verify if a text is a list"""
return txt.strip().startswith("* ")
def family_informations(self) -> str:
info = self.bold(f"🛈 {_('Informations')}")
return f"====\n{info}\n\n"
def end_family_informations(self) -> str:
return f"===="
def family_informations_ends_line(self) -> str:
return " +\n"
def dump(self, dico):
with BytesIO() as ymlfh:
self._yaml.dump(dico, ymlfh)
ret = ymlfh.getvalue().decode("utf-8").strip()
if ret.endswith("..."):
ret = ret[:-3].strip()
return ret

View file

@ -1,235 +0,0 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2024-2026
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
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from typing import List
from ..i18n import _
from rougail.error import ExtensionError
from ..utils import dump, CommonFormatter
try:
from rich.jupyter import JupyterMixin
from rich.segment import Segment
from rich.style import Style
from rich.console import Console, ConsoleOptions, RenderResult
from rich.table import Table
from rich.theme import Theme
from rich.syntax import Syntax
except ModuleNotFoundError:
Console = None
if Console:
class BlockQuote(JupyterMixin):
def __init__(
self,
elements: str,
) -> None:
self.elements = elements
self.border_style = Style(color="blue")
def __rich_console__(
self, console: Console, options: ConsoleOptions
) -> RenderResult:
"""Render blockquote to the console."""
render_options = options.update(width=options.max_width - 4)
lines = console.render_lines(self.elements, render_options)
new_line = Segment("\n")
padding = Segment("", style=self.border_style)
for line in lines:
yield padding
yield from line
yield new_line
class Formatter(CommonFormatter):
"""The console formatter"""
name = "console"
level = 10
enter_tabular = "\n"
titles_color = {
"title1": "bright_cyan underline bold",
"title2": "bright_green underline bold",
"title3": "green1 underline bold",
"title4": "green3 underline bold",
"title5": "dark_green underline bold",
}
def __init__(self, rougailconfig, **kwargs) -> None:
if not Console:
raise ExtensionError(_("cannot find Python module Rich, please install it!"))
self.custom_theme = Theme(self.titles_color)
self.max_line = 0
super().__init__(rougailconfig, **kwargs)
def _run(self, dico: dict, level: int, dico_is_already_treated=False) -> str:
if not dico_is_already_treated:
dico = self.dict_to_dict(dico, level, init=True)
return self.compute(dico)
def compute(self, dico):
if self.rougailconfig["doc.true_color"]:
force_terminal = "xterm-256color"
else:
force_terminal = None
console = Console(
theme=self.custom_theme, force_terminal=force_terminal
)
with console.capture() as capture:
for data in dico:
console.print(data)
console.print()
return capture.get()
def title(
self,
title: str,
level: int,
collapse: bool=True,
) -> str:
"""Display family name as a title"""
space = " " * (2 * (level - 1))
return f"{space}[title{level}]{title}[/title{level}]"
def join(
self,
lst: List[str],
) -> str:
"""Display line in tabular from a list"""
return self.enter_tabular.join(lst)
def bold(
self,
msg: str,
) -> str:
"""Set a text to bold"""
return f"[bold]{msg}[/bold]"
def italic(
self,
msg: str,
) -> str:
"""Set a text to italic"""
return f"[italic]{msg}[/italic]"
def delete(
self,
msg: str,
) -> str:
"""Set a text to delete"""
return f"[strike]{msg}[/strike]"
def underline(
self,
msg: str,
) -> str:
"""Set a text to underline"""
return f"[underline]{msg}[/underline]"
def stripped(
self,
text: str,
) -> str:
"""Return stripped text (as help)"""
return text
def list(
self,
choices: list,
*,
inside_tabular: bool = True,
type_: str = "variable",
with_enter: bool = True,
) -> str:
"""Display a liste of element"""
if type_ == "variable":
if with_enter:
char = first_char = f"{self.enter_tabular}"
else:
first_char = ""
char = f"{self.enter_tabular}{first_char}"
else:
char = first_char = f"\n"
ret = ""
for idx, choice in enumerate(choices):
if not isinstance(choice, str):
choice = dump(choice)
if not idx:
c = first_char
else:
c = char
ret += c + choice
return ret
def prop(
self,
prop: str,
italic: bool,
delete: bool,
underline: bool,
) -> str:
"""Display property"""
if italic:
prop = self.italic(prop)
if delete:
prop = self.delete(prop)
if underline:
prop = self.underline(prop)
prop = f"[reverse][bold] {prop} [/bold][/reverse]"
return prop
def _yaml(self, _dump: str) -> str:
"""Dump yaml part of documentation"""
return Syntax(_dump, "yaml")
def link(
self,
comment: str,
link: str,
underline: bool,
) -> str:
"""Add a link"""
return self.prop(comment, False, False, underline)
# return f"{comment} ({link})"
def columns(
self,
col: List[str],
) -> None:
"""count columns length"""
for line in col:
for l in line.split(self.enter_tabular):
self.max_line = max(self.max_line, len(l) + 1)
def tabular(self, with_header: bool = True) -> str:
"""Transform list to a tabular in string format"""
tabular = Table(show_lines=True)
if with_header:
for column in self.tabular_datas.headers():
tabular.add_column(column, width=self.max_line)
for data in self.tabular_datas.get():
tabular.add_row(*data)
return tabular
def family_informations_ends_line(self) -> str:
return "\n"
def display_family_informations(self, msg) -> str:
msg = ["[blue]" + self.bold(f"🛈 {_('Informations')}") + "\n" + "[/blue]"] + msg
return BlockQuote(self.family_informations_ends_line().join(msg))

View file

@ -1,6 +1,6 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2024-2026
Copyright (C) 2024
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
@ -16,205 +16,112 @@ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from typing import List, Optional
from html import escape
from ..utils import dump, CommonFormatter
from ..i18n import _
from io import BytesIO
from typing import List
from itertools import chain
from ruamel.yaml import YAML
def to_id(path):
# https://www.w3.org/TR/html4/types.html#type-name
return "".join(e if e in ["-", "_", ":", "."] or e.isalnum() else ":" for e in path)
class Formatter(CommonFormatter):
"""The markdown (for github) formatter"""
class Formater:
name = "github"
_tabular_name = "github"
level = 50
enter_tabular = "<br/>"
def __init__(self, rougailconfig, **kwarg) -> None:
self.max_line_variable = 0
self.max_line_description = 0
super().__init__(rougailconfig, **kwarg)
def __init__(self):
self._yaml = YAML()
self._yaml.indent(mapping=2, sequence=4, offset=2)
self.header_setted = False
def header(self):
if self.header_setted:
return ""
self.header_setted = True
return "---\ngitea: none\ninclude_toc: true\n---\n"
def title(
self,
title: str,
level: int,
collapse: bool=True,
) -> str:
"""Display family name as a title"""
char = "#"
return f"{char * level} {title}"
return f"{char * level} {title}\n\n"
def yaml(self, dump):
return f"```yaml\n---\n{self.dump(dump)}\n```\n"
def table(self, table):
return table
def link(
self,
comment: str,
link: str,
) -> str:
return f"[`{comment}`]({link})"
def prop(
self,
prop: str,
) -> str:
return f"`{prop}`"
def list(
self,
choices,
):
prefix = "<br/>- "
char = "<br/>- "
return prefix + char.join([self.dump(choice) for choice in choices])
def is_list(
self,
txt: str,
) -> str:
return txt.startswith("* ")
def columns(
self,
col1: List[str],
col2: List[str],
) -> None:
self.max_line = 0
for params in chain(col1, col2):
for param in params.split("\n"):
self.max_line = max(self.max_line, len(param))
self.max_line += 1
def join(
self,
lst: List[str],
) -> str:
"""Display line in tabular from a list"""
return self.enter_tabular.join(
[l.replace("\n", self.enter_tabular) for l in lst]
return "<br/>".join(lst)
def to_string(
self,
text: str,
) -> str:
return text.strip().replace("\n", "<br/>")
def table_header(self, lst):
return lst[0] + "&nbsp;" * (self.max_line - len(lst[0])), lst[1] + "&nbsp;" * (
self.max_line - len(lst[1])
)
def bold(
self,
msg: str,
) -> str:
"""Set a text to bold"""
return f"**{msg}**"
def italic(
self,
msg: str,
) -> str:
"""Set a text to italic"""
return f"*{msg}*"
def delete(
self,
msg: str,
) -> str:
"""Set a text to deleted"""
return f"~~{msg}~~"
def underline(
self,
msg: str,
) -> str:
"""Set a text to underline"""
return f"<ins>{msg}</ins>"
def stripped(
self,
text: str,
) -> str:
"""Return stripped text (as help)"""
return text.strip().replace("\n", self.enter_tabular)
def list(
self,
choices: list,
*,
inside_tabular: bool = True,
type_: str = "variable",
with_enter: bool = True,
):
"""Display a liste of element"""
end = ""
if type_ == "variable":
if inside_tabular:
if with_enter:
char = first_char = f"{self.enter_tabular}•&nbsp;"
else:
first_char = f"•&nbsp;"
char = f"{self.enter_tabular}{first_char}"
else:
first_char = "- "
char = "\n- "
else:
first_char = f"{self.family_informations_starts_list_first()}- "
char = f"\n{first_char}"
end = self.family_informations_ends_line()
ret = ""
for idx, choice in enumerate(choices):
if not isinstance(choice, str):
choice = dump(choice)
if not idx:
c = first_char
else:
c = char
ret += end + c + choice
def dump(self, dico):
with BytesIO() as ymlfh:
self._yaml.dump(dico, ymlfh)
ret = ymlfh.getvalue().decode("utf-8").strip()
if ret.endswith("..."):
ret = ret[:-3].strip()
return ret
def family_informations_starts_list_first(self):
return self.family_informations_starts_line()
def prop(
self,
prop: str,
italic: bool,
delete: bool,
underline: bool,
) -> str:
"""Display property"""
prop = f"`{prop}`"
if italic:
prop = self.italic(prop)
if delete:
prop = self.delete(prop)
if underline:
prop = self.underline(prop)
return prop
def tabular_header(self, lst):
"""Manage the header of a tabular"""
return lst
return [l + "&nbsp;" * (self.max_line_variable - len(l)) for l in lst]
def _yaml(self, _dump: str) -> str:
"""Dump yaml part of documentation"""
return f"```yaml\n{_dump}\n```"
def link_variable(
self,
path: str,
true_path: str,
description: str,
filename: Optional[str],
) -> str:
name = to_id(true_path)
if filename:
link = f"{filename}#{name}"
else:
link = f"#{name}"
return f'"[{description}]({link})"'
def anchor(
self,
path: str,
true_path: str,
) -> str:
name = to_id(true_path)
return f'<a id="{name}" name="{name}">{path}</a>'
def link(
self,
comment: str,
link: str,
underline: bool,
) -> str:
"""Add a link"""
comment = self.prop(comment, False, False, underline)
return f"[{comment}]({link})"
def columns(
self,
col: List[str],
) -> None:
"""count columns length"""
for line in col:
for l in line.split(self.enter_tabular):
self.max_line_variable = max(self.max_line_variable, len(l) + 1)
self.max_line_description = self.max_line_variable
def to_phrase(self, text: str) -> str:
return escape(text)
def family_informations(self):
start = self.family_informations_starts_line()
return start + "[!NOTE]\n" + start + "\n"
def family_informations_ends_line(self) -> str:
return "\\\n"
def family_informations_starts_line(self) -> str:
return "> "
def display_family_informations(self, msg) -> str:
start = self.family_informations_starts_line()
end = self.family_informations_ends_line()
return self.family_informations() + end.join([start + m for m in msg])

View file

@ -1,103 +0,0 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2025-2026
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
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from typing import List
from .github import Formatter as GithubFormatter
from ..utils import dump
from ..i18n import _
class Formatter(GithubFormatter):
name = "gitlab"
level = 51
format_in_title = False
def title(self,
title: str,
level: int,
collapse: bool=True,
) -> str:
if collapse:
return "<details><summary>" + title + "</summary>"
return super().title(title, level, collapse)
def end_family(self, level, collapse: bool=True):
if collapse:
return "</details>"
return None
def columns(
self,
col: List[str],
) -> None:
pass
def family_informations(self) -> str:
return f"> [!note] 🛈 {_('Informations')}"
def table_header(self, lst):
"""Manage the header of a table"""
return lst
def family_informations_ends_line(self) -> str:
return "\n> "
def family_informations_starts_line(self) -> str:
return "\n> "
# def list(self, *args, **kwargs):
# return super().list(*args, **kwargs) + "\n"
def family_informations_starts_list_first(self):
return ""
def list(
self,
choices: list,
*,
inside_tabular: bool = True,
type_: str = "variable",
with_enter: bool = True,
):
"""Display a liste of element"""
end = ""
if type_ == "variable":
if inside_tabular:
if with_enter:
char = first_char = f"{self.enter_tabular}•&nbsp;"
else:
first_char = f"•&nbsp;"
char = f"{self.enter_tabular}{first_char}"
else:
first_char = "- "
char = "\n- "
else:
first_char = f"{self.family_informations_starts_list_first()}- "
char = f"{first_char}"
end = self.family_informations_ends_line()
ret = ""
for idx, choice in enumerate(choices):
if not isinstance(choice, str):
choice = dump(choice)
if not idx:
c = first_char
else:
c = char
ret += end + c + choice
return ret

View file

@ -1,149 +0,0 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2025-2026
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
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from typing import List
from html import escape
from ..utils import CommonFormatter, dump
class Formatter(CommonFormatter):
"""The asciidoc formatter"""
name = "html"
_tabular_name = "unsafehtml"
level = 45
def title(
self,
title: str,
level: int,
) -> str:
"""Display family name as a title"""
return f"<h{level}>{title}</h{level}>"
def join(
self,
lst: List[str],
) -> str:
"""Display line in tabular from a list"""
string = ""
previous = ""
for line in lst:
if string:
# if self.is_list(previous.split("\n", 1)[-1]):
# string += "<br/><br/>"
# else:
string += "<br/>"
string += line
previous = line
return string
def bold(
self,
msg: str,
) -> str:
"""Set a text to bold"""
return f"<b>{msg}</b>"
def italic(
self,
msg: str,
) -> str:
"""Set a text to italic"""
return f"<i>{msg}</i>"
def delete(
self,
msg: str,
) -> str:
"""Set a text to deleted"""
return f"<del>{msg}</del>"
def underline(
self,
msg: str,
) -> str:
"""Set a text to underline"""
return f"<ins>{msg}</ins>"
def stripped(
self,
text: str,
) -> str:
"""Return stripped text (as help)"""
return text.strip()
def list(
self,
choices: list,
*,
inside_tabular: bool = True,
type_: str = "variable",
with_enter: bool = True,
) -> str:
"""Display a liste of element"""
prefix = "<ul>"
char = "\n"
return (
"<ul>"
+ char.join(["<li>" + dump(choice) + "</li>" for choice in choices])
+ "</ul>"
)
def prop(
self,
prop: str,
italic: bool,
delete: bool,
underline: bool,
) -> str:
"""Display property"""
if italic:
prop = self.italic(prop)
if delete:
prop = self.delete(prop)
if underline:
prop = self.underline(prop)
return f"<mark>{prop}</mark>"
def _yaml(self, _dump: str) -> str:
"""Dump yaml part of documentation"""
return f"<pre>{_dump}</pre>"
def link(
self,
comment: str,
link: str,
underline: bool,
) -> str:
"""Add a link"""
return self.prop(f"<a href='{link}'>{comment}</a>", False, False, underline)
def is_list(
self,
txt: str,
) -> str:
"""verify if a text is a list"""
return txt.strip().startswith("<ul>")
def to_phrase(self, text: str) -> str:
return escape(text)
def family_informations_ends_line(self):
return "<br/>"

View file

@ -1,34 +0,0 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2024-2026
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
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from json import dumps
from typing import Any
class Formatter:
"""Just return internal structure to json"""
name = "json"
level = 90
def __init__(self, rougailconfig, **kwargs):
self.rougailconfig = rougailconfig
def run(self, informations: dict, *args) -> str: # pylint: disable=unused-argument
"""Transform to string"""
return dumps(informations, ensure_ascii=False, indent=2)

View file

@ -1,17 +0,0 @@
"""Loads output
Silique (https://www.silique.fr)
Copyright (C) 2025-2026
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
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""

View file

@ -1,94 +0,0 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2025-2026
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
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from ..i18n import _
from ..config import ROUGAIL_VARIABLE_TYPE
from .four_columns import Tabular as FourTabular
class Tabular(FourTabular):
"""The five columns tabular"""
name = "five_columns"
level = 60
def clear(self):
super().clear()
self.five_column = False
def _add(self) -> tuple:
first_column = self.add_first_column()
second_column = self.get_column(
self.description,
self.help_,
self.validators,
self.choices,
self.examples,
self.tags,
)
if second_column:
self.second_column = True
third_column = self.get_column(self.default)
if third_column:
self.third_column = True
types = self.formatter.property_to_string(
self.informations,
self.calculated_properties,
self.modified_attributes,
contents=["type"],
)
four_column = self.get_column(types)
if four_column:
self.four_column = True
mode = self.formatter.property_to_string(
self.informations,
self.calculated_properties,
self.modified_attributes,
contents=["mode", "access_control"],
)
five_column = self.get_column(mode, *self.calculated_properties)
if five_column:
self.five_column = True
return first_column, second_column, third_column, four_column, five_column
def headers(self) -> tuple:
header = super().headers()
if self.five_column:
header.append(_("Access control"))
return header
def get_columns(self):
for column in self.columns:
ret = [column[0]]
if self.second_column:
ret.append(column[1])
if self.third_column:
ret.append(column[2])
if self.four_column:
ret.append(column[3])
if self.five_column:
ret.append(column[4])
yield ret
def set_properties(self):
self.properties = self.formatter.property_to_string(
self.informations,
self.calculated_properties,
self.modified_attributes,
contents=["properties", "validator"],
)

View file

@ -1,84 +0,0 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2025-2026
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
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from ..i18n import _
from ..config import ROUGAIL_VARIABLE_TYPE
from .three_columns import Tabular as ThreeTabular
class Tabular(ThreeTabular):
"""The four columns tabular"""
name = "four_columns"
level = 50
def clear(self):
super().clear()
self.four_column = False
def _add(self) -> tuple:
first_column = self.add_first_column()
second_column = self.get_column(
self.description,
self.help_,
self.validators,
self.choices,
self.examples,
self.tags,
*self.calculated_properties,
)
if second_column:
self.second_column = True
third_column = self.get_column(self.default)
if third_column:
self.third_column = True
types = self.formatter.property_to_string(
self.informations,
self.calculated_properties,
self.modified_attributes,
contents="type",
)
four_column = self.get_column(types)
if four_column:
self.four_column = True
return first_column, second_column, third_column, four_column
def headers(self) -> tuple:
header = super().headers()
if self.four_column:
header.append(_("Type"))
return header
def get_columns(self):
for column in self.columns:
ret = [column[0]]
if self.second_column:
ret.append(column[1])
if self.third_column:
ret.append(column[2])
if self.four_column:
ret.append(column[3])
yield ret
def set_properties(self):
self.properties = self.formatter.property_to_string(
self.informations,
self.calculated_properties,
self.modified_attributes,
contents=["properties", "mode", "access_control", "validator"],
)

View file

@ -1,117 +0,0 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2025-2026
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
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from ..i18n import _
from ..config import ROUGAIL_VARIABLE_TYPE
from .five_columns import Tabular as FiveTabular
class Tabular(FiveTabular):
"""The six columns tabular"""
name = "six_columns"
level = 70
def clear(self):
super().clear()
self.six_column = False
def _add(self) -> tuple:
first_column = self.add_first_column()
second_column = self.get_column(
self.description, self.help_, self.examples, self.tags
)
if second_column:
self.second_column = True
third_column = self.get_column(self.default)
if third_column:
self.third_column = True
types = self.formatter.property_to_string(
self.informations,
self.calculated_properties,
self.modified_attributes,
contents=["type"],
)
four_column = self.get_column(types)
if four_column:
self.four_column = True
mode = self.formatter.property_to_string(
self.informations,
self.calculated_properties,
self.modified_attributes,
contents=["mode", "access_control"],
)
five_column = self.get_column(mode, *self.calculated_properties)
if five_column:
self.five_column = True
validators = self.formatter.property_to_string(
self.informations,
self.calculated_properties,
self.modified_attributes,
contents=["validator"],
)
six_column = self.get_column(validators, self.validators, self.choices)
if six_column:
self.six_column = True
return (
first_column,
second_column,
third_column,
four_column,
five_column,
six_column,
)
def headers(self) -> tuple:
header = super().headers()
if self.six_column:
header.append(_("Validator"))
return header
def get_columns(self):
for column in self.columns:
ret = [column[0]]
if self.second_column:
ret.append(column[1])
if self.third_column:
ret.append(column[2])
if self.four_column:
ret.append(column[3])
if self.five_column:
ret.append(column[4])
if self.six_column:
ret.append(column[5])
yield ret
def set_properties(self):
self.properties = self.formatter.property_to_string(
self.informations,
self.calculated_properties,
self.modified_attributes,
contents=["properties"],
)
def set_validators(self):
self.validators = self.formatter.convert_section_to_string(
"validators",
self.informations,
self.modified_attributes,
multi=True,
section_name=False,
with_to_phrase=True,
)

View file

@ -1,83 +0,0 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2025-2026
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
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from ..i18n import _
from .two_columns import Tabular as TwoTabular
class Tabular(TwoTabular):
"""The three columns tabular"""
name = "three_columns"
level = 30
def clear(self):
super().clear()
self.third_column = False
def _add(self) -> tuple:
first_column = self.add_first_column()
second_column = self.get_column(
self.description,
self.help_,
self.validators,
self.choices,
self.examples,
self.tags,
*self.calculated_properties,
)
if second_column:
self.second_column = True
third_column = self.get_column(self.default)
if third_column:
self.third_column = True
return first_column, second_column, third_column
def headers(self) -> tuple:
headers = super().headers()
if self.third_column:
headers.append(_("Default value"))
return headers
def get_columns(self):
for column in self.columns:
ret = [column[0]]
if self.second_column:
ret.append(column[1])
if self.third_column:
ret.append(column[2])
yield ret
def set_default(self):
if "default" in self.informations:
self.default = self.formatter.convert_section_to_string(
"default",
self.informations,
self.modified_attributes,
multi=self.multi,
section_name=False,
)
else:
self.default = None
def set_choices(self):
self.default_is_already_set, self.choices = (
self.formatter.convert_choices_to_string(
self.informations, self.modified_attributes, with_default=False
)
)

View file

@ -1,66 +0,0 @@
"""
Silique (https://www.silique.fr)
Copyright (C) 2025-2026
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
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from ..i18n import _
from ..utils import CommonTabular
class Tabular(CommonTabular):
"""The two columns tabular"""
name = "two_columns"
level = 10
def clear(self):
super().clear()
self.second_column = False
def _add(self) -> tuple:
first_column = self.add_first_column()
default = self.default if not self.default_is_already_set else None
second_column = self.get_column(
self.description,
self.help_,
self.validators,
self.choices,
default,
self.examples,
self.tags,
*self.calculated_properties,
)
if second_column:
self.second_column = True
return first_column, second_column
def add_first_column(self) -> str:
return self.get_column(
self.paths, self.properties, self.commandlines, self.environments
)
def headers(self) -> tuple:
headers = [_("Variable")]
if self.second_column:
headers.append(_("Description"))
return headers
def get_columns(self):
for column in self.columns:
ret = [column[0]]
if self.second_column:
ret.append(column[1])
yield ret

File diff suppressed because it is too large Load diff

View file

@ -1,41 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
family: # a family
var2:
description: a second variable
test:
- string6
subfamily: # a sub family
variable: # third variable
- variable: ___.var1
- variable: __.var2
var3: # a third variable
family2: # a family
var2:
description: a variable2
default:
variable: __.family.var2
var3:
description: a third variable
test:
- string5
default: string4
subfamily: # a sub family
variable: # fourth variable
- variable: ___.var1
- variable: ___.family.var2
- variable: __.var3
...

View file

@ -1,21 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
family: # a family
var2:
description: a second variable
test:
- string6
subfamily: # a sub family
variable: # third variable
- variable: ___.var1
- variable: __.var2
var3: # a third variable
...

View file

@ -1,20 +0,0 @@
== New variables
[cols="1a,1a"]
|====
| Variable | Description
| **family2.var2** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `standard` `mandatory` | A variable2. +
**Default**: the value of the variable "a second variable" (family.var2).
| **family2.var3** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `standard` `mandatory` | A third variable. +
**Default**: string4 +
**Example**: string5
| **family2.subfamily.variable** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `multiple` `standard` `mandatory` `unique` | Fourth variable. +
**Default**:
* the value of the variable "first variable" (var1)
* the value of the variable "a second variable" (family.var2)
* the value of the variable "a third variable" (family2.var3)
|====

View file

@ -1,9 +0,0 @@
<details><summary>New variables</summary>
| Variable | Description |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **<a id="family2.var2" name="family2.var2">family2.var2</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `standard` `mandatory` | A variable2.<br/>**Default**: the value of the variable "[a second variable](#family.var2)". |
| **<a id="family2.var3" name="family2.var3">family2.var3</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `standard` `mandatory` | A third variable.<br/>**Default**: string4<br/>**Example**: string5 |
| **<a id="family2.subfamily.variable" name="family2.subfamily.variable">family2.subfamily.variable</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` `standard` `mandatory` `unique` | Fourth variable.<br/>**Default**: <br/>&nbsp;the value of the variable "[first variable](#var1)"<br/>&nbsp;the value of the variable "[a second variable](#family.var2)"<br/>&nbsp;the value of the variable "[a third variable](#family2.var3)" |
</details>

View file

@ -1,14 +0,0 @@
<h1>New variables</h1>
<table>
<thead>
<tr><th>Variable </th><th>Description </th></tr>
</thead>
<tbody>
<tr><td><b>family2.var2</b><br/><mark><a href='https://rougail.readthedocs.io/en/latest/variable.html#variables-types'>string</a></mark> <mark>standard</mark> <mark>mandatory</mark> </td><td>A variable2.<br/><b>Default</b>: the value of the variable "a second variable" (family.var2).</td></tr>
<tr><td><b>family2.var3</b><br/><mark><a href='https://rougail.readthedocs.io/en/latest/variable.html#variables-types'>string</a></mark> <mark>standard</mark> <mark>mandatory</mark> </td><td>A third variable.<br/><b>Default</b>: string4<br/><b>Example</b>: string5 </td></tr>
<tr><td><b>family2.subfamily.variable</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>Fourth variable.<br/><b>Default</b>: <ul><li>the value of the variable "first variable" (var1)</li>
<li>the value of the variable "a second variable" (family.var2)</li>
<li>the value of the variable "a third variable" (family2.var3)</li></ul> </td></tr>
</tbody>
</table>

View file

@ -1,7 +0,0 @@
# New variables
| Variable | Description |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **<a id="family2.var2" name="family2.var2">family2.var2</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `standard` `mandatory` | A variable2.<br/>**Default**: the value of the variable "[a second variable](#family.var2)". |
| **<a id="family2.var3" name="family2.var3">family2.var3</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `standard` `mandatory` | A third variable.<br/>**Default**: string4<br/>**Example**: string5 |
| **<a id="family2.subfamily.variable" name="family2.subfamily.variable">family2.subfamily.variable</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` `standard` `mandatory` `unique` | Fourth variable.<br/>**Default**: <br/>&nbsp;the value of the variable "[first variable](#var1)"<br/>&nbsp;the value of the variable "[a second variable](#family.var2)"<br/>&nbsp;the value of the variable "[a third variable](#family2.var3)" |

View file

@ -1,23 +0,0 @@
New variables
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
 Variable  ┃ Description  ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
family2.var2 │ A variable2. │
 string   standard   mandatory  │ Default: the value of the variable │
│ │ "a second variable" (family.var2). │
├───────────────────────────────────────┼──────────────────────────────────────┤
family2.var3 │ A third variable. │
 string   standard   mandatory  │ Default: string4 │
│ │ Example: string5 │
├───────────────────────────────────────┼──────────────────────────────────────┤
family2.subfamily.variable │ Fourth variable. │
 string   multiple   standard    │ Default: │
mandatory   unique  │ • the value of the variable "first │
│ │ variable" (var1) │
│ │ • the value of the variable "a │
│ │ second variable" (family.var2) │
│ │ • the value of the variable "a third │
│ │ variable" (family2.var3) │
└───────────────────────────────────────┴──────────────────────────────────────┘

View file

@ -1,8 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
variable_to_family: # a variable that became a family
...

View file

@ -1,11 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
variable_to_family: # a variable that became a family
var:
description: a second variable
...

View file

@ -1,14 +0,0 @@
== New variable
[cols="1a,1a"]
|====
| Variable | Description
| **variable_to_family** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `basic` `mandatory` | A variable that became a family.
|====
== Deleted variable
* variable_to_family.var

View file

@ -1,13 +0,0 @@
<details><summary>New variable</summary>
| Variable | Description |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------|
| **<a id="variable_to_family" name="variable_to_family">variable_to_family</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | A variable that became a family. |
</details>
<details><summary>Deleted variable</summary>
- variable_to_family.var
</details>

View file

@ -1,14 +0,0 @@
<h1>New variable</h1>
<table>
<thead>
<tr><th>Variable </th><th>Description </th></tr>
</thead>
<tbody>
<tr><td><b>variable_to_family</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 that became a family.</td></tr>
</tbody>
</table>
<h1>Deleted variable</h1>
<ul><li>variable_to_family.var</li></ul>

View file

@ -1,9 +0,0 @@
# New variable
| Variable | Description |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------|
| **<a id="variable_to_family" name="variable_to_family">variable_to_family</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | A variable that became a family. |
# Deleted variable
- variable_to_family.var

View file

@ -1,14 +0,0 @@
New variable
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
 Variable  ┃ Description  ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
variable_to_family │ A variable that became a family. │
 string   basic   mandatory  │ │
└───────────────────────────────────────┴──────────────────────────────────────┘
Deleted variable
• variable_to_family.var

View file

@ -1,41 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
family: # a family
var2:
description: a second variable
test:
- string6
subfamily: # a sub family
variable: # third variable
- variable: ___.var1
- variable: __.var2
var3: # a third variable
family2: # a family
var2:
description: a variable2
default:
variable: __.family.var2
var3:
description: a third variable
test:
- string5
default: string4
subfamily: # a sub family
variable: # fourth variable
- variable: ___.var1
- variable: ___.family.var2
- variable: __.var3
...

View file

@ -1,39 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
family: # a family
var2:
description: a second variable
test:
- string6
subfamily: # a sub family
variable: # third variable
- variable: ___.var1
- variable: __.var2
family2: # a family
var2:
description: a variable2
default:
variable: __.family.var2
var3:
description: a third variable
test:
- string5
default: string4
subfamily: # a sub family
variable: # fourth variable
- variable: ___.var1
- variable: ___.family.var2
- variable: __.var3
...

View file

@ -1,8 +0,0 @@
== New variable
[cols="1a,1a"]
|====
| Variable | Description
| **family.var3** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `basic` `mandatory` | A third variable.
|====

View file

@ -1,7 +0,0 @@
<details><summary>New variable</summary>
| Variable | Description |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------|
| **<a id="family.var3" name="family.var3">family.var3</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | A third variable. |
</details>

View file

@ -1,10 +0,0 @@
<h1>New variable</h1>
<table>
<thead>
<tr><th>Variable </th><th>Description </th></tr>
</thead>
<tbody>
<tr><td><b>family.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>A third variable.</td></tr>
</tbody>
</table>

View file

@ -1,5 +0,0 @@
# New variable
| Variable | Description |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------|
| **<a id="family.var3" name="family.var3">family.var3</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | A third variable. |

View file

@ -1,9 +0,0 @@
New variable
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
 Variable  ┃ Description  ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
family.var3 │ A third variable. │
 string   basic   mandatory  │ │
└───────────────────────────────────────┴──────────────────────────────────────┘

View file

@ -1,11 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
variable_to_family: # a variable that became a family
var:
description: a second variable
...

View file

@ -1,8 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
variable_to_family: # a variable that became a family
...

View file

@ -1,14 +0,0 @@
== New variable
[cols="1a,1a"]
|====
| Variable | Description
| **variable_to_family.var** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `basic` `mandatory` | A second variable.
|====
== Deleted variable
* variable_to_family

View file

@ -1,13 +0,0 @@
<details><summary>New variable</summary>
| Variable | Description |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|
| **<a id="variable_to_family.var" name="variable_to_family.var">variable_to_family.var</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | A second variable. |
</details>
<details><summary>Deleted variable</summary>
- variable_to_family
</details>

View file

@ -1,14 +0,0 @@
<h1>New variable</h1>
<table>
<thead>
<tr><th>Variable </th><th>Description </th></tr>
</thead>
<tbody>
<tr><td><b>variable_to_family.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 second variable.</td></tr>
</tbody>
</table>
<h1>Deleted variable</h1>
<ul><li>variable_to_family</li></ul>

View file

@ -1,9 +0,0 @@
# New variable
| Variable | Description |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|
| **<a id="variable_to_family.var" name="variable_to_family.var">variable_to_family.var</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | A second variable. |
# Deleted variable
- variable_to_family

View file

@ -1,14 +0,0 @@
New variable
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
 Variable  ┃ Description  ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
variable_to_family.var │ A second variable. │
 string   basic   mandatory  │ │
└───────────────────────────────────────┴──────────────────────────────────────┘
Deleted variable
• variable_to_family

View file

@ -1,43 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
family: # a family
var2:
description: a second variable
test:
- string6
subfamily: # a sub family
variable: # third variable
- variable: ___.var1
- variable: __.var2
var3: # a third variable
family2: # a family
var2:
description: a variable2
default:
variable: __.family.var2
var3:
description: a third variable
test:
- string5
default: string4
subfamily: # a sub family
variable: # fourth variable
- variable: ___.var1
- variable: ___.family.var2
- variable: __.var3
var4: # a fourth variable
...

View file

@ -1,39 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
family: # a family
var2:
description: a second variable
test:
- string6
subfamily: # a sub family
variable: # third variable
- variable: ___.var1
- variable: __.var2
family2: # a family
var2:
description: a variable2
default:
variable: __.family.var2
var3:
description: a third variable
test:
- string5
default: string4
subfamily: # a sub family
variable: # fourth variable
- variable: ___.var1
- variable: ___.family.var2
- variable: __.var3
...

View file

@ -1,10 +0,0 @@
== New variables
[cols="1a,1a"]
|====
| Variable | Description
| **family.var3** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `basic` `mandatory` | A third variable.
| **family2.var4** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `basic` `mandatory` | A fourth variable.
|====

View file

@ -1,8 +0,0 @@
<details><summary>New variables</summary>
| Variable | Description |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|
| **<a id="family.var3" name="family.var3">family.var3</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | A third variable. |
| **<a id="family2.var4" name="family2.var4">family2.var4</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | A fourth variable. |
</details>

View file

@ -1,11 +0,0 @@
<h1>New variables</h1>
<table>
<thead>
<tr><th>Variable </th><th>Description </th></tr>
</thead>
<tbody>
<tr><td><b>family.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>A third variable. </td></tr>
<tr><td><b>family2.var4</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 fourth variable.</td></tr>
</tbody>
</table>

View file

@ -1,6 +0,0 @@
# New variables
| Variable | Description |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|
| **<a id="family.var3" name="family.var3">family.var3</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | A third variable. |
| **<a id="family2.var4" name="family2.var4">family2.var4</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | A fourth variable. |

View file

@ -1,12 +0,0 @@
New variables
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
 Variable  ┃ Description  ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
family.var3 │ A third variable. │
 string   basic   mandatory  │ │
├───────────────────────────────────────┼──────────────────────────────────────┤
family2.var4 │ A fourth variable. │
 string   basic   mandatory  │ │
└───────────────────────────────────────┴──────────────────────────────────────┘

View file

@ -1,21 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
family: # a family
var2:
description: a second variable
test:
- string6
subfamily: # a sub family
variable: # third variable
- variable: ___.var1
- variable: __.var2
var3: # a third variable
...

View file

@ -1,41 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
family: # a family
var2:
description: a second variable
test:
- string6
subfamily: # a sub family
variable: # third variable
- variable: ___.var1
- variable: __.var2
var3: # a third variable
family2: # a family
var2:
description: a variable2
default:
variable: __.family.var2
var3:
description: a third variable
test:
- string5
default: string4
subfamily: # a sub family
variable: # fourth variable
- variable: ___.var1
- variable: ___.family.var2
- variable: __.var3
...

View file

@ -1,7 +0,0 @@
== Deleted variables
* family2.var2
* family2.var3
* family2.subfamily.variable

View file

@ -1,7 +0,0 @@
<details><summary>Deleted variables</summary>
- family2.var2
- family2.var3
- family2.subfamily.variable
</details>

View file

@ -1,5 +0,0 @@
<h1>Deleted variables</h1>
<ul><li>family2.var2</li>
<li>family2.var3</li>
<li>family2.subfamily.variable</li></ul>

View file

@ -1,5 +0,0 @@
# Deleted variables
- family2.var2
- family2.var3
- family2.subfamily.variable

View file

@ -1,7 +0,0 @@
Deleted variables
• family2.var2
• family2.var3
• family2.subfamily.variable

View file

@ -1,39 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
family: # a family
var2:
description: a second variable
test:
- string6
subfamily: # a sub family
variable: # third variable
- variable: ___.var1
- variable: __.var2
family2: # a family
var2:
description: a variable2
default:
variable: __.family.var2
var3:
description: a third variable
test:
- string5
default: string4
subfamily: # a sub family
variable: # fourth variable
- variable: ___.var1
- variable: ___.family.var2
- variable: __.var3
...

View file

@ -1,41 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
family: # a family
var2:
description: a second variable
test:
- string6
subfamily: # a sub family
variable: # third variable
- variable: ___.var1
- variable: __.var2
var3: # a third variable
family2: # a family
var2:
description: a variable2
default:
variable: __.family.var2
var3:
description: a third variable
test:
- string5
default: string4
subfamily: # a sub family
variable: # fourth variable
- variable: ___.var1
- variable: ___.family.var2
- variable: __.var3
...

View file

@ -1,5 +0,0 @@
== Deleted variable
* family.var3

View file

@ -1,5 +0,0 @@
<details><summary>Deleted variable</summary>
- family.var3
</details>

View file

@ -1,3 +0,0 @@
<h1>Deleted variable</h1>
<ul><li>family.var3</li></ul>

View file

@ -1,3 +0,0 @@
# Deleted variable
- family.var3

View file

@ -1,5 +0,0 @@
Deleted variable
• family.var3

View file

@ -1,39 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
family: # a family
var2:
description: a second variable
test:
- string6
subfamily: # a sub family
variable: # third variable
- variable: ___.var1
- variable: __.var2
family2: # a family
var2:
description: a variable2
default:
variable: __.family.var2
var3:
description: a third variable
test:
- string5
default: string4
subfamily: # a sub family
variable: # fourth variable
- variable: ___.var1
- variable: ___.family.var2
- variable: __.var3
...

View file

@ -1,43 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
family: # a family
var2:
description: a second variable
test:
- string6
subfamily: # a sub family
variable: # third variable
- variable: ___.var1
- variable: __.var2
var3: # a third variable
family2: # a family
var2:
description: a variable2
default:
variable: __.family.var2
var3:
description: a third variable
test:
- string5
default: string4
subfamily: # a sub family
variable: # fourth variable
- variable: ___.var1
- variable: ___.family.var2
- variable: __.var3
var4: # a fourth variable
...

View file

@ -1,6 +0,0 @@
== Deleted variables
* family.var3
* family2.var4

View file

@ -1,6 +0,0 @@
<details><summary>Deleted variables</summary>
- family.var3
- family2.var4
</details>

View file

@ -1,4 +0,0 @@
<h1>Deleted variables</h1>
<ul><li>family.var3</li>
<li>family2.var4</li></ul>

View file

@ -1,4 +0,0 @@
# Deleted variables
- family.var3
- family2.var4

View file

@ -1,6 +0,0 @@
Deleted variables
• family.var3
• family2.var4

View file

@ -1,6 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # new description
...

View file

@ -1,6 +0,0 @@
%YAML 1.2
---
version: 1.1
var1:
...

View file

@ -1,8 +0,0 @@
== Modified variable
[cols="1a,1a"]
|====
| Variable | Description
| **var1** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `basic` `mandatory` | #New description.#
|====

View file

@ -1,7 +0,0 @@
<details><summary>Modified variable</summary>
| Variable | Description |
|--------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------|
| **<a id="var1" name="var1">var1</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | <ins>New description.</ins> |
</details>

View file

@ -1,10 +0,0 @@
<h1>Modified variable</h1>
<table>
<thead>
<tr><th>Variable </th><th>Description </th></tr>
</thead>
<tbody>
<tr><td><b>var1</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><ins>New description.</ins></td></tr>
</tbody>
</table>

View file

@ -1,5 +0,0 @@
# Modified variable
| Variable | Description |
|--------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------|
| **<a id="var1" name="var1">var1</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | <ins>New description.</ins> |

View file

@ -1,9 +0,0 @@
Modified variable
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
 Variable  ┃ Description  ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
var1 │ New description. │
 string   basic   mandatory  │ │
└───────────────────────────────────────┴──────────────────────────────────────┘

View file

@ -1,6 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # new description
...

View file

@ -1,6 +0,0 @@
%YAML 1.2
---
version: 1.1
var1: # first variable
...

View file

@ -1,9 +0,0 @@
== Modified variable
[cols="1a,1a"]
|====
| Variable | Description
| **var1** +
`https://rougail.readthedocs.io/en/latest/variable.html#variables-types[string]` `basic` `mandatory` | +++First variable.+++ +
#New description.#
|====

View file

@ -1,7 +0,0 @@
<details><summary>Modified variable</summary>
| Variable | Description |
|--------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------|
| **<a id="var1" name="var1">var1</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | ~~First variable.~~<br/><ins>New description.</ins> |
</details>

View file

@ -1,10 +0,0 @@
<h1>Modified variable</h1>
<table>
<thead>
<tr><th>Variable </th><th>Description </th></tr>
</thead>
<tbody>
<tr><td><b>var1</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><del>First variable.</del><br/><ins>New description.</ins></td></tr>
</tbody>
</table>

View file

@ -1,5 +0,0 @@
# Modified variable
| Variable | Description |
|--------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------|
| **<a id="var1" name="var1">var1</a>**<br/>[`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `basic` `mandatory` | ~~First variable.~~<br/><ins>New description.</ins> |

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