Class: DotHelper

Inherits:
Object
  • Object
show all
Defined in:
lib/dothtml/dot_helper.rb

Constant Summary collapse

GRAPH_REGEX =
/\b(?:di)?graph\b[^\[]*\{/mi
DOT_REGEX =
/->/

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(svg_contents) ⇒ DotHelper

Returns a new instance of DotHelper.



10
11
12
# File 'lib/dothtml/dot_helper.rb', line 10

def initialize(svg_contents)
  @svg_contents = svg_contents
end

Class Method Details

.detect_language(contents, language = nil) ⇒ Object



114
115
116
# File 'lib/dothtml/dot_helper.rb', line 114

def self.detect_language(contents, language = nil)
  language || ((contents =~ DOT_REGEX) ? 'dot' : 'neato')
end

.enhance(contents, language) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/dothtml/dot_helper.rb', line 118

def self.enhance(contents, language)
  if contents =~ GRAPH_REGEX
    contents
  elsif language == 'dot'
    <<-GRAPH
    digraph {
      #{contents}
    }
    GRAPH
  else
    <<-GRAPH
    graph {
      #{contents}
    }
    GRAPH
  end
end

.from_dot(contents, language = 'dot') ⇒ Object



136
137
138
139
140
# File 'lib/dothtml/dot_helper.rb', line 136

def self.from_dot(contents, language = 'dot')
  language = detect_language(contents, language)
  contents = enhance(contents, language)
  new(svg_from_dot(contents, language))
end

.from_dotfile(filename) ⇒ Object



110
111
112
# File 'lib/dothtml/dot_helper.rb', line 110

def self.from_dotfile(filename)
  new(svg_from_dot(File.read(filename)))
end

.svg_from_dot(contents, language = 'dot') ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/dothtml/dot_helper.rb', line 142

def self.svg_from_dot(contents, language = 'dot')
  Open3.popen3("#{language} -Tsvg") do |stdin, stdout, stderr|
    stdout.binmode
    stdin.print contents
    stdin.close

    err = stderr.read
    if !err.nil? && !err.strip.empty?
      raise "Error from graphviz:\n#{err}"
    end

    stdout.read.tap { |str| str.force_encoding 'UTF-8' }
  end
end

Instance Method Details

#descriptions?Boolean

return true if the nodes have descripions?

This will create a div box where descriptions can be displayed

Returns:

  • (Boolean)


37
38
39
# File 'lib/dothtml/dot_helper.rb', line 37

def descriptions?
  #dom.css("")
end

#domObject



18
19
20
# File 'lib/dothtml/dot_helper.rb', line 18

def dom
  @dom ||= parse_dom(@svg_contents)
end

#embed_imagesObject



87
88
89
90
# File 'lib/dothtml/dot_helper.rb', line 87

def embed_images
  node.children.before(images)
  self
end

#extract_id_class(old_id) ⇒ Object



79
80
81
82
83
84
85
# File 'lib/dothtml/dot_helper.rb', line 79

def extract_id_class(old_id)
  if old_id =~ /(.*?) ?class=["']?(.*?)['"]?$/
    [$1, $2]
  else
    [old_id]
  end
end

#extractChoicesObject

return the list of choices provided for a user

these choices are displayed to modify the data on the page

this will add a body css class and trigger a data event for d3js



29
30
# File 'lib/dothtml/dot_helper.rb', line 29

def extractChoices
end

#extractTitleObject



41
42
43
# File 'lib/dothtml/dot_helper.rb', line 41

def extractTitle
  dom.css("title").first.content()
end

#imagesObject

Embed svg image links directly into the document

this currently has too many issues working on making this more friendly assume unique list of filenames



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/dothtml/dot_helper.rb', line 50

def images
  embedded_images = Set.new

  defs = dom.create_element("def")

  # assuming the images are the correct size, declare their size
  dom.css("image").each do |img|
    file_name = img.attributes["href"].value
    id = file_name.split(".").first.split("/").last
    if file_name =~ /\.svg$/ && ! embedded_images.include?(file_name)
      src = parse_dom(File.read(file_name)).at("svg")
      g = dom.create_element("g", id: id,
        width: src["width"], height: src["height"])
      defs.add_child(g)
      src.children.each do |child|
        g.add_child(child.clone)
      end
      embedded_images << file_name
    end

    img.name="use"
    img.attributes["href"].value="##{id}"
    #img.attributes["width"].remove
    #img.attributes["height"].remove
    #img.attributes["preserveAspectRatio"].remove
  end
  defs
end

#nodeObject



97
98
99
# File 'lib/dothtml/dot_helper.rb', line 97

def node
  dom.at("svg")
end

#parse_dom(contents) ⇒ Object



14
15
16
# File 'lib/dothtml/dot_helper.rb', line 14

def parse_dom(contents)
  Nokogiri::XML.parse(contents)
end

#remove_commentsObject



92
93
94
95
# File 'lib/dothtml/dot_helper.rb', line 92

def remove_comments
  dom.xpath('//comment()').each { |comment| comment.remove }
  self
end

#to_xmlObject

uses a fragment to remove extra xml declarations



102
103
104
# File 'lib/dothtml/dot_helper.rb', line 102

def to_xml
  node.to_xml
end

#write(file_name, template_name, locals) ⇒ Object



106
107
108
# File 'lib/dothtml/dot_helper.rb', line 106

def write(file_name, template_name, locals)
  File.write(file_name, Tilt.new(template_name).render(binding, locals))
end