class RDoc::Generator::Darkfish
$Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $
作者¶ ↑
-
Michael Granger ([email protected])
贡献者¶ ↑
-
Mahlon E. Smith ([email protected])
-
Eric Hodel ([email protected])
许可证¶ ↑
版权所有 © 2007, 2008, Michael Granger。 保留所有权利。
如果满足以下条件,则允许以源代码和二进制形式进行再分发和使用,无论是否修改:
-
源代码的再分发必须保留上述版权声明、此条件列表和以下免责声明。
-
以二进制形式的再分发必须在随分发提供的文档和/或其他材料中复制上述版权声明、此条件列表和以下免责声明。
-
未经事先明确书面许可,不得使用作者/们的姓名或项目贡献者的姓名来认可或推广由此软件衍生的产品。
本软件由版权所有者和贡献者“按原样”提供,并且不承担任何明示或暗示的保证,包括但不限于对适销性和特定用途适用性的暗示保证。在任何情况下,版权所有者或贡献者均不对任何直接、间接、偶然、特殊、惩戒性或后果性损害(包括但不限于采购替代商品或服务;使用、数据或利润损失;或业务中断)承担责任,无论其原因以及任何责任理论,无论是合同、严格责任还是侵权行为(包括疏忽或其他),均以任何方式因使用本软件而引起,即使已被告知可能发生此类损害。
归属¶ ↑
常量
- DESCRIPTION
此生成器的描述
- GENERATOR_DIR
此文件父目录的路径。用于查找模板和其他资源。
- SVNID_PATTERN
%q$Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $“
- VERSION
发布版本
属性
样式表和 javascript 的相对路径。默认情况下,此路径与 rel_prefix 相同。
要将文件生成到的路径,与选项中的 --op
组合得到完整路径。
此生成器使用的类和模块,不一定显示。另请参阅 modsort
当 dry_run
为 true 时,将不会写入任何文件。
当为 false 时,生成方法返回 String 而不是写入文件。默认为 true。
此生成器显示的文件
此 Darkfish
生成器的 JSON 索引生成器
此生成器显示的方法
此生成器显示的类和模块的排序列表
输出目录
作为生成内容源的 RDoc::Store
公共类方法
在开始之前初始化一些实例变量
# File rdoc/generator/darkfish.rb, line 159 def initialize store, options @store = store @options = options @asset_rel_path = '' @base_dir = Pathname.pwd.expand_path @dry_run = @options.dry_run @file_output = true @template_dir = Pathname.new options.template_dir @template_cache = {} @classes = nil @context = nil @files = nil @methods = nil @modsort = nil @json_index = RDoc::Generator::JsonIndex.new self, options end
公共实例方法
从其组件和 body_file
创建模板。
为了向后兼容,如果 body_file
包含“<html”,则直接使用主体。
# File rdoc/generator/darkfish.rb, line 675 def assemble_template body_file body = body_file.read return body if body =~ /<html/ head_file = @template_dir + '_head.rhtml' <<-TEMPLATE <!DOCTYPE html> <html> <head> #{head_file.read} #{body} TEMPLATE end
生成的类 HTML 文件相对于输出目录所在的目录。
# File rdoc/generator/darkfish.rb, line 191 def class_dir nil end
将静态文件从 static_path 复制到输出目录
# File rdoc/generator/darkfish.rb, line 265 def copy_static return if @options.static_path.empty? fu_options = { :verbose => $DEBUG_RDOC, :noop => @dry_run } @options.static_path.each do |path| unless File.directory? path then FileUtils.install path, @outputdir, **fu_options.merge(:mode => 0644) next end Dir.chdir path do Dir[File.join('**', '*')].each do |entry| dest_file = @outputdir + entry if File.directory? entry then FileUtils.mkdir_p entry, **fu_options else FileUtils.install entry, dest_file, **fu_options.merge(:mode => 0644) end end end end end
如果启用了调试,则输出进度信息
# File rdoc/generator/darkfish.rb, line 182 def debug_msg *msg return unless $DEBUG_RDOC $stderr.puts(*msg) end
返回内容的摘录,用于元描述标签
# File rdoc/generator/darkfish.rb, line 784 def excerpt(content) text = case content when RDoc::Comment content.text when RDoc::Markup::Document # This case is for page files that are not markdown nor rdoc # We convert them to markdown for now as it's easier to extract the text formatter = RDoc::Markup::ToMarkdown.new formatter.start_accepting formatter.accept_document(content) formatter.end_accepting else content end # Match from a capital letter to the first period, discarding any links, so # that we don't end up matching badges in the README first_paragraph_match = text.match(/[A-Z][^\.:\/]+\./) return text[0...150].gsub(/\n/, " ").squeeze(" ") unless first_paragraph_match extracted_text = first_paragraph_match[0] second_paragraph = first_paragraph_match.post_match.match(/[A-Z][^\.:\/]+\./) extracted_text << " " << second_paragraph[0] if second_paragraph extracted_text[0...150].gsub(/\n/, " ").squeeze(" ") end
生成的类 HTML 文件相对于输出目录所在的目录。
# File rdoc/generator/darkfish.rb, line 199 def file_dir nil end
如果生成的文档尚不存在,则创建它们所在的目录。
# File rdoc/generator/darkfish.rb, line 207 def gen_sub_directories @outputdir.mkpath end
基于包含提取信息的 TopLevel 对象数组构建初始索引并输出对象。
# File rdoc/generator/darkfish.rb, line 241 def generate setup write_style_sheet generate_index generate_class_files generate_file_files generate_table_of_contents @json_index.generate @json_index.generate_gzipped copy_static rescue => e debug_msg "%s: %s\n %s" % [ e.class.name, e.message, e.backtrace.join("\n ") ] raise end
# File rdoc/generator/darkfish.rb, line 811 def generate_ancestor_list(ancestors, klass) return '' if ancestors.empty? ancestor = ancestors.shift content = +'<ul><li>' if ancestor.is_a?(RDoc::NormalClass) content << "<a href=\"#{klass.aref_to ancestor.path}\">#{ancestor.full_name}</a>" else content << ancestor.to_s end # Recursively call the method for the remaining ancestors content << generate_ancestor_list(ancestors, klass) content << '</li></ul>' end
为 klass
生成一个类文件
# File rdoc/generator/darkfish.rb, line 337 def generate_class klass, template_file = nil setup current = klass template_file ||= @template_dir + 'class.rhtml' debug_msg " working on %s (%s)" % [klass.full_name, klass.path] out_file = @outputdir + klass.path rel_prefix = @outputdir.relative_path_from out_file.dirname search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output asset_rel_prefix = rel_prefix + @asset_rel_path svninfo = get_svninfo(current) @title = "#{klass.type} #{klass.full_name} - #{@options.title}" debug_msg " rendering #{out_file}" render_template template_file, out_file do |io| here = binding # suppress 1.9.3 warning here.local_variable_set(:asset_rel_prefix, asset_rel_prefix) here.local_variable_set(:svninfo, svninfo) here end end
为每个类和模块生成一个文档文件
# File rdoc/generator/darkfish.rb, line 368 def generate_class_files setup template_file = @template_dir + 'class.rhtml' template_file = @template_dir + 'classpage.rhtml' unless template_file.exist? return unless template_file.exist? debug_msg "Generating class documentation in #{@outputdir}" current = nil @classes.each do |klass| current = klass generate_class klass, template_file end rescue => e error = RDoc::Error.new \ "error generating #{current.path}: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end
为每个文件生成一个文档文件
# File rdoc/generator/darkfish.rb, line 395 def generate_file_files setup page_file = @template_dir + 'page.rhtml' fileinfo_file = @template_dir + 'fileinfo.rhtml' # for legacy templates filepage_file = @template_dir + 'filepage.rhtml' unless page_file.exist? or fileinfo_file.exist? return unless page_file.exist? or fileinfo_file.exist? or filepage_file.exist? debug_msg "Generating file documentation in #{@outputdir}" out_file = nil current = nil @files.each do |file| current = file if file.text? and page_file.exist? then generate_page file next end template_file = nil out_file = @outputdir + file.path debug_msg " working on %s (%s)" % [file.full_name, out_file] rel_prefix = @outputdir.relative_path_from out_file.dirname search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output asset_rel_prefix = rel_prefix + @asset_rel_path unless filepage_file then if file.text? then next unless page_file.exist? template_file = page_file @title = file.page_name else next unless fileinfo_file.exist? template_file = fileinfo_file @title = "File: #{file.base_name}" end end @title += " - #{@options.title}" template_file ||= filepage_file render_template template_file, out_file do |io| here = binding # suppress 1.9.3 warning here.local_variable_set(:asset_rel_prefix, asset_rel_prefix) here.local_variable_set(:current, current) here end end rescue => e error = RDoc::Error.new "error generating #{out_file}: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end
生成一个索引页面,其中列出所有已记录的类。
# File rdoc/generator/darkfish.rb, line 303 def generate_index setup template_file = @template_dir + 'index.rhtml' return unless template_file.exist? debug_msg "Rendering the index page..." out_file = @base_dir + @options.op_dir + 'index.html' rel_prefix = @outputdir.relative_path_from out_file.dirname search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output asset_rel_prefix = rel_prefix + @asset_rel_path @title = @options.title render_template template_file, out_file do |io| here = binding # suppress 1.9.3 warning here.local_variable_set(:asset_rel_prefix, asset_rel_prefix) here end rescue => e error = RDoc::Error.new \ "error generating index.html: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end
为 file
生成一个页面文件
# File rdoc/generator/darkfish.rb, line 464 def generate_page file setup template_file = @template_dir + 'page.rhtml' out_file = @outputdir + file.path debug_msg " working on %s (%s)" % [file.full_name, out_file] rel_prefix = @outputdir.relative_path_from out_file.dirname search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output current = file asset_rel_prefix = rel_prefix + @asset_rel_path @title = "#{file.page_name} - #{@options.title}" debug_msg " rendering #{out_file}" render_template template_file, out_file do |io| here = binding # suppress 1.9.3 warning here.local_variable_set(:current, current) here.local_variable_set(:asset_rel_prefix, asset_rel_prefix) here end end
为 RDoc
servlet 生成 404 页面
# File rdoc/generator/darkfish.rb, line 493 def generate_servlet_not_found message setup template_file = @template_dir + 'servlet_not_found.rhtml' return unless template_file.exist? debug_msg "Rendering the servlet 404 Not Found page..." rel_prefix = rel_prefix = '' search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output asset_rel_prefix = '' @title = 'Not Found' render_template template_file do |io| here = binding # suppress 1.9.3 warning here.local_variable_set(:asset_rel_prefix, asset_rel_prefix) here end rescue => e error = RDoc::Error.new \ "error generating servlet_not_found: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end
为 RDoc
servlet 生成 servlet 根页面
# File rdoc/generator/darkfish.rb, line 526 def generate_servlet_root installed setup template_file = @template_dir + 'servlet_root.rhtml' return unless template_file.exist? debug_msg 'Rendering the servlet root page...' rel_prefix = '.' asset_rel_prefix = rel_prefix search_index_rel_prefix = asset_rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output @title = 'Local RDoc Documentation' render_template template_file do |io| binding end rescue => e error = RDoc::Error.new \ "error generating servlet_root: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end
生成一个索引页面,其中列出所有已记录的类。
# File rdoc/generator/darkfish.rb, line 553 def generate_table_of_contents setup template_file = @template_dir + 'table_of_contents.rhtml' return unless template_file.exist? debug_msg "Rendering the Table of Contents..." out_file = @outputdir + 'table_of_contents.html' rel_prefix = @outputdir.relative_path_from out_file.dirname search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output asset_rel_prefix = rel_prefix + @asset_rel_path @title = "Table of Contents - #{@options.title}" render_template template_file, out_file do |io| here = binding # suppress 1.9.3 warning here.local_variable_set(:asset_rel_prefix, asset_rel_prefix) here end rescue => e error = RDoc::Error.new \ "error generating table_of_contents.html: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end
返回按显着性排序,然后按名称排序的已记录模块列表。
# File rdoc/generator/darkfish.rb, line 294 def get_sorted_module_list classes classes.select do |klass| klass.display? end.sort end
尝试从第一个值看起来像 Subversion Id 标记的常量中提取 Subversion 信息。如果找不到匹配的常量,则返回空哈希。
# File rdoc/generator/darkfish.rb, line 652 def get_svninfo klass constants = klass.constants or return {} constants.find { |c| c.value =~ SVNID_PATTERN } or return {} filename, rev, date, time, committer = $~.captures commitdate = Time.parse "#{date} #{time}" return { :filename => filename, :rev => Integer(rev), :commitdate => commitdate, :commitdelta => time_delta_string(Time.now - commitdate), :committer => committer, } end
呈现相对于模板目录的 file_name
中包含的 ERb,并根据当前上下文返回结果。
# File rdoc/generator/darkfish.rb, line 696 def render file_name template_file = @template_dir + file_name template = template_for template_file, false, RDoc::ERBPartial template.filename = template_file.to_s template.result @context end
加载并呈现给定 template_file
中的 erb 模板,并将其写入 out_file
。
template_file
和 out_file
都应该是 Pathname 类对象。
将产生一个 io,必须由调用者绑定捕获。
# File rdoc/generator/darkfish.rb, line 714 def render_template template_file, out_file = nil # :yield: io io_output = out_file && !@dry_run && @file_output erb_klass = io_output ? RDoc::ERBIO : ERB template = template_for template_file, true, erb_klass if io_output then debug_msg "Outputting to %s" % [out_file.expand_path] out_file.dirname.mkpath out_file.open 'w', 0644 do |io| io.set_encoding @options.encoding @context = yield io template_result template, @context, template_file end else @context = yield nil output = template_result template, @context, template_file debug_msg " would have written %d characters to %s" % [ output.length, out_file.expand_path ] if @dry_run output end end
准备从当前目录生成输出
# File rdoc/generator/darkfish.rb, line 604 def setup return if instance_variable_defined? :@outputdir @outputdir = Pathname.new(@options.op_dir).expand_path @base_dir return unless @store @classes = @store.all_classes_and_modules.sort @files = @store.all_files.sort @methods = @classes.flat_map { |m| m.method_list }.sort @modsort = get_sorted_module_list @classes end
检索 file
的缓存模板(如果存在),或填充缓存。
# File rdoc/generator/darkfish.rb, line 761 def template_for file, page = true, klass = ERB template = @template_cache[file] return template if template if page then template = assemble_template file erbout = 'io' else template = file.read template = template.encode @options.encoding file_var = File.basename(file).sub(/\..*/, '') erbout = "_erbout_#{file_var}" end template = klass.new template, trim_mode: '-', eoutvar: erbout @template_cache[file] = template template end
使用 context
为 template
创建结果。如果引发错误,Pathname template_file
将指示发生错误的文件。
# File rdoc/generator/darkfish.rb, line 748 def template_result template, context, template_file template.filename = template_file.to_s template.result context rescue NoMethodError => e raise RDoc::Error, "Error while evaluating %s: %s" % [ template_file.expand_path, e.message, ], e.backtrace end
返回一个字符串,该字符串以人类容易理解的方式描述给定秒数的时间量。
# File rdoc/generator/darkfish.rb, line 621 def time_delta_string seconds return 'less than a minute' if seconds < 60 return "#{seconds / 60} minute#{seconds / 60 == 1 ? '' : 's'}" if seconds < 3000 # 50 minutes return 'about one hour' if seconds < 5400 # 90 minutes return "#{seconds / 3600} hours" if seconds < 64800 # 18 hours return 'one day' if seconds < 86400 # 1 day return 'about one day' if seconds < 172800 # 2 days return "#{seconds / 86400} days" if seconds < 604800 # 1 week return 'about one week' if seconds < 1209600 # 2 week return "#{seconds / 604800} weeks" if seconds < 7257600 # 3 months return "#{seconds / 2419200} months" if seconds < 31536000 # 1 year return "#{seconds / 31536000} years" end
将样式表复制到输出目录中的适当位置。
# File rdoc/generator/darkfish.rb, line 215 def write_style_sheet debug_msg "Copying static files" options = { :verbose => $DEBUG_RDOC, :noop => @dry_run } BUILTIN_STYLE_ITEMS.each do |item| install_rdoc_static_file @template_dir + item, "./#{item}", options end unless @options.template_stylesheets.empty? FileUtils.cp @options.template_stylesheets, '.', **options end Dir[(@template_dir + "{js,images}/**/*").to_s].each do |path| next if File.directory? path next if File.basename(path) =~ /^\./ dst = Pathname.new(path).relative_path_from @template_dir install_rdoc_static_file @template_dir + path, dst, options end end