mirror of
https://github.com/Icinga/icinga-docs-tools.git
synced 2025-09-29 04:39:04 +02:00
This update enables markdown files in the template directory to include other files from the same directory, providing full support for Jinja templates. Previously, when a file included another file that was naturally ordered before it, the templates were already resolved due to in-place modifications. Now, rather than modifying template files directly and renaming them later, they are written to the target location instead.
276 lines
9.9 KiB
Ruby
Executable File
276 lines
9.9 KiB
Ruby
Executable File
#!/usr/bin/env ruby
|
|
require 'optparse'
|
|
require 'fileutils'
|
|
require 'yaml'
|
|
require 'date'
|
|
|
|
options = {}
|
|
OptionParser.new { |opts|
|
|
opts.banner = "Usage: #{File.basename($0)} -c config.yml -t mkdocs.template.yml}"
|
|
|
|
options[:config] = 'config.yml'
|
|
opts.on('-f',
|
|
'--config FILENAME',
|
|
'Configuration file with project definition. Defaults to "config.yml"') do |config|
|
|
options[:config] = config
|
|
end
|
|
|
|
options[:template] = 'mkdocs.template.yml'
|
|
opts.on('-t',
|
|
'--template FILENAME',
|
|
'This file is used as template for the generated mkdocs.yaml. Defaults to "mkdocs.template.yml"') do |template|
|
|
options[:template] = template
|
|
end
|
|
|
|
options[:skip_clone] = false
|
|
opts.on('-s',
|
|
'--skip-clone',
|
|
'Do not update the repository. This option only works if the repo was already cloned once.') do |skip|
|
|
options[:skip_clone] = true
|
|
end
|
|
|
|
opts.on_tail('-h', '--help', 'Show this message') do
|
|
puts opts
|
|
exit
|
|
end
|
|
}.parse!
|
|
|
|
def cleanup_and_clone(clone_target, git, ref, inject_central_docs = false)
|
|
@git_options = "-b #{ref}" if ref =~ /tags/
|
|
if !File.directory?(clone_target)
|
|
puts "Cloning #{git} to #{clone_target} ..."
|
|
FileUtils.mkdir_p(clone_target)
|
|
%x(git clone #{git} #{clone_target})
|
|
|
|
puts "Checking out #{ref}"
|
|
%x(git --git-dir=#{clone_target}/.git --work-tree=#{clone_target} checkout #{ref} #{@git_options})
|
|
|
|
if inject_central_docs
|
|
puts "Inject Central Docs"
|
|
%x(git config --global user.email "info@icinga.com")
|
|
%x(git config --global user.name "Icinga Docs Tool")
|
|
%x(git --git-dir=#{clone_target}/.git --work-tree=#{clone_target} remote add -f package-installation-docs https://github.com/Icinga/package-installation-docs.git)
|
|
%x(git --git-dir=#{clone_target}/.git --work-tree=#{clone_target} merge --squash --allow-unrelated-histories -s subtree -Xsubtree="doc/02-Installation.md.d" package-installation-docs/main)
|
|
%x(git --git-dir=#{clone_target}/.git --work-tree=#{clone_target} commit -m "Merge package installation docs")
|
|
end
|
|
else
|
|
puts "Cleaning up #{clone_target}"
|
|
FileUtils::rm_rf(clone_target)
|
|
cleanup_and_clone(clone_target, git, ref, inject_central_docs)
|
|
end
|
|
end
|
|
|
|
def titleize(string)
|
|
# Remove .md
|
|
title = string.gsub('.md', '')
|
|
|
|
# Remove numbering on the front
|
|
title = title.gsub(/^\d+-/, '')
|
|
|
|
# Remove dashes and underscores
|
|
title = title.gsub(/(-|_)/, ' ')
|
|
|
|
# Uppercase only first letter of each word, ignore stopwords
|
|
stopwords = ['and', 'or', 'to', 'by', 'on', 'with', 'is', 'at', 'of', 'from', 'for']
|
|
title = title.split.map { |word|
|
|
if stopwords.include?(word)
|
|
word
|
|
else
|
|
word[0].upcase + word[1..-1]
|
|
end
|
|
}.join(" ")
|
|
|
|
return title
|
|
end
|
|
|
|
def build_page_index(full_docs_dir, project_docs_dir, package = "", product = "")
|
|
pages = []
|
|
puts "Building page index from #{full_docs_dir}"
|
|
|
|
Dir.glob("#{full_docs_dir}/**", File::FNM_CASEFOLD).sort.each do |file|
|
|
next if !file.match(/.*(\d+)-(.*)$/)
|
|
|
|
filepath = file.gsub(full_docs_dir + '/', project_docs_dir + '/')
|
|
filename = filepath.match(/.*?(\d+)-(.*?)(\.d)?$/)
|
|
|
|
if(File.directory?("#{file}"))
|
|
subdirectory = []
|
|
nav_item = titleize(filename[2]) unless File.symlink?(filepath)
|
|
is_template_dir = !filename[3].nil?
|
|
|
|
Dir.glob("#{file}/*.md", File::FNM_CASEFOLD).sort.each do |subfile|
|
|
subfile_path = subfile.gsub(full_docs_dir + '/', project_docs_dir + '/')
|
|
# Get everything after last slash
|
|
subfile_name = subfile.match(/([^\/]+$)/)
|
|
if(is_template_dir)
|
|
subdir_name = File.basename(file)
|
|
new_subdir_name = subdir_name.gsub(/\.md.d$/, '')
|
|
|
|
subdir = file.gsub(subdir_name, new_subdir_name)
|
|
FileUtils.mkdir_p(subdir) unless File.directory?(subdir)
|
|
|
|
subfile = subfile.gsub(subdir_name, new_subdir_name)
|
|
|
|
%x(./parse_template.py -o "#{subfile}" -D product "#{product}" -D package "#{package}" -D icingaDocs true "#{full_docs_dir}" "#{subfile_path.gsub(/^doc\//, '')}")
|
|
|
|
content = File.read(subfile)
|
|
# Adjust self references
|
|
content = content.gsub(/\[(.*)\]\(#{filename[1]}-#{Regexp.quote(filename[2])}(.*)\)/, '[\1](\2)')
|
|
# Adjust external references
|
|
content = content.gsub(/\[(.*)\]\((?!http|#)(.*)\)/, '[\1](../\2)')
|
|
File.write(subfile, content)
|
|
|
|
subfile_path = subfile_path.gsub(subdir_name, new_subdir_name)
|
|
end
|
|
|
|
header = titleize(subfile_name[1]) unless File.symlink?(subfile)
|
|
subdirectory.push(header => subfile_path) if header
|
|
end
|
|
|
|
# Sort the "From Source" installation guide explicitly to the end
|
|
subdirectory.each_with_index do |subdirectory_element, index|
|
|
if subdirectory_element.key?("From Source")
|
|
subdirectory.append(subdirectory_element)
|
|
subdirectory.delete_at(index)
|
|
break
|
|
end
|
|
end
|
|
|
|
if(is_template_dir)
|
|
template_path = filepath.gsub(/\.d$/, '')
|
|
if(pages.include?(nav_item => template_path))
|
|
pages.delete_at(pages.find_index(nav_item => template_path))
|
|
end
|
|
|
|
# Rename template directory to mimic template references
|
|
newTemplateDirPath = file.gsub(/\.md.d$/, '')
|
|
FileUtils.rm_r(file)
|
|
|
|
# Attempt to create a index file
|
|
index_content = %x(./parse_template.py -o - -D index true #{full_docs_dir} #{template_path.gsub(/^doc\//, '')})
|
|
if(!index_content.empty?)
|
|
# Adjust self references
|
|
index_content = index_content.gsub(/\[(.*)\]\(#{filename[1]}-#{Regexp.quote(filename[2])}(.*)\)/, '[\1](\2)')
|
|
# Adjust external references
|
|
index_content = index_content.gsub(/\[(.*)\]\((?!http|#)(.*)\)/, '[\1](../\2)')
|
|
|
|
File.write(newTemplateDirPath + '/index.md', index_content)
|
|
subdirectory.unshift(filepath.gsub(/.md.d$/, '') + '/index.md')
|
|
end
|
|
end
|
|
|
|
pages.push(nav_item => subdirectory) if nav_item
|
|
else
|
|
header = titleize(filename[2]) unless File.symlink?(filepath)
|
|
pages.push(header => filepath) if header
|
|
end
|
|
end
|
|
|
|
return pages
|
|
end
|
|
|
|
def get_events(git, source_dir, categories)
|
|
events = []
|
|
event_categories = categories
|
|
clone_target = source_dir + '/events'
|
|
#cleanup_and_clone('events', clone_target, git, 'master')
|
|
event_categories.each do |category|
|
|
category_events = YAML::load_file(clone_target + '/' + category + '.yml')
|
|
if category_events
|
|
category_events_sorted = category_events.sort_by { |k| k['date'] }
|
|
category_events_sorted.each do |event|
|
|
if event['date'] > Date.today
|
|
events << event
|
|
break
|
|
else
|
|
next
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
events_sorted = events.sort_by { |k| k['date']}
|
|
|
|
events_sorted.each do |k|
|
|
k['date'] = Date::ABBR_MONTHNAMES[k['date'].month]
|
|
end
|
|
|
|
return events_sorted
|
|
end
|
|
|
|
config = YAML::load_file('config.yml')
|
|
project_config = YAML::load_file(options[:config])
|
|
mkdocs = YAML::load_file(options[:template])
|
|
mkdocs['nav'] = []
|
|
|
|
|
|
|
|
puts "== #{project_config['site_name']}"
|
|
|
|
version = if project_config['project']['latest']
|
|
'latest'
|
|
elsif project_config['project']['ref'] == 'master' or project_config['project']['ref'] == 'main'
|
|
'snapshot'
|
|
else
|
|
project_config['project']['ref'].gsub('tags/', '')
|
|
project_config['project']['ref'].gsub('support/', '')
|
|
end
|
|
|
|
source_dir = project_config['source_dir'] + '/' + project_config['project']['target']
|
|
clone_target = source_dir + '/' + version
|
|
full_docs_dir = clone_target + '/' + project_config['project']['docs_dir']
|
|
inject_central_docs = project_config['inject_central_docs']
|
|
|
|
if !options[:skip_clone]
|
|
cleanup_and_clone(clone_target,
|
|
project_config['project']['git'],
|
|
project_config['project']['ref'],
|
|
inject_central_docs)
|
|
end
|
|
|
|
main_pages = build_page_index(full_docs_dir, project_config['project']['docs_dir'], project_config['project']['package'], project_config['project']['product'])
|
|
# MKdocs allows only 'index.md' as homepage. This is a dirty workaround to use the first markdown file instead
|
|
#FileUtils.ln_s("#{clone_target}/#{main_pages[0].values[0]}", "#{clone_target}/index.md", :force => true)
|
|
index_file = "#{clone_target}/index.md"
|
|
FileUtils.cp("#{clone_target}/#{main_pages[0].values[0]}", index_file)
|
|
index_content = File.read(index_file)
|
|
index_new_content = index_content.gsub(/\(((?!http)\S+(\.md|\.png)(\w)?)/,
|
|
"(#{project_config['project']['docs_dir']}/\\1")
|
|
|
|
File.open(index_file, "w") {|file| file.puts index_new_content }
|
|
mkdocs['nav'].push('' => "index.md")
|
|
|
|
if project_config['project']['subprojects']
|
|
subproject_navigation = []
|
|
|
|
project_config['project']['subprojects'].each do |subproject|
|
|
|
|
if subproject[1]['git']
|
|
subproject_clone_target = clone_target + '/' + subproject[1]['target']
|
|
cleanup_and_clone(subproject_clone_target, subproject[1]['git'], subproject[1]['ref'])
|
|
end
|
|
|
|
subproject_navigation.push(subproject[0] => build_page_index(clone_target + '/' + subproject[1]['docs_dir'], subproject[1]['docs_dir']))
|
|
end
|
|
end
|
|
|
|
mkdocs['site_name'] = project_config['site_name']
|
|
mkdocs['docs_dir'] = clone_target
|
|
mkdocs['site_dir'] = project_config['site_dir'] + '/' + project_config['project']['target'] + '/' + version
|
|
mkdocs['repo_url'] = project_config['project']['git'].gsub('.git', '').downcase
|
|
mkdocs['repo_url'] = '' if project_config['repo_url'] == 'hide'
|
|
mkdocs['nav'].push(*main_pages)
|
|
mkdocs['nav'].push(*subproject_navigation) if subproject_navigation
|
|
#mkdocs['extra']['events'] = get_events(config['events']['git'],
|
|
# config['events']['source_dir'],
|
|
# config['events']['categories'])
|
|
|
|
File.write('mkdocs.yml', mkdocs.to_yaml)
|
|
%x(mkdocs build)
|
|
|
|
Dir.chdir(mkdocs['site_dir'])
|
|
|
|
#Dir.glob('**/*.png').each do|f|
|
|
# system("optipng #{f}") or exit!
|
|
#end
|