Skip to content

Commit 63215b4

Browse files
authored
Add automatic manpage generation (#234)
- add manpage generation step to our custom Jekyll module that produces manpage-compatible markdown files - add manpage generation script to our GitHub action workflow that converts the markdown files to real manpages, and stores the generated manpages in the final site - add back the dynamic version info usage in the produced site (and therefore, in the produced manpages as well)
2 parents ea8d657 + 310c410 commit 63215b4

26 files changed

+428
-252
lines changed

.github/workflows/jekyll-gh-pages.yml

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ jobs:
6868
./_tools/pack debug
6969
ls -AlR assets/js
7070
71+
# Update the site.config.version info in the _config.yml based on the current syslog-ng version
72+
#
73+
./_tools/update_config_version
74+
7175
- name: Build with Jekyll
7276
# Outputs to the './_site' directory by default
7377
run: |
@@ -83,20 +87,22 @@ jobs:
8387
JEKYLL_ENV: production
8488

8589
- name: Run custom after build steps
86-
# Seems jekyll build finds references from the minimal-mistakes bundle to the assets/js folder scripts
87-
# even though most of them are packed in assets/js/main.min.js
88-
# Re-packing only the required ones and overwrite the assets/js with the minimal result needed
89-
# For more see the _tools/pack script
90-
# TODO: Eliminate this later (probably building purely from local source the minimal-mistakes will solve this)
91-
# TODO: Double-check if it's still needed
9290
run: |
91+
# Seems jekyll build finds references from the minimal-mistakes bundle to the assets/js folder scripts
92+
# even though most of them are packed in assets/js/main.min.js
93+
# Re-packing only the required ones and overwrite the assets/js with the minimal result needed
94+
# For more see the _tools/pack script
95+
# TODO: Eliminate this later (probably building purely from local source the minimal-mistakes will solve this)
96+
# TODO: Double-check if it's still needed
97+
#
9398
echo "Updating main.min.js and re-pack js scripts"
9499
pwd
95-
96100
./_tools/pack debug
97101
ls -AlR _site/assets/js
98102
99103
# Generate and add Doxygen source documentation
104+
#
105+
echo "Generating Doxygen source documentation"
100106
sudo apt-get install doxygen graphviz -y
101107
102108
OSE_SRC_REPO=https://github.com/syslog-ng/syslog-ng.git
@@ -110,6 +116,13 @@ jobs:
110116
popd
111117
rm -Rf ./_work
112118
119+
# Generate final manpages from the pre-generated special markdown files
120+
#
121+
echo "Generating manpages"
122+
INPUT_DIRECTORY=./_data/manpages
123+
OUTPUT_DIRECTORY=./_site/manpages
124+
./_tools/mangen "${INPUT_DIRECTORY}" "${OUTPUT_DIRECTORY}"
125+
113126
- name: Upload artifact
114127
# Automatically uploads an artifact from the './_site' directory by default
115128
uses: actions/upload-pages-artifact@v3

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ _data/links
3232
# _js/main.min.js
3333
assets/js
3434
_tools/package.json
35+
_data/manpages

Gemfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ gem "ostruct"
9696
# self made plugins dependencies
9797
gem "nokogiri"
9898

99+
# https://github.com/sunaku/md2man?tab=readme-ov-file
100+
gem "md2man"
101+
99102
# Gems loaded irrespective of site configuration.
100103
# If you have any other plugins, put them here!
101104
# Cf. https://jekyllrb.com/docs/plugins/installation/
@@ -111,6 +114,5 @@ group :jekyll_plugins do
111114
# https://github.com/HofiOne/minimal-mistakes
112115
#
113116
gem "jekyll-include-cache"
114-
gem "jekyll-github-metadata"
115117
# gem "github-pages"
116118
end

_config.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ exclude:
7676
#- assets/js
7777
- _js/
7878
- _tools/
79+
- _data/manpages
7980
- Gemfile
8081
- Gemfile.lock
8182
- node_modules
@@ -257,5 +258,7 @@ footer:
257258
product:
258259
name: 'syslog-ng Open Source Edition'
259260
short_name: 'syslog-ng OSE'
261+
# NOTE: This is updated automatically in the GitHub workflow (jekyll-gh-pages.yml) from the current syslog-ng version
262+
version: '4.9.0'
260263

261264
repository: syslog-ng/syslog-ng.github.io

_data/link_aliases.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
# Any not enclosed strings will be matched exactly like written.
44
#
55

6+
adm-guide:
7+
aliases: [ "/[Aa]dministration [Gg]uide/", "/[Aa]dministrator [Gg]uide/", "/syslog-ng OSE [Aa]dministration [Gg]uide", "/syslog-ng OSE [Aa]dministrator [Gg]uide" ]
8+
69
adm-temp-macro-ose:
710
aliases: [ "/[Mm]acros/" ]
811

_data/navigation.yml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,29 +1068,29 @@ admin-guide-nav:
10681068
url: /admin-guide/190_The_syslog-ng_manual_pages/README
10691069
subnav:
10701070
- title: "The dqtool tool manual page"
1071-
url: /admin-guide/190_The_syslog-ng_manual_pages/000_dqtool
1071+
url: /admin-guide/190_The_syslog-ng_manual_pages/001_dqtool_manual
10721072
- title: "The loggen manual page"
1073-
url: /admin-guide/190_The_syslog-ng_manual_pages/001_loggen
1073+
url: /admin-guide/190_The_syslog-ng_manual_pages/002_loggen_manual
10741074
- title: "The pdbtool manual page"
1075-
url: /admin-guide/190_The_syslog-ng_manual_pages/002_pdbtool
1075+
url: /admin-guide/190_The_syslog-ng_manual_pages/003_pdbtool_manual
10761076
- title: "The secure-logging manual page"
1077-
url: /admin-guide/190_The_syslog-ng_manual_pages/003_secure_logging_manual
1077+
url: /admin-guide/190_The_syslog-ng_manual_pages/004_secure_logging_manual
10781078
- title: "The slogencrypt manual page"
1079-
url: /admin-guide/190_The_syslog-ng_manual_pages/004_slogencrypt_manual
1079+
url: /admin-guide/190_The_syslog-ng_manual_pages/005_slogencrypt_manual
10801080
- title: "The slogkey manual page"
1081-
url: /admin-guide/190_The_syslog-ng_manual_pages/005_slogkey_manual
1081+
url: /admin-guide/190_The_syslog-ng_manual_pages/006_slogkey_manual
10821082
- title: "The slogverify manual page"
1083-
url: /admin-guide/190_The_syslog-ng_manual_pages/006_slogverify_manual
1083+
url: /admin-guide/190_The_syslog-ng_manual_pages/007_slogverify_manual
10841084
- title: "The {{ site.product.short_name }} control tool manual page"
1085-
url: /admin-guide/190_The_syslog-ng_manual_pages/007_syslog-ng_control_tool
1085+
url: /admin-guide/190_The_syslog-ng_manual_pages/008_syslog-ng_control_tool_manual
10861086
- title: "The syslog-debun manual page"
1087-
url: /admin-guide/190_The_syslog-ng_manual_pages/008_syslog_debun_tool
1087+
url: /admin-guide/190_The_syslog-ng_manual_pages/009_syslog_debun_tool_manual
10881088
- title: "The {{ site.product.short_name }} manual page"
1089-
url: /admin-guide/190_The_syslog-ng_manual_pages/009_syslog-ng_manual
1089+
url: /admin-guide/190_The_syslog-ng_manual_pages/010_syslog-ng_manual
10901090
- title: "The syslog-ng.conf manual page"
1091-
url: /admin-guide/190_The_syslog-ng_manual_pages/010_syslog-ng_conf
1091+
url: /admin-guide/190_The_syslog-ng_manual_pages/011_syslog-ng_conf
10921092
- title: "The persist-tool manual page"
1093-
url: /admin-guide/190_The_syslog-ng_manual_pages/011_persist-tool
1093+
url: /admin-guide/190_The_syslog-ng_manual_pages/012_persist-tool_manual
10941094
- title: "About us"
10951095
url: /admin-guide/200_About/README
10961096
subnav:
Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1-
## See also
1+
**NOTE:**
2+
If you experience any problems or need help with {{ site.product.short_name }}, see the *{{ site.product.short_name }} Administration Guide*[1], or visit the *{{ site.product.short_name }} mailing list*[2].
3+
For news and notifications about {{ site.product.short_name }}, visit the *{{ site.product.short_name }} blogs*[3].
4+
{: .notice--info}
25

3-
The syslog-ng.conf manual page
4-
The {{ site.product.short_name }} manual page
6+
## AUTHOR
7+
This manual page was generated from the *{{ site.product.short_name }} Administration Guide*[1], which was written by several contributors to whom we'd like to extend our sincere thanks.
58

6-
>**NOTE:**
7-
>If you experience any problems or need help with {{ site.product.short_name }}, visit
8-
>the {{ site.product.short_name }} mailing list.
9-
>
10-
>For news and notifications about {{ site.product.short_name }}, visit the syslog-ng blogs.
11-
{: .notice--info}
9+
## COPYRIGHT
10+
## NOTES
11+
12+
[1] `{{ site.product.short_name }} Administration Guide`
13+
https://syslog-ng.github.io/admin-guide/README
14+
15+
[2] `{{ site.product.short_name }} mailing list`
16+
https://lists.balabit.hu/mailman/listinfo/syslog-ng
17+
18+
[3] `{{ site.product.short_name }} blogs`
19+
https://syslog-ng.com/blog/

_plugins/generate_tooltips.rb

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@
22
require 'liquid'
33

44
module Jekyll
5+
class SyslogNGTools
6+
class << self
7+
public
8+
9+
def write_to_file(file_path, content)
10+
File.open(file_path, "w") do |file|
11+
file.write(content)
12+
end
13+
end
14+
15+
end # self
16+
end # SyslogNGTools
17+
518
class TooltipGen
619
class << self
720

@@ -250,12 +263,6 @@ def process_page(page)
250263
page.content = parts.join
251264
end
252265

253-
def write_to_file(file_path, content)
254-
File.open(file_path, "w") do |file|
255-
file.write(content)
256-
end
257-
end
258-
259266
def process_nav_link_items(items, ndx, nav_links_dictionary)
260267
items.each do |item|
261268
item['nav_ndx'] = ndx
@@ -397,14 +404,66 @@ def generate_tooltips(page, write_back)
397404
#puts "\n\n\n" + page.content
398405

399406
if write_back
400-
write_to_file(page.path, page.content)
407+
SyslogNGTools.write_to_file(page.path, page.content)
401408
end
402409

403410
puts "-----------"
404411
end # def generate_tooltips
405412

406413
end # class << self
407414
end # class TooltipGen
415+
416+
class ManpageGen
417+
class << self
418+
419+
private
420+
421+
public
422+
def generate_manpage(page, manpages_dir)
423+
puts "collection: " + (page.respond_to?(:collection) ? page.collection.label : "") + ", ndx: #{page.data["nav_ndx"]}, relative_path: #{page.relative_path}"
424+
425+
FileUtils.mkdir_p(manpages_dir)
426+
427+
page_id = page.data['id']
428+
page_links = page.data["page_links"]
429+
version_string = page.site.config['product']['version']
430+
link_data = page_links[page_id]
431+
title = link_data["title"][0] # link_data["title"] is an array of titles that all must be represented by ID already in the filtered_page_ids_sorted_by_title_len array
432+
433+
# Remove the description rendering helper part from the manpage content
434+
page_content = page.content
435+
pattern = /^.*#{Regexp.escape(JekyllTooltipGen_description_start_tag)}.*$\n?/
436+
page_content = page_content.gsub(pattern, '')
437+
page_content = page_content.gsub(JekyllTooltipGen_description_end_tag, '')
438+
439+
# Compose a manpage header for md2man like
440+
#
441+
# manname manid "11 MARCH 1969" 4.9.0 "title"
442+
# "======================================="
443+
#
444+
# "## NAME"
445+
# description
446+
#
447+
date_str = Time.now.strftime("%d %B %Y")
448+
manpage_header = "#{page.data["manname"]} #{page.data["manid"]} \"#{date_str}\" #{version_string} \"#{title}\"\n=======================================\n\n"
449+
if page.data["description"] && false == page.data["description"].empty?
450+
manpage_header = manpage_header + "## NAME\n" + page.data["description"] + "\n\n"
451+
end
452+
453+
page_content = manpage_header + page_content
454+
# TODO: Check why these are not rendered yet
455+
# Remove some special, not yet rendered liquid, markdown notations, we do not want in the manpage output either
456+
page_content = page_content.gsub(/\{\:[^}]*\}/, "")
457+
458+
outfile = File.join(manpages_dir, File.basename(page.path))
459+
SyslogNGTools.write_to_file(outfile, page_content)
460+
461+
puts "-----------"
462+
end # def generate_tooltips
463+
464+
end # class << self
465+
end # ManpageGen
466+
408467
end # module jekyll
409468

410469
def JekyllTooltipGen_debug_page_info(page, details = true)
@@ -485,7 +544,7 @@ def JekyllTooltipGen_hack_description_in(page_has_subtitle, page_has_description
485544
# This is used now to
486545
# - set the page nav_ndx correctly to support our custom bottom collection elements navigator
487546
# - set additional page data elements that will be used during all the passes
488-
# - add the description to the beginning of the page.content to get it rendred correclty the same way, together with the page content
547+
# - add the description to the beginning of the page.content to get it rendered correctly the same way, together with the page content
489548
#
490549
# NOTE: Do not use this site based enumeration directly for the page content manipulation as well
491550
# as that needs proper per-page payload data (or TODO: figure out how to get it in that case properly)
@@ -532,10 +591,13 @@ def JekyllTooltipGen_hack_description_in(page_has_subtitle, page_has_description
532591
end
533592
end
534593

594+
JekyllManpageGen_manpages_folder = '_data/manpages'
595+
535596
# 3rd pass
536597
#
537598
# This is used now to
538599
# - render the page content manually and create the autolinks and tooltips
600+
# - create manpage input markdown files for the manual pages
539601
#
540602
Jekyll::Hooks.register [:pages, :documents], :pre_render do |page, payload|
541603
next if false == $JekyllTooltipGen_should_build_tooltips
@@ -555,8 +617,16 @@ def JekyllTooltipGen_hack_description_in(page_has_subtitle, page_has_description
555617
}
556618
page.content = template.render!(payload, info)
557619

558-
Jekyll::TooltipGen.generate_tooltips(page, $JekyllTooltipGen_should_build_persistent_tooltips)
620+
# Generate a manpage input markdown file if manid is defined in the page front-matter
621+
if page.data['manid']
622+
if page.data["manname"] == nil
623+
puts "Error: manid found without manname in page: #{page.relative_path}"
624+
exit 5
625+
end
626+
Jekyll::ManpageGen.generate_manpage(page, JekyllManpageGen_manpages_folder)
627+
end
559628

629+
Jekyll::TooltipGen.generate_tooltips(page, $JekyllTooltipGen_should_build_persistent_tooltips)
560630
page.content = page.content.gsub(JekyllTooltipGen_description_start_tag, '<p id="page-description">')
561631
page.content = page.content.gsub(JekyllTooltipGen_description_end_tag, '</p>')
562632
end

_tools/mangen

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/bin/bash
2+
3+
process_params()
4+
{
5+
mkdir -p ${OUTPUT_DIRECTORY} || true
6+
7+
for FILE in $(/bin/ls ${INPUT_DIRECTORY}/*.md); do
8+
echo "Processing ${FILE} file..."
9+
BASENAME=$(basename "${FILE}")
10+
OUTPUT_FILE_TYPE=$([[ $BASENAME == *_config ]] && echo 5 || echo 1)
11+
MANNAME=$(head -n 1 "${FILE}" | awk '{print $1}')
12+
13+
bundle exec md2man-roff ${FILE} > ${OUTPUT_DIRECTORY}/${MANNAME}.${OUTPUT_FILE_TYPE}
14+
done
15+
16+
}
17+
18+
19+
# Check for the correct number of command-line parameters
20+
if [ "$#" -lt 2 ]; then
21+
echo "Usage: $0 <input_folder> <output_folder>"
22+
exit 1
23+
fi
24+
25+
INPUT_DIRECTORY="${1}"
26+
OUTPUT_DIRECTORY="${2}"
27+
28+
process_params "$@"
29+
30+
exit 0

_tools/update_config_version

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
echo "Updating version info"
2+
3+
VERSION=$(curl -s https://raw.githubusercontent.com/syslog-ng/syslog-ng/develop/VERSION.txt)
4+
sed -E "s/(version: ')[0-9]+\.[0-9]+\.[0-9]+(')/\1$VERSION\2/" _config.yml > _config.yml.new
5+
6+
mv -f _config.yml.new _config.yml
7+
8+
echo "Version set to $VERSION"
9+
grep 'version:' _config.yml

0 commit comments

Comments
 (0)