bashly 1.0.7 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -1
  3. data/lib/bashly/cli.rb +1 -0
  4. data/lib/bashly/commands/completions.rb +1 -1
  5. data/lib/bashly/commands/render.rb +103 -0
  6. data/lib/bashly/concerns/validation_helpers.rb +1 -1
  7. data/lib/bashly/config.rb +0 -2
  8. data/lib/bashly/extensions/string.rb +17 -1
  9. data/lib/bashly/extensions/yaml.rb +4 -1
  10. data/lib/bashly/libraries/config/config.sh +74 -94
  11. data/lib/bashly/libraries/ini/ini.sh +110 -0
  12. data/lib/bashly/libraries/libraries.yml +40 -1
  13. data/lib/bashly/libraries/render/mandoc/README.md +45 -0
  14. data/lib/bashly/libraries/render/mandoc/mandoc.gtx +196 -0
  15. data/lib/bashly/libraries/render/mandoc/render.rb +34 -0
  16. data/lib/bashly/libraries/render/mandoc/summary.txt +1 -0
  17. data/lib/bashly/libraries/render/markdown/README.md +42 -0
  18. data/lib/bashly/libraries/render/markdown/markdown.gtx +186 -0
  19. data/lib/bashly/libraries/render/markdown/render.rb +23 -0
  20. data/lib/bashly/libraries/render/markdown/summary.txt +1 -0
  21. data/lib/bashly/refinements/compose_refinements.rb +0 -2
  22. data/lib/bashly/render_context.rb +30 -0
  23. data/lib/bashly/render_source.rb +71 -0
  24. data/lib/bashly/script/base.rb +2 -1
  25. data/lib/bashly/script/command.rb +17 -0
  26. data/lib/bashly/version.rb +1 -1
  27. data/lib/bashly/views/command/dependencies_filter.gtx +1 -1
  28. data/lib/bashly/views/command/footer.gtx +1 -1
  29. data/lib/bashly/views/command/parse_requirements_while.gtx +1 -1
  30. data/lib/bashly/views/command/usage.gtx +2 -2
  31. data/lib/bashly/views/command/usage_commands.gtx +2 -2
  32. data/lib/bashly.rb +56 -11
  33. metadata +41 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a333ce419f5ba64e38000497f245fc5baf822243cd2765c1805ebdf6de2e3b46
4
- data.tar.gz: 0c9ab24cc2cecd88cbd20a06ab11028740ce3000aec75080ca9a12c6769110c1
3
+ metadata.gz: d333139a3555fdc50cdb3ddf21119712fcada4ab837f5703f29529f346c6ad24
4
+ data.tar.gz: 0a40e42bfa542ed5d4f8d59792aa2a19518ae1c9098db0309f9349db391c74b2
5
5
  SHA512:
6
- metadata.gz: ff95fd919a29a16d610d8f3c069f2de17b9984a41251de56e484a5dc49e86dd4114934c47ccb2274521f7f8bd5078287a54ef10478c5e18b6c8a93f462f1c503
7
- data.tar.gz: 65a1be57601cc7a560a19ef48dc75b09647244fe477327f23ae52a37f8114afca4ee3871a1f72e1b046589e252a57701956a93e9015907bf76fd24455da341ff
6
+ metadata.gz: e601e098208e0a5de186279e67c001ff58c44536f09e5cea6815722e9bef3ec3dc1b257c1b9ca2267e94977f05514916a66f03721c88c5a795cab93e8eadb20d
7
+ data.tar.gz: 670bcae80903cdabc5d76b5139b1c6d80b1ee3ca33af03078a340a847c4ef1385ca74ca08b2b0a274845f0be5ecfc7ecd9822575b8f8ea8cb3592b821df22760
data/README.md CHANGED
@@ -71,7 +71,8 @@ Bashly is responsible for:
71
71
  - **Config file management** (INI format).
72
72
  - **YAML parsing**.
73
73
  - **Bash completions**.
74
- - and more.
74
+ - *and more*.
75
+ - Auto-generating **markdown and man page documentation** for your script.
75
76
 
76
77
  ## Contributing / Support
77
78
 
data/lib/bashly/cli.rb CHANGED
@@ -16,6 +16,7 @@ module Bashly
16
16
  runner.route 'add', to: Commands::Add
17
17
  runner.route 'doc', to: Commands::Doc
18
18
  runner.route 'completions', to: Commands::Completions
19
+ runner.route 'render', to: Commands::Render
19
20
  runner.route 'shell', to: Commands::Shell unless ENV['BASHLY_SHELL']
20
21
 
21
22
  runner
@@ -4,7 +4,7 @@ module Bashly
4
4
  summary 'Install bash completions for bashly itself'
5
5
  help 'Display the bash completions script or install it directly to your bash completions directory'
6
6
 
7
- usage 'bashly completions [--install --uninstall]'
7
+ usage 'bashly completions [--install|--uninstall]'
8
8
  usage 'bashly completions (-h|--help)'
9
9
 
10
10
  option '-i --install', 'Install the completions script to your bash completions directory'
@@ -0,0 +1,103 @@
1
+ require 'filewatcher'
2
+ require 'tty-markdown'
3
+
4
+ module Bashly
5
+ module Commands
6
+ class Render < Base
7
+ help 'Render the bashly data structure using cutsom templates'
8
+
9
+ usage 'bashly render SOURCE TARGET [--watch --show PATH]'
10
+ usage 'bashly render SOURCE --about'
11
+ usage 'bashly render --list'
12
+ usage 'bashly render (-h|--help)'
13
+
14
+ param 'SOURCE', <<~HELP
15
+ An ID to an internal templates source, or a path to a custom templates directory.
16
+
17
+ A leading colon (:) denotes an internal ID (see `--list`).
18
+ HELP
19
+
20
+ param 'TARGET', 'Output directory'
21
+
22
+ option '-w --watch', 'Watch bashly.yml and the templates source for changes and render on change'
23
+ option '-s --show PATH', <<~USAGE
24
+ After rendering, show the result generated in PATH.
25
+
26
+ The provided PATH is treated as relative TARGET.
27
+
28
+ Note that this works only if the template source supports it.
29
+ USAGE
30
+
31
+ option '-l --list', 'Show list of built-in templates'
32
+ option '-a --about', 'Show information about a given templates source'
33
+
34
+ example 'bashly render --list'
35
+ example 'bashly render :markdown --about'
36
+ example 'bashly render :markdown docs --watch'
37
+ example 'bashly render :markdown docs --show "cli-download.1"'
38
+ example 'bashly render /path/to/templates ./out_path'
39
+
40
+ attr_reader :watching, :target, :source
41
+
42
+ def run
43
+ if args['--list'] then show_list
44
+ elsif args['--about'] then show_about
45
+ else
46
+ start_render
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def show_list
53
+ RenderSource.internal.each_value do |source|
54
+ say "g`:#{source.selector.to_s.ljust 10}` #{source.summary}"
55
+ end
56
+ end
57
+
58
+ def show_about
59
+ puts TTY::Markdown.parse(render_source.readme)
60
+ end
61
+
62
+ def start_render
63
+ @target = args['TARGET']
64
+ @watching = args['--watch']
65
+
66
+ render
67
+ watch if watching
68
+ end
69
+
70
+ def render
71
+ render_source.render target, show: args['--show']
72
+ end
73
+
74
+ def watch
75
+ say "g`watching`\n"
76
+
77
+ Filewatcher.new(watchables).watch do
78
+ render
79
+ say "g`waiting`\n"
80
+ end
81
+ end
82
+
83
+ def render_source
84
+ @render_source ||= begin
85
+ source = RenderSource.new selector
86
+ raise "Invalid render source: #{args['SOURCE']}" unless source.exist?
87
+
88
+ source
89
+ end
90
+ end
91
+
92
+ def selector
93
+ return args['SOURCE'] unless args['SOURCE'].start_with? ':'
94
+
95
+ args['SOURCE'][1..].to_sym
96
+ end
97
+
98
+ def watchables
99
+ @watchables ||= [Settings.config_path, render_source.path]
100
+ end
101
+ end
102
+ end
103
+ end
@@ -40,7 +40,7 @@ module Bashly
40
40
 
41
41
  return unless keys
42
42
 
43
- invalid_keys = value.keys.map(&:to_sym) - keys
43
+ invalid_keys = (value.keys.map(&:to_sym) - keys).reject { |k| k.start_with? 'x_' }
44
44
  assert invalid_keys.empty?, "#{key} contains invalid options: #{invalid_keys.join ', '}"
45
45
  end
46
46
 
data/lib/bashly/config.rb CHANGED
@@ -1,5 +1,3 @@
1
- require 'yaml'
2
-
3
1
  module Bashly
4
2
  # A convenience class to use either a hash or a filename as a configuration
5
3
  # source.
@@ -1,6 +1,18 @@
1
1
  class String
2
2
  def sanitize_for_print
3
- gsub("\n", '\\n').gsub('"', '\"')
3
+ gsub("\n", '\\n').gsub('"', '\"').gsub('`', '\\\\`')
4
+ end
5
+
6
+ def for_markdown
7
+ gsub('<', '\\<').gsub('>', '\\>').nl2br
8
+ end
9
+
10
+ def for_manpage
11
+ gsub('<', '\\<').gsub('>', '\\>').gsub('`', '**').gsub(" \n", "\n\n")
12
+ end
13
+
14
+ def nl2br
15
+ gsub("\n", " \n")
4
16
  end
5
17
 
6
18
  def indent(offset)
@@ -13,6 +25,10 @@ class String
13
25
  gsub(/(.)([A-Z])/, '\1_\2').gsub(/[- ]/, '_').downcase
14
26
  end
15
27
 
28
+ def to_hyphen
29
+ tr(' ', '-').gsub(/([a-z])([A-Z])/, '\1-\2').downcase
30
+ end
31
+
16
32
  def to_path
17
33
  tr(' ', '/').downcase
18
34
  end
@@ -1,9 +1,12 @@
1
+ require 'erb'
2
+ require 'yaml'
3
+
1
4
  module YAML
2
5
  # We trust our loaded YAMLs
3
6
  # This patch is due to https://bugs.ruby-lang.org/issues/17866
4
7
  # StackOverflow: https://stackoverflow.com/questions/71191685/visit-psych-nodes-alias-unknown-alias-default-psychbadalias/71192990#71192990
5
8
  class << self
6
- alias load unsafe_load
9
+ alias load unsafe_load if YAML.respond_to? :unsafe_load
7
10
 
8
11
  def load_erb_file(path)
9
12
  YAML.load ERB.new(File.read(path)).result
@@ -1,128 +1,108 @@
1
- ## Config functions [@bashly-upgrade config]
1
+ ## Config (INI) functions [@bashly-upgrade config]
2
2
  ## This file is a part of Bashly standard library
3
3
  ##
4
4
  ## Usage:
5
- ## - In your script, set the CONFIG_FILE variable. For rxample:
6
- ## CONFIG_FILE=settings.ini.
7
- ## If it is unset, it will default to 'config.ini'.
8
- ## - Use any of the functions below to access the config file.
9
5
  ##
10
- ## Create a new config file.
11
- ## There is normally no need to use this function, it is used by other
12
- ## functions as needed.
6
+ ## - Set the global variable CONFIG_FILE to the path of your INI file somewhere
7
+ ## in your script (for example, in src/initialize.sh).
8
+ ## - Use any of the following functions to access and manipulate the values.
9
+ ## - INI sections are optional (i.e., sectionless key=value pairs are allowed).
13
10
  ##
14
- config_init() {
15
- CONFIG_FILE=${CONFIG_FILE:=config.ini}
16
- [[ -f "$CONFIG_FILE" ]] || touch "$CONFIG_FILE"
11
+
12
+ ## Show all the key=value pairs from your config file
13
+ config_show() {
14
+ config_load
15
+ ini_show
17
16
  }
18
17
 
19
- ## Get a value from the config.
20
- ## Usage: result=$(config_get hello)
18
+ ## Get a single value from the config file:
19
+ ##
20
+ ## config_get login.email
21
+ ##
22
+ ## Get the value or a default one if it is not set:
23
+ ##
24
+ ## config_get login.user guest
25
+ ##
26
+ ## Assign the result to a variable:
27
+ ##
28
+ ## theme="$(config_get interface.theme)"
29
+ ##
21
30
  config_get() {
22
- local key=$1
23
- local regex="^$key *= *(.+)$"
24
- local value=""
25
-
26
- config_init
31
+ local key="$1"
32
+ local default_value="$2"
27
33
 
28
- while IFS= read -r line || [ -n "$line" ]; do
29
- if [[ $line =~ $regex ]]; then
30
- value="${BASH_REMATCH[1]}"
31
- break
32
- fi
33
- done <"$CONFIG_FILE"
34
-
35
- echo "$value"
34
+ config_load
35
+ echo "${ini["$key"]:-$default_value}"
36
36
  }
37
37
 
38
- ## Add or update a key=value pair in the config.
39
- ## Usage: config_set key value
38
+ ## Create/update a key=value pair:
39
+ ##
40
+ ## config_set cloud.provider aws
41
+ ##
40
42
  config_set() {
41
- local key=$1
43
+ local key="$1"
42
44
  shift
43
45
  local value="$*"
44
46
 
45
- config_init
46
-
47
- local regex="^($key) *= *.+$"
48
- local output=""
49
- local found_key=""
50
- local newline
51
-
52
- while IFS= read -r line || [ -n "$line" ]; do
53
- newline=$line
54
- if [[ $line =~ $regex ]]; then
55
- found_key="${BASH_REMATCH[1]}"
56
- newline="$key = $value"
57
- output="$output$newline\n"
58
- elif [[ $line ]]; then
59
- output="$output$line\n"
60
- fi
61
- done <"$CONFIG_FILE"
62
-
63
- if [[ -z $found_key ]]; then
64
- output="$output$key = $value\n"
65
- fi
66
-
67
- printf "%b\n" "$output" >"$CONFIG_FILE"
47
+ config_load
48
+ ini["$key"]="$value"
49
+ config_save
68
50
  }
69
51
 
70
- ## Delete a key from the config.
71
- ## Usage: config_del key
52
+ ## Delete a key=value pair:
53
+ ##
54
+ ## config_del login.email
55
+ ##
72
56
  config_del() {
73
- local key=$1
57
+ local key="$1"
74
58
 
75
- local regex="^($key) *="
76
- local output=""
77
-
78
- config_init
79
-
80
- while IFS= read -r line || [ -n "$line" ]; do
81
- if [[ $line ]] && [[ ! $line =~ $regex ]]; then
82
- output="$output$line\n"
83
- fi
84
- done <"$CONFIG_FILE"
85
-
86
- printf "%b\n" "$output" >"$CONFIG_FILE"
87
- }
88
-
89
- ## Show the config file
90
- config_show() {
91
- config_init
92
- cat "$CONFIG_FILE"
59
+ config_load
60
+ unset "ini[$key]"
61
+ config_save
93
62
  }
94
63
 
95
- ## Return an array of the keys in the config file.
96
- ## Usage:
64
+ ## Get an array of all keys:
97
65
  ##
98
- ## for k in $(config_keys); do
99
- ## echo "- $k = $(config_get "$k")";
66
+ ## for key in $(config_keys); do
67
+ ## echo "- $key = $(config_get "$key")";
100
68
  ## done
101
69
  ##
102
70
  config_keys() {
103
- local regex="^([a-zA-Z0-9_\-\/\.]+) *="
104
-
105
- config_init
106
-
107
- local keys=()
108
- local key
109
-
110
- while IFS= read -r line || [ -n "$line" ]; do
111
- if [[ $line =~ $regex ]]; then
112
- key="${BASH_REMATCH[1]}"
113
- keys+=("$key")
114
- fi
115
- done <"$CONFIG_FILE"
116
- echo "${keys[@]}"
71
+ config_load
72
+ ini_keys
117
73
  }
118
74
 
119
- ## Returns true if the specified key exists in the config file.
120
- ## Usage:
75
+ ## Check if a key exists:
121
76
  ##
122
- ## if config_has_key "key"; then
77
+ ## if config_has_key login.password; then
123
78
  ## echo "key exists"
124
79
  ## fi
125
80
  ##
126
81
  config_has_key() {
127
82
  [[ $(config_get "$1") ]]
128
83
  }
84
+
85
+ ## Force-load from file
86
+ ## This should normally not be called, unless you suspect that the INI file
87
+ ## was modified by external means during the run of your script.
88
+ config_reload() {
89
+ declare -g config_loaded=false
90
+ config_load
91
+ }
92
+
93
+ ## Load an INI file (unless loaded) and populate the associative array
94
+ ## NOTE: Normally there is no need to call this function, it is called as needed
95
+ config_load() {
96
+ [[ "$config_loaded" == "true" ]] && return
97
+
98
+ declare -g CONFIG_FILE=${CONFIG_FILE:=config.ini}
99
+ declare -g config_loaded=true
100
+ [[ -f "$CONFIG_FILE" ]] || touch "$CONFIG_FILE"
101
+ ini_load "$CONFIG_FILE"
102
+ }
103
+
104
+ ## Save the associative array back to a file
105
+ ## NOTE: Normally there is no need to call this function, it is called as needed
106
+ config_save() {
107
+ ini_save "$CONFIG_FILE"
108
+ }
@@ -0,0 +1,110 @@
1
+ ## INI functions [@bashly-upgrade ini]
2
+ ## This file is a part of Bashly standard library
3
+ ##
4
+ ## Usage:
5
+ ##
6
+ ## - In your script, call `ini_load path/to/config.ini`.
7
+ ## - A global associative array named `ini` will become available to you,
8
+ ## - When updating any of the associative array's values, call
9
+ ## `ini_save path/to/config.ini` to save the data.
10
+ ## - INI sections are optional.
11
+ ##
12
+ ## Get a value:
13
+ ##
14
+ ## ${ini[section1.key1]} # for keys under a [section]
15
+ ## ${ini[key1]} # for keys not under a [section]
16
+ ## ${ini[key1]:-default} # get a default value if the INI key is unset
17
+ ##
18
+ ## Update/create a value:
19
+ ##
20
+ ## ini[section1.key1]="value"
21
+ ## ini_save path/to/config.ini
22
+ ##
23
+ ## Delete a value
24
+ ##
25
+ ## unset ini[section1.key1]
26
+ ## ini_save path/to/config.ini
27
+ ##
28
+
29
+ ## Load an INI file and populate the associative array `ini`.
30
+ ini_load() {
31
+ declare -gA ini
32
+
33
+ local ini_file="$1"
34
+
35
+ local section=""
36
+ local key=""
37
+ local value=""
38
+ local section_regex="^\[(.+)\]"
39
+ local key_regex="^([^ =]+) *= *(.*) *$"
40
+ local comment_regex="^;"
41
+
42
+ while IFS= read -r line; do
43
+ if [[ $line =~ $comment_regex ]]; then
44
+ continue
45
+ elif [[ $line =~ $section_regex ]]; then
46
+ section="${BASH_REMATCH[1]}."
47
+ elif [[ $line =~ $key_regex ]]; then
48
+ key="${BASH_REMATCH[1]}"
49
+ value="${BASH_REMATCH[2]}"
50
+ ini["${section}${key}"]="$value"
51
+ fi
52
+ done <"$ini_file"
53
+ }
54
+
55
+ ## Save the associative array `ini` back to a file
56
+ ini_save() {
57
+ declare -gA ini
58
+
59
+ local ini_file="$1"
60
+
61
+ local current_section=""
62
+ local has_free_keys=false
63
+
64
+ rm -f "$ini_file"
65
+
66
+ for key in $(ini_keys); do
67
+ [[ $key == *.* ]] && continue
68
+ has_free_keys=true
69
+ value="${ini[$key]}"
70
+ echo "$key = $value" >>"$ini_file"
71
+ done
72
+
73
+ [[ "${has_free_keys}" == "true" ]] && echo >>"$ini_file"
74
+
75
+ for key in $(ini_keys); do
76
+ [[ $key == *.* ]] || continue
77
+ value="${ini[$key]}"
78
+ IFS="." read -r section_name key_name <<<"$key"
79
+
80
+ if [[ "$current_section" != "$section_name" ]]; then
81
+ [[ $current_section ]] && echo >>"$ini_file"
82
+ echo "[$section_name]" >>"$ini_file"
83
+ current_section="$section_name"
84
+ fi
85
+
86
+ echo "$key_name = $value" >>"$ini_file"
87
+ done
88
+ }
89
+
90
+ ## Show all loaded key-value pairs
91
+ ini_show() {
92
+ declare -gA ini
93
+
94
+ for key in $(ini_keys); do
95
+ echo "$key = ${ini[$key]}"
96
+ done
97
+ }
98
+
99
+ ## Get an array of all keys:
100
+ ##
101
+ ## for key in $(ini_keys); do
102
+ ## echo "- $key = ${ini[$key]}";
103
+ ## done
104
+ ##
105
+ ini_keys() {
106
+ declare -gA ini
107
+
108
+ local keys=("${!ini[@]}")
109
+ for a in "${keys[@]}"; do echo "$a"; done | sort
110
+ }
@@ -20,10 +20,12 @@ completions_yaml:
20
20
  handler: Bashly::Libraries::CompletionsYAML
21
21
 
22
22
  config:
23
- help: Add standard functions for handling INI files to the lib directory.
23
+ help: Add functions for handling INI configuration files to the lib directory.
24
24
  files:
25
25
  - source: "config/config.sh"
26
26
  target: "%{user_lib_dir}/config.%{user_ext}"
27
+ - source: "ini/ini.sh"
28
+ target: "%{user_lib_dir}/ini.%{user_ext}"
27
29
 
28
30
  help:
29
31
  help: Add a help command, in addition to the standard --help flag.
@@ -39,6 +41,12 @@ hooks:
39
41
  - source: "hooks/after.sh"
40
42
  target: "%{user_source_dir}/after.%{user_ext}"
41
43
 
44
+ ini:
45
+ help: Add low level functions for reading/writing INI files to the lib directory.
46
+ files:
47
+ - source: "ini/ini.sh"
48
+ target: "%{user_lib_dir}/ini.%{user_ext}"
49
+
42
50
  lib:
43
51
  help: |-
44
52
  Create the lib directory for any additional user scripts.
@@ -48,6 +56,37 @@ lib:
48
56
  - source: "lib/sample_function.sh"
49
57
  target: "%{user_lib_dir}/sample_function.%{user_ext}"
50
58
 
59
+ render_markdown:
60
+ help: Copy the markdown templates to your project, allowing you to customize the markdown documentation output.
61
+ skip_src_check: true
62
+ files:
63
+ - source: "render/markdown/README.md"
64
+ target: "templates/markdown/README.md"
65
+ - source: "render/markdown/markdown.gtx"
66
+ target: "templates/markdown/markdown.gtx"
67
+ - source: "render/markdown/render.rb"
68
+ target: "templates/markdown/render.rb"
69
+ post_install_message: |
70
+ Generate your markdown documentation by running:
71
+
72
+ m`$ bashly render templates/markdown docs`
73
+
74
+ render_mandoc:
75
+ help: Copy the mandoc templates to your project, allowing you to customize the man documentation output.
76
+ skip_src_check: true
77
+ files:
78
+ - source: "render/mandoc/README.md"
79
+ target: "templates/mandoc/README.md"
80
+ - source: "render/mandoc/mandoc.gtx"
81
+ target: "templates/mandoc/mandoc.gtx"
82
+ - source: "render/mandoc/render.rb"
83
+ target: "templates/mandoc/render.rb"
84
+ post_install_message: |
85
+ Note that this template requires pandoc.
86
+ Generate your man pages by running:
87
+
88
+ m`$ bashly render templates/mandoc docs`
89
+
51
90
  settings:
52
91
  help: Copy a sample settings.yml file to your project, allowing you to customize some bashly options.
53
92
  skip_src_check: true
@@ -0,0 +1,45 @@
1
+ # Render mandoc
2
+
3
+ Render man pages for your script.
4
+
5
+ Note that this renderer will render specially formatted markdown documents and
6
+ will then use [pandoc](https://command-not-found.com/pandoc) to convert them.
7
+
8
+ ## Usage
9
+
10
+ ```bash
11
+ # Generate all man pages to the ./docs directory
12
+ $ bashly render :mandoc docs
13
+
14
+ # Generate on change, and show one of the files
15
+ $ bashly render :mandoc docs --watch --show cli-download.1
16
+ ```
17
+
18
+ ## Supported custom definitions
19
+
20
+ Add these definitions to your `bashly.yml` to render them in your
21
+ markdown:
22
+
23
+ ### Footer: `x_mandoc_footer`
24
+
25
+ Add additional sections to your man pages. This field is expected
26
+ to be in markdown format.
27
+
28
+ #### Example
29
+
30
+ ```yaml
31
+ x_mandoc_footer: |-
32
+ # ISSUE TRACKER
33
+
34
+ Report issues at <https://github.com/lanalang/smallville>
35
+ ```
36
+
37
+ ### Authors: `x_mandoc_authors`
38
+
39
+ Add an authors string to your man pages.
40
+
41
+ #### Example
42
+
43
+ ```yaml
44
+ x_mandoc_authors: Lana Lang
45
+ ```