# frozen_string_literal: true # Copyright (c) 2006-2007 Minero Aoki # # This program is free software. # You can distribute/modify this program under the Ruby License. # require 'fileutils' require 'bitclust' require 'bitclust/nameutils' require 'bitclust/subcommand' require 'bitclust/progress_bar' require 'bitclust/silent_progress_bar' module BitClust module Subcommands class StatichtmlCommand < Subcommand include NameUtils class URLMapperEx < URLMapper include NameUtils attr_accessor :bitclust_html_base def initialize(h) super @bitclust_html_base = "" @suffix = h[:suffix] @fs_casesensitive = h[:fs_casesensitive] @canonical_base_url = h[:canonical_base_url] @edit_base_url = h[:edit_base_url] end def library_url(name) if name == '/' @bitclust_html_base + "/library/#{html_filename("index", @suffix)}" else @bitclust_html_base + "/library/#{html_filename(encodename_package(name), @suffix)}" end end def class_url(name) @bitclust_html_base + "/class/#{html_filename(encodename_package(name), @suffix)}" end def method_url(spec) cname, tmark, mname = *split_method_spec(spec) filename = html_filename(encodename_package(mname), @suffix) @bitclust_html_base + "/method/#{encodename_package(cname)}/#{typemark2char(tmark)}/#{filename}" end def function_url(name) filename = html_filename(name.empty? ? 'index' : name, @suffix) @bitclust_html_base + "/function/#{filename}" end def document_url(name) filename = html_filename(encodename_package(name), @suffix) @bitclust_html_base + "/doc/#{filename}" end def css_url @bitclust_html_base + "/" + @css_url end def custom_css_url(filename) @bitclust_html_base + "/" + filename end def custom_js_url(filename) @bitclust_html_base + "/" + filename end def favicon_url @bitclust_html_base + "/" + @favicon_url end def library_index_url @bitclust_html_base + "/library/#{html_filename("index", @suffix)}" end def function_index_url @bitclust_html_base + "/function/#{html_filename("index", @suffix)}" end def canonical_url(current_url) (@canonical_base_url + "/#{current_url}").sub(@bitclust_html_base, "").sub(/([^:])\/\/+/, "\\1/") end def edit_url(location) "#{@edit_base_url}/#{location.file}#L#{location.line}".sub(/([^:])\/\/+/, "\\1/") end def encodename_package(str) if @fs_casesensitive encodename_url(str) else encodename_fs(str) end end end def initialize if Object.const_defined?(:Encoding) begin verbose, $VERBOSE = $VERBOSE, false Encoding.default_external = 'utf-8' ensure $VERBOSE = verbose end end super @verbose = true @catalogdir = nil @templatedir = srcdir_root + "data/bitclust/template.offline" @themedir = srcdir_root + "theme/default" @suffix = ".html" @gtm_tracking_id = nil @meta_robots_content = ["noindex"] @stop_on_syntax_error = true @parser.banner = "Usage: #{File.basename($0, '.*')} statichtml [options]" @parser.on('-o', '--outputdir=PATH', 'Output directory') do |path| begin @outputdir = Pathname.new(path).realpath rescue Errno::ENOENT FileUtils.mkdir_p(path, :verbose => @verbose) retry end end @parser.on('--catalog=PATH', 'Catalog directory') do |path| @catalogdir = Pathname.new(path).realpath end @parser.on('--templatedir=PATH', 'Template directory') do |path| @templatedir = Pathname.new(path).realpath end @parser.on('--themedir=PATH', 'Theme directory') do |path| @themedir = Pathname.new(path).realpath end @parser.on('--suffix=SUFFIX', 'Suffix for each (X)HTML file [.html]') do |suffix| @suffix = suffix end @parser.on('--fs-casesensitive', 'Filesystem is case-sensitive') do @fs_casesensitive = true end @parser.on('--canonical-base-url=URL', 'Canonical base URL') do |url| @canonical_base_url = url end @parser.on('--edit-base-url=URL', 'Edit base URL') do |url| @edit_base_url = url end @parser.on('--tracking-id=ID', 'Google Tag Manager Tracking ID') do |id| @gtm_tracking_id = id end @parser.on('--meta-robots-content=VALUE1,VALUE2,...', Array, 'HTML element: db}).body, :verbose => @verbose) create_file(@outputdir + "class/#{html_filename("index", @suffix)}", manager.class_index_screen(db.classes.sort, {:database => db}).body, :verbose => @verbose) create_file(@outputdir + "function/#{html_filename("index", @suffix)}", manager.function_index_screen(fdb.functions.sort, { :database => fdb }).body, :verbose => @verbose) create_index_html(@outputdir) FileUtils.cp(@manager_config[:themedir] + @manager_config[:css_url], @outputdir.to_s, :verbose => @verbose, :preserve => true) FileUtils.cp(@manager_config[:themedir] + "syntax-highlight.css", @outputdir.to_s, :verbose => @verbose, :preserve => true) FileUtils.cp(@manager_config[:themedir] + "script.js", @outputdir.to_s, :verbose => @verbose, :preserve => true) FileUtils.cp(@manager_config[:themedir] + @manager_config[:favicon_url], @outputdir.to_s, :verbose => @verbose, :preserve => true) Dir.mktmpdir do |tmpdir| FileUtils.cp_r(@manager_config[:themedir] + 'images', tmpdir, :verbose => @verbose, :preserve => true) Dir.glob(File.join(tmpdir, 'images', '/**/.svn')).each do |d| FileUtils.rm_r(d, :verbose => @verbose) end FileUtils.cp_r(File.join(tmpdir, 'images'), @outputdir.to_s, :verbose => @verbose, :preserve => true) end end private def create_manager_config @manager_config = { :catalogdir => @catalogdir, :suffix => @suffix, :templatedir => @templatedir, :themedir => @themedir, :css_url => 'style.css', :favicon_url => 'rurema.png', :cgi_url => '', :tochm_mode => true, :fs_casesensitive => @fs_casesensitive, :canonical_base_url => @canonical_base_url, :edit_base_url => @edit_base_url, :gtm_tracking_id => @gtm_tracking_id, :meta_robots_content => @meta_robots_content, :stop_on_syntax_error => @stop_on_syntax_error, } @manager_config[:urlmapper] = URLMapperEx.new(@manager_config) @urlmapper = @manager_config[:urlmapper] end def create_html_entries(title, entries, manager, db) title = align_progress_bar_title(title) original_title = title.dup if @verbose progressbar = ProgressBar.create(title: title, total: entries.size) else progressbar = SilentProgressBar.create(title: title, total: entries.size) end entries.each do |entry| create_html_file(entry, manager, @outputdir, db) progressbar.title = align_progress_bar_title([entry].flatten.first.name) progressbar.increment end progressbar.title = original_title progressbar.finish end def create_html_methods(title, methods, manager, db) title = align_progress_bar_title(title) original_title = title.dup if @verbose progressbar = ProgressBar.create(title: title, total: methods.size) else progressbar = SilentProgressBar.create(title: title, total: methods.size) end methods.each do |method_name, method_entries| create_html_method_file(method_name, method_entries, manager, @outputdir, db) progressbar.title = align_progress_bar_title(method_name) progressbar.increment end progressbar.title = original_title progressbar.finish end def create_index_html(outputdir) index_filename = html_filename("index", @suffix) path = outputdir + index_filename File.open(path, 'w'){|io| io.write < Go HERE } end def create_html_file(entry, manager, outputdir, db) e = entry.is_a?(Array) ? entry.sort.first : entry case e.type_id when :library, :class, :doc @urlmapper.bitclust_html_base = '..' path = outputdir + e.type_id.to_s + html_filename(encodename_package(e.name), @suffix) create_html_file_p(entry, manager, path, db) when :function create_html_function_file(entry, manager, outputdir, db) else raise end e.unload end def create_html_method_file(method_name, entries, manager, outputdir, db) path = nil @urlmapper.bitclust_html_base = '../../..' e = entries.sort.first name = method_name.sub(e.klass.name + e.typemark, "") path = outputdir + e.type_id.to_s + encodename_package(e.klass.name) + e.typechar + html_filename(encodename_package(name), @suffix) create_html_file_p(entries, manager, path, db) end def create_html_function_file(entry, manager, outputdir, db) path = nil @urlmapper.bitclust_html_base = '..' path = outputdir + entry.type_id.to_s + html_filename(entry.name, @suffix) create_html_file_p(entry, manager, path, db) end def create_html_file_p(entry, manager, path, db) FileUtils.mkdir_p(path.dirname) unless path.dirname.directory? html = manager.entry_screen(entry, {:database => db}).body path.open('w') do |f| f.write(html) end end def create_file(path, str, options = {}) verbose = options[:verbose] $stderr.print("creating #{path} ...") if verbose path.open('w') do |f| f.write(str) end $stderr.puts(" done.") if verbose end def encodename_package(str) if @fs_casesensitive encodename_url(str) else encodename_fs(str) end end end end end