glejeune / Ruby-Graphviz

[MIRROR] Ruby interface to the GraphViz graphing tool
https://gitlab.com/glejeune/ruby-graphviz
Other
608 stars 116 forks source link

Svg first string in node not correct (russian) #109

Open rqz13 opened 9 years ago

rqz13 commented 9 years ago

I have some problems when i create svg format. I checked my graph using output ('none' => 'filename'), same as .to_s on graph object, check with .dot formatand i see that all nodes has correct text. But using svg format i see that first line of my russian text in node has no spaces and first word is missing. You can see screenshots. pic of nodes pic of html in generated svg You can see than xlink:title="Один два три четыре пять шесть семь\nвосемь девять десять одинадцать\nдвенадцать тринадцать четырнадцать\nпятнадцать шестнадцать семнадцать\nвосемнадцать девятнадцать двадцать\nдвадцатьодин двадцатьдва и т.д.\n" And inside this element first element DO NOT contain word "Один" and words not split with space, but english record with same text has spaces and all words present in element

Also my code for generation graph.

require 'graphviz'

class GroupGraph

  def initialize(group, format, path)
    @group = group
    @format = format
    @path = path
    @col_length = 40
  end

  def create_graph
    graph = GraphViz.digraph(@group.name) do |g|
      g[:bgcolor] = '#FFEEDD'
      g[:label] = "#{Group.model_name.human} #{@group.name}. #{ExpertSocialNetwork::Application.config.local_env['host']}"
      g[:labelloc] = "b"

      g.edge[:style] = 'filled'
      g.edge[:color] = 'black'

      g.node[:shape] = 'record'
      g.node[:fillcolor] = '#f2d8a7'
      g.node[:color] = '#591e23'
      g.node[:style] = 'filled'

      create_nodes(g)
      create_edges(g)
    end
    if @format == :dot
      graph.output(Hash['none', @path])
    else
      graph.output(Hash[@format, @path])
    end
  end

  private

  def create_nodes(graph)
    @group.access_records.each do |record|
      text = record.text
      escape_text text
      text = split_by_length(text)
      if record.tag_list.present?
        text.insert(0, '{')
        text += "|#{record.tag_list.map{ |t| "##{t}" }.join(' ')}"
        text.insert(-1, '}')
      end
      graph.add_nodes(record.id.to_s, URL: record_url(record.id), label: text)
    end
  end

  def create_edges(graph)
    rec_ids = @group.access_records.pluck(:id)
    RecordMap.where(parent_id: rec_ids, child_id: rec_ids, is_deleted: false).each do |rec_map|
      child = Record.find rec_map.child_id
      next unless child
      child.map_id = rec_map.id
      rec_format = RecordFormat.find_by_record(child)
      arrow_color = rec_format && rec_format.format ? JSON.parse(rec_format.format)['background_color'] : nil
      options = {}
      options[:color]  = arrow_color if arrow_color
      graph.add_edges(rec_map.parent_id.to_s, rec_map.child_id.to_s, options)
    end
  end

  def record_url(id)
    "#{ExpertSocialNetwork::Application.config.local_env['host']}/records/#{id}"
  end

  def escape_text(text)
    text.gsub!('<', '&lt;')
    text.gsub!('>', '&gt;')
    text.gsub!('{', '\{')
    text.gsub!('}', '\}')
  end

  def split_by_length(text)
    res_text = ''
    text.split("\n").each do |sub_line|
      line = ''
      sub_line.split.each do |word|
        if line.length + word.length + 1 > @col_length
          res_text += "#{line}\n"
          line = "#{word}"
          next
        end
        line += line.empty? ? word : " #{word}"
      end
      res_text += "#{line}\n" unless line.empty?
    end
    res_text.gsub! "\n", "&#92;n" if @format == :svg
    res_text
  end
end
rqz13 commented 9 years ago

Bug was in graphvis version 2.38. 2.36 works fine.