class Giblish::GraphBuilderGraphviz
Builds an asciidoc page with an svg image with a digraph showing how documents reference each other.
Graphviz is used as the graph generator and must be available as a valid engine via asciidoctor-diagram for this class to work.
Public Class Methods
new(processed_docs, paths, deployment_info, options = {})
click to toggle source
Supported options: :extension - file extension for URL links (default is .html)
# File lib/giblish/buildgraph.rb, line 15 def initialize(processed_docs, paths, deployment_info, options = {}) # this class relies on graphwiz (dot), make sure we can access that raise "Could not find the 'dot' tool needed to generate a dependency graph!" unless GraphBuilderGraphviz.supported # require asciidoctor module needed for generating diagrams require "asciidoctor-diagram/graphviz" @noid_docs = {} @next_id = 0 @processed_docs = processed_docs @paths = paths @deployment_info = deployment_info @converter_options = options.dup @extension = @converter_options.key?(:extension) ? options[:extension] : "html" @docid_cache = DocidCollector.docid_cache @docid_deps = DocidCollector.docid_deps @dep_graph = build_dep_graph @search_opts = { web_assets_top: @deployment_info.web_path, search_assets_top: @deployment_info.search_assets_path } end
supported()
click to toggle source
the dependency graph relies on graphwiz (dot), check if we can access that
# File lib/giblish/buildgraph.rb, line 9 def self.supported !Giblish.which("dot").nil? end
Public Instance Methods
cleanup()
click to toggle source
# File lib/giblish/buildgraph.rb, line 51 def cleanup # remove cache dir and svg image created by asciidoctor-diagram # when creating the document dependency graph adoc_diag_cache = @paths.dst_root_abs.join(".asciidoctor") FileUtils.remove_dir(adoc_diag_cache) if adoc_diag_cache.directory? Giblog.logger.info { "Removing cached files at: #{@paths.dst_root_abs.join('docdeps.svg')}" } @paths.dst_root_abs.join("docdeps.svg").delete end
source(make_searchable: false)
click to toggle source
get the asciidoc source for the document.
# File lib/giblish/buildgraph.rb, line 39 def source(make_searchable: false) s = <<~DOC_STR #{generate_header} #{add_search_box if make_searchable} #{generate_graph_header} #{generate_labels} #{generate_deps} #{generate_footer} DOC_STR s end
Private Instance Methods
add_search_box()
click to toggle source
# File lib/giblish/buildgraph.rb, line 114 def add_search_box Giblish.generate_search_box_html( @converter_options[:attributes]["stylesheet"], "/cgi-bin/giblish-search.cgi", @search_opts ) end
build_dep_graph()
click to toggle source
build a hash with {DocInfo => [doc_id array]}
# File lib/giblish/buildgraph.rb, line 63 def build_dep_graph result = {} @docid_deps.each do |src_file, id_array| d = @processed_docs.find do |doc| doc.src_file.to_s.eql? src_file end raise "Inconsistent docs when building graph!! found no match for #{src_file}" if d.nil? result[d] = id_array if d.converted end result end
generate_deps()
click to toggle source
# File lib/giblish/buildgraph.rb, line 179 def generate_deps dep_str = "" @dep_graph.each do |info, targets| # set either the real or the generated id as source src_part = if info.doc_id.nil? "\"#{@noid_docs[info]}\"" else "\"#{info.doc_id}\"" end if targets.length.zero? dep_str += "#{src_part}\n" next end dep_str += "#{src_part} -> {" + targets.reduce("") do |acc, target| acc + " \"#{target}\"" end # replace last comma with newline dep_str += "}\n" end dep_str end
generate_graph_header()
click to toggle source
# File lib/giblish/buildgraph.rb, line 76 def generate_graph_header <<~DOC_STR Below is a graph that visualizes what documents (by doc-id) a specific document references. [graphviz,"docdeps","svg",options="inline"] .... digraph notebook { bgcolor="#33333310" node [shape=note, fillcolor="#ebf26680", style="filled,solid" ] rankdir="LR" DOC_STR end
generate_header()
click to toggle source
# File lib/giblish/buildgraph.rb, line 95 def generate_header t = Time.now <<~DOC_STR = Document-id reference graph from #{@paths.src_root_abs} Generated by Giblish at:: #{t.strftime('%Y-%m-%d %H:%M')} DOC_STR end
generate_labels()
click to toggle source
# File lib/giblish/buildgraph.rb, line 162 def generate_labels # create an entry in the 'dot' description for each # document, sort them according to descending doc id to # get them displayed in the opposite order in the graph node_dict = {} @dep_graph.each_key do |info| make_dot_entry node_dict, info end # sort the nodes by reverse doc id node_dict = node_dict.sort.reverse.to_h # produce the string with all node entries node_dict.map do |_k, v| v end.join("\n") end
make_dot_entry(doc_dict, info)
click to toggle source
# File lib/giblish/buildgraph.rb, line 122 def make_dot_entry(doc_dict, info) # split title into multiple rows if it is too long line_length = 15 lines = [""] unless info&.title.nil? info.title.split(" ").inject("") do |l, w| line = "#{l} #{w}" lines[-1] = line if line.length > line_length # create a new, empty, line lines << "" "" else line end end end title = lines.select { |l| l.length.positive? }.map { |l| l }.join("\n") # create the label used to display the node in the graph dot_entry = if info.doc_id.nil? doc_id = next_fake_id @noid_docs[info] = doc_id "\"#{doc_id}\"[label=\"-\\n#{title}\"" else doc_id = info.doc_id "\"#{info.doc_id}\"[label=\"#{info.doc_id}\\n#{title}\"" end # add clickable links in the case of html output (this is not supported # out-of-the-box for pdf). rp = info.rel_path.sub_ext(".#{@extension}") dot_entry += case @extension when "html" ", URL=\"#{rp}\" ]" else " ]" end doc_dict[doc_id] = dot_entry end
next_fake_id()
click to toggle source
# File lib/giblish/buildgraph.rb, line 203 def next_fake_id @next_id += 1 "_generated_id_#{@next_id.to_s.rjust(4, '0')}" end