<commit_before>
module Giblish
  # 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.
  class GraphBuilderGraphviz

    # the dependency graph relies on graphwiz (dot), check if we can access that
    def self.supported
      return !Giblish.which('dot').nil?
    end

    # Supported options:
    # :extension - file extension for URL links (default is .html)
    def initialize(processed_docs, paths, 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
      @options = options.dup
      @extension = options.key?(:extension) ? options[:extension] : "html"
      @docid_cache = DocidCollector.docid_cache
      @docid_deps =  DocidCollector.docid_deps
      @dep_graph = build_dep_graph
    end

    # get the asciidoc source for the document.
    def source
      <<~DOC_STR
        #{generate_header}
        #{generate_labels}
        #{generate_deps}
        #{generate_footer}
      DOC_STR
    end

    private

    # build a hash with {DocInfo => [doc_id array]}
    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
      end
      result
    end

    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')}

        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

    def generate_footer
      <<~DOC_STR
        }
        ....
      DOC_STR
    end

    def make_dot_entry(doc_dict, info)
      dot_entry = if info.doc_id.nil?
                    doc_id = next_fake_id
                    @noid_docs[info] = doc_id
                    "\"#{doc_id}\"[label=\"-\\n#{info.title}\""
                  else
                    doc_id = info.doc_id
                    "\"#{info.doc_id}\"[label=\"#{info.doc_id}\\n#{info.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}")
      case @extension
        when "html"
          dot_entry += ", URL=\"#{rp}\" ]"
        else<commit_msg>split title in multiple lines for dep graph<commit_after>
module Giblish
  # 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.
  class GraphBuilderGraphviz

    # the dependency graph relies on graphwiz (dot), check if we can access that
    def self.supported
      return !Giblish.which('dot').nil?
    end

    # Supported options:
    # :extension - file extension for URL links (default is .html)
    def initialize(processed_docs, paths, 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
      @options = options.dup
      @extension = options.key?(:extension) ? options[:extension] : "html"
      @docid_cache = DocidCollector.docid_cache
      @docid_deps =  DocidCollector.docid_deps
      @dep_graph = build_dep_graph
    end

    # get the asciidoc source for the document.
    def source
      <<~DOC_STR
        #{generate_header}
        #{generate_labels}
        #{generate_deps}
        #{generate_footer}
      DOC_STR
    end

    private

    # build a hash with {DocInfo => [doc_id array]}
    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
      end
      result
    end

    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')}

        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

    def generate_footer
      <<~DOC_STR
        }
        ....
      DOC_STR
    end

    def make_dot_entry(doc_dict, info)
      # split title into multiple rows if it is too long
      line_length = 15
      lines = [""]
      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
      title = lines.select { |l| l.length > 0 }.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}")
      case @extension
        when "html"
          dot_entry += ", URL=\"#{rp}\" ]"
        else
{'fraction_non_alphanumeric': 0.09962941847206386, 'fraction_numerical': 0.004561003420752566, 'mean_word_length': 1.9532828282828283, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '207870', 'n_tokens_mistral': 2166, 'n_tokens_neox': 2081, 'n_words': 612}