Compare commits

...

163 commits

Author SHA1 Message Date
4a3a391ee0 bump: version 0.2.0a47 → 0.2.0a48 2026-05-04 13:35:08 +02:00
5f5cb9aa08 fix: get unrestraint default value 2026-05-04 11:10:50 +02:00
68d6b1cd14 bump: version 0.2.0a46 → 0.2.0a47 2026-04-30 07:32:53 +02:00
8562659f2b fix: better identifier documentation 2026-04-30 06:58:12 +02:00
cce4447390 fix: better display of path 2026-04-01 17:01:24 +02:00
316af5cb3f fix: better description informations 2026-03-31 12:27:08 +02:00
d26653d95c fix: do not display {{ identifier }} in description 2026-03-30 22:28:05 +02:00
f9d3428bf3 feat: add dot if needed 2026-03-30 08:59:25 +02:00
d76e676d4e feat: better documentation generation 2026-03-29 11:01:15 +02:00
0271bf430a fix: better identifier support 2026-03-14 21:24:57 +01:00
48668bce75 fix: support mode 2026-03-14 20:51:52 +01:00
76a0a9080b fix: root config with identifier 2026-02-01 21:11:08 +01:00
e06c9b1829 bump: version 0.2.0a45 → 0.2.0a46 2026-01-29 08:40:07 +01:00
d4b16e918b fix: better transitive documentation 2026-01-29 08:34:40 +01:00
1ecd7abbe7 fix: update translation 2026-01-28 08:28:56 +01:00
c0cae3fc6e feat: support transitive 2026-01-27 16:08:39 +01:00
246ad6c7e0 bump: version 0.2.0a44 → 0.2.0a45 2026-01-21 09:00:38 +01:00
42053d0e0d feat: doc transitive properties 2026-01-21 08:34:43 +01:00
0024c2cb2a fix: root could be a variable 2026-01-19 17:12:20 +01:00
fe3c28f6d4 fix: path 2026-01-19 17:01:29 +01:00
20b475c5f2 bump: version 0.2.0a43 → 0.2.0a44 2026-01-14 15:37:56 +01:00
78b649cf39 fix: yaml in output format do not convert object to str 2026-01-14 15:37:50 +01:00
9e2812c542 bump: version 0.2.0a42 → 0.2.0a43 2026-01-14 13:57:00 +01:00
8e2e70486c feat: add 'document_a_type' option 2026-01-14 13:56:51 +01:00
8d305c96fb bump: version 0.2.0a41 → 0.2.0a42 2026-01-04 19:16:56 +01:00
d229eb2a34 feat: remove doc.root, pass directly the family to doc output (be careful, add true_config parameter too) 2026-01-04 19:16:18 +01:00
e3ad3be95d bump: version 0.2.0a40 → 0.2.0a41 2025-12-30 10:53:04 +01:00
5551536c07 fix: update tests 2025-12-29 18:47:37 +01:00
8b44182bf5 fix: read_write is a boolean 2025-12-23 20:04:14 +01:00
5abfe1c4a8 bump: version 0.2.0a39 → 0.2.0a40 2025-12-22 08:56:14 +01:00
abe492c178 fix: better documentation 2025-12-22 08:56:04 +01:00
948e0b49ed feat: personalise column number 2025-12-02 13:39:44 +01:00
3cde479202 fix: better commandline doc + params description is now in rougail 2025-11-29 07:59:33 +01:00
77e311dedf feat: document commandline and environment variable 2025-11-27 22:17:17 +01:00
2b9c251780 bump: version 0.2.0a38 → 0.2.0a39 2025-11-21 08:15:09 +01:00
0b7f1fe087 feat: change path in description 2025-11-21 08:15:00 +01:00
e48c55a8f2 fix: dynamic variables with identifier in description 2025-11-17 15:46:24 +01:00
103adeddf4 feat: add anchor to markdown format and remove unsupported character in anchor id 2025-11-17 09:50:28 +01:00
4bf2f778ac fix: gitlab id in anchor with dynamic variables 2025-11-16 21:22:18 +01:00
d0915ff83d feat: use blockquote for family description 2025-11-15 10:37:15 +01:00
4f475be53e bump: version 0.2.0a37 → 0.2.0a38 2025-11-12 19:26:53 +01:00
a400088e2d feat: better enter support 2025-11-10 14:01:45 +01:00
4b215ce407 bump: version 0.2.0a36 → 0.2.0a37 2025-11-06 06:27:47 +01:00
64f448c141 feat: delete/underline is inside tag for some format 2025-11-05 21:43:10 +01:00
d8a0e22de9 feat: can reload formatter 2025-11-03 09:03:59 +01:00
8afb61c5ad feat: can document part by part with reloading structure 2025-10-30 21:14:34 +01:00
c754f5c654 bump: version 0.2.0a35 → 0.2.0a36 2025-10-29 11:12:09 +01:00
bd1d85442e feat: anchor in gitlab output_format 2025-10-29 11:03:16 +01:00
ecf3570b79 feat: can had comments with family/variable description in examples doc 2025-10-28 06:22:50 +01:00
9d8be3880a feat: comment variables from a family 2025-10-27 21:59:39 +01:00
2961a61aa6 bump: version 0.2.0a34 → 0.2.0a35 2025-10-27 14:25:26 +01:00
ce96cad54d fix: add changelog support for github/gitlab format 2025-10-27 14:25:07 +01:00
9bbb60c460 feat: tags documentation 2025-10-26 17:12:17 +01:00
72fa10208e fix: tests 2025-10-26 15:22:17 +01:00
a913be6b52 bump: version 0.2.0a33 → 0.2.0a34 2025-10-22 17:02:38 +02:00
bd44db892c feat: ca force true_color terminal when export to console 2025-10-22 17:01:57 +02:00
afb85063ac fix: parse subtree for a dynamic 2025-10-18 11:27:22 +02:00
a0843e08ca fix: adapt api for rougail-web-ui 2025-10-18 06:40:23 +02:00
c1ab106ba5 fix: undocumented variable in dynamic 2025-10-16 20:58:39 +02:00
cb770dd8d7 bump: version 0.2.0a32 → 0.2.0a33 2025-10-16 08:21:49 +02:00
fc4c2221d1 fix: support rougail-web-ui 2025-10-16 08:19:35 +02:00
a92f447478 feat: can document a variable for a specified identifier 2025-10-15 10:05:21 +02:00
b4ce22a0af fix: black 2025-10-15 09:44:22 +02:00
6dd6df77a1 fix: remove extra '*' 2025-10-14 21:58:01 +02:00
bebea05e7c feat: can remove header when generate a table 2025-10-14 16:48:39 +02:00
e97f4b4ca6 fix: always use name for informations key (sometime path was used) 2025-10-14 16:09:33 +02:00
a79a420ba5 feat: add html output 2025-10-14 13:50:02 +02:00
641ab723e0 feat: changelog for variables 2025-10-14 12:58:39 +02:00
da1519071e fix: update tests 2025-10-07 21:00:28 +02:00
622764bf53 fix: translation for property is now in rougail 2025-10-05 21:28:58 +02:00
856811805c bump: version 0.2.0a31 → 0.2.0a32 2025-10-03 08:22:36 +02:00
38fa8447eb fix: property calculated with disabled variable 2025-10-03 08:22:14 +02:00
c5134247a0 fix: better disabled support 2025-10-03 06:44:25 +02:00
a5dc507c65 bump: version 0.2.0a30 → 0.2.0a31 2025-10-02 22:43:42 +02:00
550996f22a feat: limit warning when asked 2025-10-02 22:43:25 +02:00
5652757787 bump: version 0.2.0a29 → 0.2.0a30 2025-10-02 22:23:04 +02:00
a307cb1c66 feat: better support variable calculation for property 2025-10-02 22:20:33 +02:00
1cbe8377e0 bump: version 0.2.0a28 → 0.2.0a29 2025-10-02 22:20:19 +02:00
3af6ee631c fix: property for namespace 2025-10-02 22:20:09 +02:00
d022e44e1d bump: version 0.2.0a27 → 0.2.0a28 2025-10-02 22:19:44 +02:00
9a0219ce55 feat: add gitlab plugin 2025-10-02 22:19:22 +02:00
17b589c268 fix: tests for formatter 2025-09-30 21:57:05 +02:00
53e1261812 fix: update translation 2025-09-30 06:15:00 +02:00
ef0aca7e55 bump: version 0.2.0a26 → 0.2.0a27 2025-09-29 21:26:25 +02:00
86dce82a57 fix: doc network with CIDR format 2025-09-29 21:26:12 +02:00
777346d070 fix: better doc for calculation with unknown variable 2025-09-29 21:18:55 +02:00
213c25c8f6 bump: version 0.2.0a25 → 0.2.0a26 2025-09-29 11:00:30 +02:00
242b6505ce feat: default value for a calculated variable with an unknown optional variable 2025-09-28 15:53:31 +02:00
f5dc501bf9 feat: add integer type which will replace number type 2025-09-23 22:09:33 +02:00
154238c46e bump: version 0.2.0a24 → 0.2.0a25 2025-09-22 09:43:08 +02:00
1fe10dbe20 feat: adapt to tiramisu-web-ui 2025-09-22 09:42:46 +02:00
2652fc9db6 bump: version 0.2.0a23 → 0.2.0a24 2025-06-19 07:28:10 +03:00
2a7f78103b feat: could not change default value during annotator 2025-06-19 07:27:59 +03:00
02778fe53b bump: version 0.2.0a22 → 0.2.0a23 2025-06-18 16:52:35 +03:00
1718a76ce9 fix: separation 2025-06-18 16:50:11 +03:00
a8c682d76c bump: version 0.2.0a21 → 0.2.0a22 2025-06-18 07:57:53 +03:00
706ddd369e fix: rougail separation 2025-06-18 07:42:33 +03:00
25dc2874b2 bump: version 0.2.0a20 → 0.2.0a21 2025-05-12 09:11:19 +02:00
3dfc3ab166 fix: update translation 2025-05-12 08:39:38 +02:00
263dae2b2c fix: black 2025-05-11 19:13:12 +02:00
561d117d4d fix: doc example with leader example lower than leader default value 2025-05-11 14:44:46 +02:00
8f2c4b0011 bump: version 0.2.0a19 → 0.2.0a20 2025-05-09 08:22:34 +02:00
94c7922782 fix: undefined is a rougail object 2025-05-09 07:45:10 +02:00
c9a0f2d1ec bump: version 0.2.0a18 → 0.2.0a19 2025-05-05 10:08:56 +02:00
5e325f744d fix: update translation 2025-05-05 10:08:45 +02:00
f911425e1a bump: version 0.2.0a17 → 0.2.0a18 2025-05-05 10:03:59 +02:00
b60792314e fix: doc default value with undocumented variable 2025-05-05 10:03:44 +02:00
2886cf0348 bump: version 0.2.0a16 → 0.2.0a17 2025-05-05 08:52:28 +02:00
f0f3fc899d fix: description for all calculations 2025-05-04 14:29:51 +02:00
96866e99a4 fix: better documentation variable with variable in default attribut 2025-05-02 21:57:35 +02:00
d8e52e26fd bump: version 0.2.0a15 → 0.2.0a16 2025-04-30 09:04:41 +02:00
07027690a7 fix: update translation 2025-04-29 23:06:35 +02:00
19767f346d fix: remove negative_description support 2025-04-29 22:51:36 +02:00
726c64e23d fix: better documentation with hidden variable in property calculation 2025-04-29 08:32:53 +02:00
abbeb78dbb fix: use new information ymlfiles 2025-04-28 16:49:41 +02:00
aaf3f95126 fix: update tests 2025-04-27 10:24:10 +02:00
aeff3e8b7c fix: better dynamic support 2025-04-25 14:17:07 +02:00
0f96fa0123 bump: version 0.2.0a14 → 0.2.0a15 2025-04-09 21:34:24 +02:00
d69d0cc8e8 fix: version 2025-04-09 21:34:21 +02:00
81ff417107 bump: version 0.2.0a13 → 0.2.0a14 2025-04-07 08:42:04 +02:00
a7ede66aa7 fix: calculation for dynamic ans leadership variables 2025-04-05 11:23:47 +02:00
b4dfa14602 bump: version 0.2.0a12 → 0.2.0a13 2025-04-02 21:16:40 +02:00
a2e1d7746e fix: error in disabled dynamic variable 2025-04-02 21:15:33 +02:00
b8f3e71314 bump: version 0.2.0a11 → 0.2.0a12 2025-04-01 22:19:42 +02:00
bb5caa5388 fix: update tests 2025-04-01 22:02:44 +02:00
fd8a2843ba fix: groups.namespace could be unexistant 2025-04-01 19:42:45 +02:00
8e5cc2622e bump: version 0.2.0a10 → 0.2.0a11 2025-03-31 10:25:17 +02:00
22e839027d fix: doc a param with a set but with only one item 2025-03-31 10:25:08 +02:00
fcac55ae92 bump: version 0.2.0a9 → 0.2.0a10 2025-03-30 19:48:00 +02:00
d3b1462db5 feat: document unix file name parameters 2025-03-30 19:47:56 +02:00
737ddc0f43 feat: better console output 2025-03-29 15:10:03 +01:00
5c9c102245 fix: doc for param 2025-03-29 14:38:47 +01:00
fd54b9ca00 fix: support NamespaceCalculation 2025-03-29 14:37:14 +01:00
83614a2a5e fix: convert <ENV> to &lt;ENV&gt; for github plugin 2025-03-29 14:35:32 +01:00
8e6200b321 feat: do not document reference to undocumented variable 2025-03-02 13:38:14 +01:00
1364083ffb bump: version 0.2.0a8 → 0.2.0a9 2025-02-19 16:43:55 +01:00
604cfa0a1d fix: support suffix (in version 1.0 format) in calculation 2025-02-19 16:43:37 +01:00
97a8653b28 bump: version 0.2.0a7 → 0.2.0a8 2025-02-19 12:49:32 +01:00
76d7c968fe fix: key is the path 2025-02-19 12:49:21 +01:00
693050b195 bump: version 0.2.0a6 → 0.2.0a7 2025-02-19 08:39:59 +01:00
d927f60769 fix: with_family => without_family and with_example => example 2025-02-19 08:39:44 +01:00
53de7569ee bump: version 0.2.0a5 → 0.2.0a6 2025-02-17 20:54:12 +01:00
3f3f6aa495 feat: add with_family parameter 2025-02-17 20:53:58 +01:00
affd645ebd bump: version 0.2.0a4 → 0.2.0a5 2025-02-17 09:49:59 +01:00
7f003a574b fix: do not add multiple attribute several time in json export 2025-02-17 09:49:51 +01:00
495336c146 bump: version 0.2.0a3 → 0.2.0a4 2025-02-10 09:52:15 +01:00
60b4a06807 feat: output return status too 2025-02-10 09:52:12 +01:00
88aca6b0ea bump: version 0.2.0a2 → 0.2.0a3 2025-01-04 18:00:49 +01:00
1903ee8031 fix: detect_symlink => only_self 2025-01-04 18:00:38 +01:00
135936782f bump: version 0.2.0a1 → 0.2.0a2 2025-01-04 11:55:02 +01:00
705239141e fix: do not document symlink 2025-01-04 11:54:20 +01:00
673e89e5e1 fix: remove prefix_path 2025-01-04 11:52:09 +01:00
cac294b800 feat: create tests 2024-12-07 10:53:41 +01:00
58ee0f3106 bump: version 0.2.0a0 → 0.2.0a1 2024-11-28 21:37:17 +01:00
e6a38423ef fix: separation between run and print function 2024-11-28 21:36:45 +01:00
1f37457b9f bump: version 0.1.1a0 → 0.2.0a0 2024-11-20 22:01:04 +01:00
9f5d0e2497 feat: personalize mode that we want disable documentation 2024-11-20 21:59:21 +01:00
af652eda76 feat: add console output 2024-11-20 21:13:42 +01:00
3d4b7b945c feat: better dynamique family support 2024-11-20 21:10:14 +01:00
3cc85d7ba5 feat: add json output 2024-11-09 15:10:25 +01:00
12622032a8 fix: correction for properties in italic 2024-11-09 07:40:08 +01:00
d805cbf565 bump: version 0.1.0 → 0.1.1a0 2024-11-08 08:14:35 +01:00
46eeb49c5f fix: generate documentation with force_optional configuration 2024-11-08 07:39:32 +01:00
18394 changed files with 308225 additions and 26153 deletions

View file

@ -1,3 +1,404 @@
## 0.2.0a48 (2026-05-04)
### Fix
- get unrestraint default value
## 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) ## 0.1.0rc1 (2024-11-06)
### Fix ### Fix

80
README.fr.md Normal file
View file

@ -0,0 +1,80 @@
---
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,2 +1,80 @@
# rougaildoc ---
gitea: none
include_toc: true
---
[🇬🇧 (EN)](README.md) - [🇫🇷 (FR)](README.fr.md)
## 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". |

View file

@ -5,8 +5,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"POT-Creation-Date: 2024-11-01 11:42+0100\n" "POT-Creation-Date: 2026-04-30 06:54+0200\n"
"PO-Revision-Date: 2024-11-01 11:42+0100\n" "PO-Revision-Date: 2026-04-30 06:55+0200\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
"Language: fr\n" "Language: fr\n"
@ -14,138 +14,616 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n" "Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 3.5\n" "X-Generator: Poedit 3.9\n"
#: src/rougail/output_doc/__init__.py:40 #: src/rougail/output_doc/changelog.py:153
msgid "the domain name can starts by a dot" msgid "New variable"
msgstr "le nom de domaine peut commencé par un point" msgstr "Nouvelle variable"
#: src/rougail/output_doc/__init__.py:41 #: src/rougail/output_doc/changelog.py:155
msgid "the domain name can be a hostname" msgid "New variables"
msgstr "le nom de domaine peut être un nom d'hôte" msgstr "Nouvelles variables"
#: src/rougail/output_doc/__init__.py:42 #: src/rougail/output_doc/changelog.py:165
msgid "the domain name can be an IP" msgid "Modified variable"
msgstr "le nom de domaine peut être une IP" msgstr "Variable modifiée"
#: src/rougail/output_doc/__init__.py:43 #: src/rougail/output_doc/changelog.py:167
msgid "the domain name can be network in CIDR format" msgid "Modified variables"
msgstr "le nom de domaine peut être un réseau au format CIDR" msgstr "Variables modifiées"
#: src/rougail/output_doc/__init__.py:48 #: src/rougail/output_doc/changelog.py:177
msgid "the minimum value is {0}" msgid "Deleted variable"
msgstr "le valeur minimal est {0}" msgstr "Variable supprimée"
#: src/rougail/output_doc/__init__.py:49 #: src/rougail/output_doc/changelog.py:179
msgid "the maximum value is {0}" msgid "Deleted variables"
msgstr "le valeur maximal est {0}" msgstr "Variables supprimées"
#: src/rougail/output_doc/__init__.py:55 #: src/rougail/output_doc/collect.py:53
msgid "IP must be in CIDR format" msgid ""
msgstr "IP doit être au format CIDR" "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:56 #: src/rougail/output_doc/collect.py:107
msgid "private IP are allowed" msgid "the value of the information \"{0}\" of the variable {{0}}"
msgstr "les IP privées sont autorisés" msgstr "la valeur de l'information \"{0}\" de la variable \"{{0}}\""
#: src/rougail/output_doc/__init__.py:57 #: src/rougail/output_doc/collect.py:115
msgid "reserved IP are allowed" msgid "the value of the global information \"{0}\""
msgstr "les IP réservés sont autorisés" msgstr "la valeur de l'information globale \"{0}\""
#: src/rougail/output_doc/__init__.py:62 #: src/rougail/output_doc/collect.py:121
msgid "the host name can be an IP" msgid "the value of the {0}"
msgstr "le nom d'hôte peut être une IP" msgstr "la valeur de l'{0}"
#: src/rougail/output_doc/__init__.py:67 #: src/rougail/output_doc/collect.py:130
msgid "the domain name in web address can be an IP" msgid "depends on a calculation"
msgstr "le nom de domaine dans l'adresse web peut être une IP" msgstr "dépend d'un calcul"
#: src/rougail/output_doc/__init__.py:68 #: src/rougail/output_doc/collect.py:131
msgid "the domain name in web address can be only a hostname" msgid "\"{0}\" is a calculation for {1} but has no description in {2}"
msgstr "le nom de domaine dans l'adresse web ne peut être qu'un nom d'hôte" msgstr "\"{0}\" est un calcul pour {1} mais n'a pas de description dans {2}"
#: src/rougail/output_doc/__init__.py:75 #: src/rougail/output_doc/collect.py:190
msgid "can be range of port" msgid "depends on an undocumented variable"
msgstr "peut être un range de port" msgstr "dépends d'une variable non documentée"
#: src/rougail/output_doc/__init__.py:76 #: src/rougail/output_doc/collect.py:208
msgid "can have the protocol" msgid "is \"{0}\""
msgstr "peut avoir un protocole" msgstr "est \"{0}\""
#: src/rougail/output_doc/__init__.py:77 #: src/rougail/output_doc/collect.py:213
msgid "port 0 is allowed" msgid "is accessible"
msgstr "le port 0 est autorisé" msgstr "est accessible"
#: src/rougail/output_doc/__init__.py:78 #: src/rougail/output_doc/collect.py:215
msgid "ports 1 to 1023 are allowed" msgid "is defined"
msgstr "les ports entre 1 et 1023 sont autorisés" msgstr "est définie"
#: src/rougail/output_doc/__init__.py:79 #: src/rougail/output_doc/collect.py:220
msgid "ports 1024 to 49151 are allowed" msgid "hasn't the value \"{0}\""
msgstr "les ports entre 1024 et 49151 sont autorisés" msgstr "n'a pas la valeur \"{0}\""
#: src/rougail/output_doc/__init__.py:80 #: src/rougail/output_doc/collect.py:222
msgid "ports greater than 49152 are allowed" msgid "has the value \"{0}\""
msgstr "les ports supérieurs à 49152 sont autorisés" msgstr "a la valeur \"{0}\""
#: src/rougail/output_doc/__init__.py:125 #: src/rougail/output_doc/collect.py:226
msgid "mandatory" msgid "is {0}"
msgstr "obligatoire" msgstr "est {0}"
#: src/rougail/output_doc/__init__.py:126 #: src/rougail/output_doc/collect.py:228
msgid "hidden" msgid "when the variable {{0}} {0}."
msgstr "caché" msgstr "lorsque la variable {{0}} {0}."
#: src/rougail/output_doc/__init__.py:127 #: src/rougail/output_doc/collect.py:256
msgid "disabled" msgid "the value of the variable {0} if it is defined"
msgstr "désactivé" msgstr "la valeur de la variable {0} si elle est définie"
#: src/rougail/output_doc/__init__.py:128 #: src/rougail/output_doc/collect.py:258
msgid "unique" msgid "the value of the variable {0}"
msgstr "unique" msgstr "la valeur de la variable {0}"
#: src/rougail/output_doc/__init__.py:129 #: src/rougail/output_doc/collect.py:277
msgid "auto modified" msgid "(from an undocumented variable)"
msgstr "auto modifiée" msgstr "(issue d'une variable non documentée)"
#: src/rougail/output_doc/__init__.py:163 #: src/rougail/output_doc/collect.py:283
msgid "Variables for \"{0}\"" msgid "{0} (from an undocumented variable)"
msgstr "Variables pour \"{0}\"" msgstr "{0} (issue d'une variable non documentée)"
#: src/rougail/output_doc/__init__.py:180 #: src/rougail/output_doc/collect.py:287
msgid "Variables" msgid "the value of an undocumented variable"
msgstr "Variables" msgstr "la valeur d'une variable non documentée"
#: src/rougail/output_doc/__init__.py:187 #: src/rougail/output_doc/collect.py:322
msgid "Example with mandatory variables not filled in" msgid "when the identifier is \"{0}\""
msgstr "Exemple avec des variables obligatoire non renseignée" msgstr "lorsque l'identifiant est \"{0}\""
#: src/rougail/output_doc/__init__.py:493 #: src/rougail/output_doc/collect.py:324
msgid "(default)" msgid "when the identifier is not \"{0}\""
msgstr "(defaut)" msgstr "lorsque l'identifiant n'est pas \"{0}\""
#: src/rougail/output_doc/__init__.py:498 #: src/rougail/output_doc/collect.py:329
msgid "Choices" msgid "the value of the identifier"
msgstr "Choix" msgstr "la valeur de l'identifiant"
#: src/rougail/output_doc/__init__.py:501 #: src/rougail/output_doc/collect.py:426
msgid "Default" msgid "This family contains lists of variable blocks"
msgstr "Défaut" msgstr "Cette famille contient des listes de bloc de variable"
#: src/rougail/output_doc/__init__.py:559 #: src/rougail/output_doc/collect.py:430
msgid "the value of the variable \"{0}\"" msgid "This family builds families dynamically"
msgstr "la valeur de la variable \"{0}\"" msgstr "Cette famille construit des familles dynamiquement"
#: src/rougail/output_doc/__init__.py:564 #: src/rougail/output_doc/collect.py:440
#: src/rougail/output_doc/__init__.py:566 msgid "This family is a namespace"
msgid "value of the {0}" msgstr "Cette famille est un espace de nom"
msgstr "la valeur de {0}"
#: src/rougail/output_doc/__init__.py:638 #: src/rougail/output_doc/collect.py:489
#: src/rougail/output_doc/__init__.py:651
msgid "Example" msgid "Example"
msgstr "Exemple" msgstr "Exemple"
#: src/rougail/output_doc/__init__.py:649 #: src/rougail/output_doc/collect.py:492
msgid "Examples" msgid "Examples"
msgstr "Exemples" 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
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
msgid "(default)"
msgstr "(défaut)"
#: src/rougail/output_doc/utils.py:1211
msgid "{0}: {1}"
msgstr "{0} : {1}"
#~ msgid "if doc is not set in \"step.output\""
#~ msgstr "si doc n'est pas spécifié dans \"step.output\""
#~ msgid "the values of undocumented variables"
#~ msgstr "les valeurs de variables non documentées"
#~ 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}\""
#~ 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}\""
#~ 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\""

View file

@ -5,7 +5,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2024-11-01 11:42+0100\n" "POT-Creation-Date: 2026-04-30 06:55+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -15,137 +15,388 @@ msgstr ""
"Generated-By: pygettext.py 1.5\n" "Generated-By: pygettext.py 1.5\n"
#: src/rougail/output_doc/__init__.py:40 #: src/rougail/output_doc/changelog.py:153
msgid "the domain name can starts by a dot" msgid "New variable"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:41 #: src/rougail/output_doc/changelog.py:155
msgid "the domain name can be a hostname" msgid "New variables"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:42 #: src/rougail/output_doc/changelog.py:165
msgid "the domain name can be an IP" msgid "Modified variable"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:43 #: src/rougail/output_doc/changelog.py:167
msgid "the domain name can be network in CIDR format" msgid "Modified variables"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:48 #: src/rougail/output_doc/changelog.py:177
msgid "the minimum value is {0}" msgid "Deleted variable"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:49 #: src/rougail/output_doc/changelog.py:179
msgid "the maximum value is {0}" msgid "Deleted variables"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:55 #: src/rougail/output_doc/collect.py:53
msgid "IP must be in CIDR format" msgid "cannot find \"{0}_calculation\" information, do you have annotate this configuration?"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:56 #: src/rougail/output_doc/collect.py:107
msgid "private IP are allowed" msgid "the value of the information \"{0}\" of the variable {{0}}"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:57 #: src/rougail/output_doc/collect.py:115
msgid "reserved IP are allowed" msgid "the value of the global information \"{0}\""
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:62 #: src/rougail/output_doc/collect.py:121
msgid "the host name can be an IP" msgid "the value of the {0}"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:67 #: src/rougail/output_doc/collect.py:130
msgid "the domain name in web address can be an IP" msgid "depends on a calculation"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:68 #: src/rougail/output_doc/collect.py:131
msgid "the domain name in web address can be only a hostname" msgid "\"{0}\" is a calculation for {1} but has no description in {2}"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:75 #: src/rougail/output_doc/collect.py:190
msgid "can be range of port" msgid "depends on an undocumented variable"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:76 #: src/rougail/output_doc/collect.py:208
msgid "can have the protocol" msgid "is \"{0}\""
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:77 #: src/rougail/output_doc/collect.py:213
msgid "port 0 is allowed" msgid "is accessible"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:78 #: src/rougail/output_doc/collect.py:215
msgid "ports 1 to 1023 are allowed" msgid "is defined"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:79 #: src/rougail/output_doc/collect.py:220
msgid "ports 1024 to 49151 are allowed" msgid "hasn't the value \"{0}\""
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:80 #: src/rougail/output_doc/collect.py:222
msgid "ports greater than 49152 are allowed" msgid "has the value \"{0}\""
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:125 #: src/rougail/output_doc/collect.py:226
msgid "mandatory" msgid "is {0}"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:126 #: src/rougail/output_doc/collect.py:228
msgid "hidden" msgid "when the variable {{0}} {0}."
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:127 #: src/rougail/output_doc/collect.py:256
msgid "disabled" msgid "the value of the variable {0} if it is defined"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:128 #: src/rougail/output_doc/collect.py:258
msgid "unique" msgid "the value of the variable {0}"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:129 #: src/rougail/output_doc/collect.py:277
msgid "auto modified" msgid "(from an undocumented variable)"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:163 #: src/rougail/output_doc/collect.py:283
msgid "Variables for \"{0}\"" msgid "{0} (from an undocumented variable)"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:180 #: src/rougail/output_doc/collect.py:287
msgid "Variables" msgid "the value of an undocumented variable"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:187 #: src/rougail/output_doc/collect.py:322
msgid "Example with mandatory variables not filled in" msgid "when the identifier is \"{0}\""
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:493 #: src/rougail/output_doc/collect.py:324
msgid "(default)" msgid "when the identifier is not \"{0}\""
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:498 #: src/rougail/output_doc/collect.py:329
msgid "Choices" msgid "the value of the identifier"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:501 #: src/rougail/output_doc/collect.py:426
msgid "Default" msgid "This family contains lists of variable blocks"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:559 #: src/rougail/output_doc/collect.py:430
msgid "the value of the variable \"{0}\"" msgid "This family builds families dynamically"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:564 #: src/rougail/output_doc/collect.py:440
#: src/rougail/output_doc/__init__.py:566 msgid "This family is a namespace"
msgid "value of the {0}"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:638 #: src/rougail/output_doc/collect.py:489
#: src/rougail/output_doc/__init__.py:651
msgid "Example" msgid "Example"
msgstr "" msgstr ""
#: src/rougail/output_doc/__init__.py:649 #: src/rougail/output_doc/collect.py:492
msgid "Examples" msgid "Examples"
msgstr "" 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
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
msgid "(default)"
msgstr ""
#: src/rougail/output_doc/utils.py:1211
msgid "{0}: {1}"
msgstr ""

View file

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

View file

@ -1,7 +1,6 @@
#!/usr/bin/env python3
""" """
Silique (https://www.silique.fr) Silique (https://www.silique.fr)
Copyright (C) 2024 Copyright (C) 2024-2026
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the under the terms of the GNU Lesser General Public License as published by the
@ -16,671 +15,9 @@ details.
You should have received a copy of the GNU Lesser General Public License 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/>. 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 rougail.error import display_xmlfiles from .doc import RougailOutputDoc
from rougail import RougailConfig, Rougail, CONVERT_OPTION from .__version__ import __version__
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 RougailOutput = RougailOutputDoc

View file

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

View file

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

@ -0,0 +1,191 @@
"""
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

@ -0,0 +1,764 @@
"""
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.unrestraint.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,8 +1,6 @@
""" """
Config file for Rougail-doc
Silique (https://www.silique.fr) Silique (https://www.silique.fr)
Copyright (C) 2024 Copyright (C) 2024-2026
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the under the terms of the GNU Lesser General Public License as published by the
@ -20,27 +18,49 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
from pathlib import Path from pathlib import Path
from rougail.utils import load_modules from rougail.utils import load_modules
from .i18n import _
ROUGAIL_VARIABLE_TYPE = (
"https://rougail.readthedocs.io/en/latest/variable.html#variables-types"
)
OUTPUTS = None OUTPUTS = None
TABULARS = None
def get_outputs() -> None: def get_outputs_or_tabulars(type_) -> None:
module_name = "rougail.doc.output" """Load all outputs or tabulars"""
module_name = f"rougail.output_doc.{type_}"
outputs = {} outputs = {}
for path in (Path(__file__).parent / "output").iterdir(): names = []
for path in (Path(__file__).parent / type_).iterdir():
name = path.name name = path.name
if not name.endswith(".py") or name.endswith("__.py"): if not name.endswith(".py") or name.endswith("__.py"):
continue continue
module = load_modules(module_name + "." + name, str(path)) module = load_modules(module_name + "." + name[:-3], str(path))
if "Formater" not in dir(module): if type_ == "output":
continue if "Formatter" not in dir(module):
level = module.Formater.level continue
obj_class = module.Formatter
elif type_ == "tabular":
if "Tabular" not in dir(module):
continue
obj_class = module.Tabular
level = obj_class.level
if level in outputs: if level in outputs:
raise Exception( raise ImportError(
f'duplicated level rougail-doc for output "{level}": {module.Formater.name} and {outputs[level].name}' _(
'duplicated level rougail-output-doc for {0} "{1}": {2} and {3}'
).format(type_, level, obj_class.name, outputs[level].name)
) )
outputs[module.Formater.level] = module.Formater 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
return {outputs[level].name: outputs[level] for level in sorted(outputs)} return {outputs[level].name: outputs[level] for level in sorted(outputs)}
@ -52,46 +72,205 @@ class OutPuts: # pylint: disable=R0903
) -> None: ) -> None:
global OUTPUTS global OUTPUTS
if OUTPUTS is None: if OUTPUTS is None:
OUTPUTS = get_outputs() OUTPUTS = get_outputs_or_tabulars("output")
def get(self) -> dict: def get(self) -> dict:
"""Get all outputs"""
return 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( def get_rougail_config(
*, *,
backward_compatibility=True, backward_compatibility=True, # pylint: disable=unused-argument
) -> dict: ) -> dict:
"""Get documentation for output_doc modules"""
outputs = list(OutPuts().get()) outputs = list(OutPuts().get())
output_format_default = outputs[0] output_format_default = outputs[0]
rougail_options = """ 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')}
doc: doc:
description: Configuration rougail-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.')}
disabled: disabled:
type: jinja jinja: |-
jinja: | {{{{ step.output is propertyerror or step.output != 'doc' }}}}
{% if step.output != 'doc' %} return_type: boolean
disabled description: {_('if "step.output" is not doc')}
{% endif %}
title_level:
description: Start title level
alternative_name: dt
default: 1
with_example:
description: Display example in documentation
negative_description: Hide example in documentation
alternative_name: de
default: false
output_format: output_format:
description: Generate document in format description: {_('the output format of the generated documentation')}
alternative_name: do alternative_name: do
default: output_format_default default: { output_format_default }
choices: choices:
""".replace( """
"output_format_default", output_format_default
)
for output in outputs: for output in outputs:
rougail_options += f" - {output}\n" 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"')}
title_level:
description: {_('Starting 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')}
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
"""
return { return {
"name": "doc", "name": "doc",
"process": "output", "process": "output",

View file

@ -0,0 +1,160 @@
"""
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

@ -0,0 +1,266 @@
"""
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 """Internationalisation utilities
Silique (https://www.silique.fr) Silique (https://www.silique.fr)
Copyright (C) 2024 Copyright (C) 2024-2026
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the under the terms of the GNU Lesser General Public License as published by the
@ -19,6 +19,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
from gettext import translation from gettext import translation
from pathlib import Path 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 _ = t.gettext

View file

@ -1,6 +1,6 @@
"""Loads output """Loads output
Silique (https://www.silique.fr) Silique (https://www.silique.fr)
Copyright (C) 2024 Copyright (C) 2024-2026
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the under the terms of the GNU Lesser General Public License as published by the

View file

@ -1,6 +1,6 @@
""" """
Silique (https://www.silique.fr) Silique (https://www.silique.fr)
Copyright (C) 2024 Copyright (C) 2024-2026
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the under the terms of the GNU Lesser General Public License as published by the
@ -16,124 +16,148 @@ 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/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from io import BytesIO
from typing import List from typing import List
from itertools import chain from ..utils import CommonFormatter, dump
from ruamel.yaml import YAML from ..i18n import _
class Formater: class Formatter(CommonFormatter):
"""The asciidoc formatter"""
name = "asciidoc" name = "asciidoc"
_tabular_name = "asciidoc"
level = 40 level = 40
def __init__(self):
self._yaml = YAML()
self._yaml.indent(mapping=2, sequence=4, offset=2)
def header(self):
return ""
def title( def title(
self, self,
title: str, title: str,
level: int, level: int,
) -> str: ) -> str:
"""Display family name as a title"""
char = "=" char = "="
return f"{char * (level + 1)} {title}\n\n" return f"{char * (level + 1)} {title}"
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( def join(
self, self,
lst: List[str], lst: List[str],
) -> str: ) -> str:
"""Display line in tabular from a list"""
string = "" string = ""
previous = "" previous = ""
for line in lst: for line in lst:
if string: if string:
if self.is_list(previous.split("\n")[-1]): if self.is_list(previous.split("\n", 1)[-1]):
string += "\n\n" string += "\n\n"
else: else:
string += " +\n" string += " +\n"
string += line string += line
previous = line previous = line
return "\n" + string return 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( def bold(
self, self,
msg: str, msg: str,
) -> str: ) -> str:
"""Set a text to bold"""
return f"**{msg}**" return f"**{msg}**"
def italic( def italic(
self, self,
msg: str, msg: str,
) -> str: ) -> str:
return f"_{msg}_" """Set a text to italic"""
return f"__{msg}__"
def dump(self, dico): def delete(
with BytesIO() as ymlfh: self,
self._yaml.dump(dico, ymlfh) msg: str,
ret = ymlfh.getvalue().decode("utf-8").strip() ) -> str:
if ret.endswith("..."): """Set a text to deleted"""
ret = ret[:-3].strip() return f"+++{msg}+++"
return ret
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"

View file

@ -0,0 +1,235 @@
"""
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) Silique (https://www.silique.fr)
Copyright (C) 2024 Copyright (C) 2024-2026
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the under the terms of the GNU Lesser General Public License as published by the
@ -16,112 +16,205 @@ 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/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from io import BytesIO from typing import List, Optional
from typing import List from html import escape
from itertools import chain
from ruamel.yaml import YAML from ..utils import dump, CommonFormatter
from ..i18n import _
class Formater: 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"""
name = "github" name = "github"
_tabular_name = "github"
level = 50 level = 50
enter_tabular = "<br/>"
def __init__(self): def __init__(self, rougailconfig, **kwarg) -> None:
self._yaml = YAML() self.max_line_variable = 0
self._yaml.indent(mapping=2, sequence=4, offset=2) self.max_line_description = 0
self.header_setted = False super().__init__(rougailconfig, **kwarg)
def header(self):
if self.header_setted:
return ""
self.header_setted = True
return "---\ngitea: none\ninclude_toc: true\n---\n"
def title( def title(
self, self,
title: str, title: str,
level: int, level: int,
collapse: bool=True,
) -> str: ) -> str:
"""Display family name as a title"""
char = "#" char = "#"
return f"{char * level} {title}\n\n" return f"{char * level} {title}"
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( def join(
self, self,
lst: List[str], lst: List[str],
) -> str: ) -> str:
return "<br/>".join(lst) """Display line in tabular from a list"""
return self.enter_tabular.join(
def to_string( [l.replace("\n", self.enter_tabular) for l in lst]
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( def bold(
self, self,
msg: str, msg: str,
) -> str: ) -> str:
"""Set a text to bold"""
return f"**{msg}**" return f"**{msg}**"
def italic( def italic(
self, self,
msg: str, msg: str,
) -> str: ) -> str:
"""Set a text to italic"""
return f"*{msg}*" return f"*{msg}*"
def dump(self, dico): def delete(
with BytesIO() as ymlfh: self,
self._yaml.dump(dico, ymlfh) msg: str,
ret = ymlfh.getvalue().decode("utf-8").strip() ) -> str:
if ret.endswith("..."): """Set a text to deleted"""
ret = ret[:-3].strip() 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
return ret 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

@ -0,0 +1,103 @@
"""
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

@ -0,0 +1,149 @@
"""
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

@ -0,0 +1,34 @@
"""
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

@ -0,0 +1,17 @@
"""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

@ -0,0 +1,94 @@
"""
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

@ -0,0 +1,84 @@
"""
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

@ -0,0 +1,117 @@
"""
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

@ -0,0 +1,83 @@
"""
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

@ -0,0 +1,66 @@
"""
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

@ -0,0 +1,41 @@
%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

@ -0,0 +1,21 @@
%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

@ -0,0 +1,20 @@
== 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

@ -0,0 +1,9 @@
<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

@ -0,0 +1,14 @@
<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

@ -0,0 +1,7 @@
# 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

@ -0,0 +1,23 @@
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

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

View file

@ -0,0 +1,11 @@
%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

@ -0,0 +1,14 @@
== 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

@ -0,0 +1,13 @@
<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

@ -0,0 +1,14 @@
<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

@ -0,0 +1,9 @@
# 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

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

View file

@ -0,0 +1,41 @@
%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

@ -0,0 +1,39 @@
%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

@ -0,0 +1,8 @@
== 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

@ -0,0 +1,7 @@
<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

@ -0,0 +1,10 @@
<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

@ -0,0 +1,5 @@
# 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

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

View file

@ -0,0 +1,11 @@
%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

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

View file

@ -0,0 +1,14 @@
== 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

@ -0,0 +1,13 @@
<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

@ -0,0 +1,14 @@
<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

@ -0,0 +1,9 @@
# 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

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

View file

@ -0,0 +1,43 @@
%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

@ -0,0 +1,39 @@
%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

@ -0,0 +1,10 @@
== 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

@ -0,0 +1,8 @@
<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

@ -0,0 +1,11 @@
<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

@ -0,0 +1,6 @@
# 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

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

View file

@ -0,0 +1,21 @@
%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

@ -0,0 +1,41 @@
%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

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,39 @@
%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

@ -0,0 +1,41 @@
%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

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,39 @@
%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

@ -0,0 +1,43 @@
%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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,8 @@
== 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

@ -0,0 +1,7 @@
<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

@ -0,0 +1,10 @@
<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

@ -0,0 +1,5 @@
# 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

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

View file

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

View file

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

View file

@ -0,0 +1,9 @@
== 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

@ -0,0 +1,7 @@
<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

@ -0,0 +1,10 @@
<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

@ -0,0 +1,5 @@
# 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