giblish 0.8.2 → 1.0.0.rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/unit_tests.yml +30 -0
  3. data/.gitignore +7 -3
  4. data/.ruby-version +1 -1
  5. data/Changelog.adoc +61 -0
  6. data/README.adoc +267 -0
  7. data/docs/concepts/text_search.adoc +213 -0
  8. data/docs/concepts/text_search_im/cgi-search_request.puml +35 -0
  9. data/docs/concepts/text_search_im/cgi-search_request.svg +397 -0
  10. data/docs/concepts/text_search_im/search_request.puml +40 -0
  11. data/docs/concepts/text_search_im/search_request.svg +408 -0
  12. data/docs/howtos/trigger_generation.adoc +180 -0
  13. data/docs/{setup_server_assets → howtos/trigger_generation_im}/Render Documents.png +0 -0
  14. data/docs/{setup_server_assets → howtos/trigger_generation_im}/View Documents.png +0 -0
  15. data/docs/{setup_server_assets → howtos/trigger_generation_im}/deploy_with_hooks.graphml +0 -0
  16. data/docs/{setup_server_assets → howtos/trigger_generation_im}/deploy_with_hooks.svg +0 -0
  17. data/docs/{setup_server_assets → howtos/trigger_generation_im}/deploy_with_jenkins.graphml +0 -0
  18. data/docs/{setup_server_assets → howtos/trigger_generation_im}/deploy_with_jenkins.svg +0 -0
  19. data/docs/howtos/trigger_generation_im/docgen_github.puml +51 -0
  20. data/docs/{setup_server_assets → howtos/trigger_generation_im}/giblish_deployment.graphml +0 -0
  21. data/docs/howtos/trigger_generation_im/post-receive-example.sh +50 -0
  22. data/docs/reference/box_flow_spec.adoc +22 -0
  23. data/docs/reference/search_spec.adoc +185 -0
  24. data/giblish.gemspec +47 -29
  25. data/lib/giblish/adocsrc_providers.rb +23 -0
  26. data/lib/giblish/application.rb +214 -41
  27. data/lib/giblish/cmdline.rb +273 -259
  28. data/lib/giblish/config_utils.rb +41 -0
  29. data/lib/giblish/configurator.rb +163 -0
  30. data/lib/giblish/conversion_info.rb +120 -0
  31. data/lib/giblish/docattr_providers.rb +125 -0
  32. data/lib/giblish/docid/docid.rb +181 -0
  33. data/lib/giblish/github_trigger/webhook_manager.rb +64 -0
  34. data/lib/giblish/gitrepos/checkoutmanager.rb +124 -0
  35. data/lib/giblish/{gititf.rb → gitrepos/gititf.rb} +30 -4
  36. data/lib/giblish/gitrepos/gitsummary.erb +61 -0
  37. data/lib/giblish/gitrepos/gitsummaryprovider.rb +78 -0
  38. data/lib/giblish/gitrepos/history_pb.rb +41 -0
  39. data/lib/giblish/indexbuilders/d3treegraph.rb +88 -0
  40. data/lib/giblish/indexbuilders/depgraphbuilder.rb +109 -0
  41. data/lib/giblish/indexbuilders/dotdigraphadoc.rb +174 -0
  42. data/lib/giblish/indexbuilders/standard_index.erb +10 -0
  43. data/lib/giblish/indexbuilders/subtree_indices.rb +132 -0
  44. data/lib/giblish/indexbuilders/templates/circles.html.erb +111 -0
  45. data/lib/giblish/indexbuilders/templates/flame.html.erb +61 -0
  46. data/lib/giblish/indexbuilders/templates/tree.html.erb +366 -0
  47. data/lib/giblish/indexbuilders/templates/treemap.html.erb +127 -0
  48. data/lib/giblish/indexbuilders/verbatimtree.rb +94 -0
  49. data/lib/giblish/pathtree.rb +473 -74
  50. data/lib/giblish/resourcepaths.rb +150 -0
  51. data/lib/giblish/search/expand_adoc.rb +55 -0
  52. data/lib/giblish/search/headingindexer.rb +312 -0
  53. data/lib/giblish/search/request_manager.rb +110 -0
  54. data/lib/giblish/search/searchquery.rb +68 -0
  55. data/lib/giblish/search/textsearcher.rb +349 -0
  56. data/lib/giblish/subtreeinfobuilder.rb +77 -0
  57. data/lib/giblish/treeconverter.rb +272 -0
  58. data/lib/giblish/utils.rb +142 -294
  59. data/lib/giblish/version.rb +1 -1
  60. data/lib/giblish.rb +10 -7
  61. data/scripts/hooks/post-receive.example +66 -0
  62. data/{docgen/scripts/githook_examples → scripts/hooks}/post-update.example +0 -0
  63. data/{docgen → scripts}/resources/css/adoc-colony.css +0 -0
  64. data/scripts/resources/css/giblish-serif.css +419 -0
  65. data/scripts/resources/css/giblish.css +1979 -419
  66. data/{docgen → scripts}/resources/fonts/Ubuntu-B.ttf +0 -0
  67. data/{docgen → scripts}/resources/fonts/Ubuntu-BI.ttf +0 -0
  68. data/{docgen → scripts}/resources/fonts/Ubuntu-R.ttf +0 -0
  69. data/{docgen → scripts}/resources/fonts/Ubuntu-RI.ttf +0 -0
  70. data/{docgen → scripts}/resources/fonts/mplus1p-regular-fallback.ttf +0 -0
  71. data/{docgen → scripts}/resources/images/giblish_logo.png +0 -0
  72. data/{docgen → scripts}/resources/images/giblish_logo.svg +0 -0
  73. data/{docgen → scripts}/resources/themes/giblish.yml +0 -0
  74. data/scripts/wserv_development.rb +32 -0
  75. data/web_apps/cgi_search/gibsearch.rb +43 -0
  76. data/web_apps/gh_webhook_trigger/config.ru +2 -0
  77. data/web_apps/gh_webhook_trigger/gh_webhook_trigger.rb +73 -0
  78. data/web_apps/gh_webhook_trigger/public/dummy.txt +3 -0
  79. data/web_apps/sinatra_search/config.ru +2 -0
  80. data/web_apps/sinatra_search/public/dummy.txt +3 -0
  81. data/web_apps/sinatra_search/sinatra_search.rb +34 -0
  82. data/web_apps/sinatra_search/tmp/restart.txt +0 -0
  83. metadata +168 -73
  84. data/.rubocop.yml +0 -7
  85. data/.travis.yml +0 -3
  86. data/Changelog +0 -16
  87. data/Gemfile +0 -4
  88. data/README.adoc +0 -1
  89. data/Rakefile +0 -41
  90. data/bin/console +0 -14
  91. data/bin/setup +0 -8
  92. data/data/testdocs/malformed/no_header.adoc +0 -5
  93. data/data/testdocs/toplevel.adoc +0 -19
  94. data/data/testdocs/wellformed/adorned_purpose.adoc +0 -17
  95. data/data/testdocs/wellformed/docidtest/docid_1.adoc +0 -24
  96. data/data/testdocs/wellformed/docidtest/docid_2.adoc +0 -8
  97. data/data/testdocs/wellformed/simple.adoc +0 -14
  98. data/data/testdocs/wellformed/source_highlighting/highlight_source.adoc +0 -38
  99. data/docgen/resources/css/giblish.css +0 -1979
  100. data/docgen/scripts/Jenkinsfile +0 -18
  101. data/docgen/scripts/gen_adoc_org.sh +0 -58
  102. data/docs/README.adoc +0 -387
  103. data/docs/setup_server.adoc +0 -202
  104. data/lib/giblish/buildgraph.rb +0 -216
  105. data/lib/giblish/buildindex.rb +0 -459
  106. data/lib/giblish/core.rb +0 -451
  107. data/lib/giblish/docconverter.rb +0 -308
  108. data/lib/giblish/docid.rb +0 -180
  109. data/lib/giblish/docinfo.rb +0 -75
  110. data/lib/giblish/indexheadings.rb +0 -251
  111. data/lib/giblish-search.cgi +0 -459
  112. data/scripts/hooks/post-receive +0 -57
  113. data/scripts/publish_html.sh +0 -99
@@ -0,0 +1,174 @@
1
+ require_relative "../utils"
2
+
3
+ module Giblish
4
+ # Provides a graphviz-formatted digraph of the provided node<->id ref map.
5
+ #
6
+ # See https://graphviz.gitlab.io/doc/conv_info/lang.html for one definition of the
7
+ # language.
8
+ #
9
+ # A short example:
10
+ #
11
+ # [graphviz,target="docdeps",format="svg",svg-type="inline"]
12
+ # ....
13
+ # digraph document_deps {
14
+ # bgcolor="#33333310"
15
+ # node [shape=note,
16
+ # fillcolor="#ebf26680",
17
+ # style="filled,solid"
18
+ # ]
19
+ #
20
+ # rankdir="LR"
21
+ #
22
+ #
23
+ # "D-3"[label="D-3\n Doc 3", URL="file3.html" ]
24
+ # "D-2"[label="D-2\n Doc 2", URL="my/file2.html" ]
25
+ # "D-1"[label="D-1\n Doc 1", URL="my/subdir/file1.html" ]
26
+ # "D-1" -> { "D-2" "D-3"}
27
+ # "D-2" -> { "D-1"}
28
+ # "D-3"
29
+ # }
30
+ # ....
31
+ class DotDigraphAdoc
32
+ # info_2_ids:: A {ConversionInfo => [doc id refs]} hash.
33
+ #
34
+ # The following properties are expected from the ConversionInfo:
35
+ # title:: String
36
+ # doc_id:: String
37
+ # dst_rel_path:: String - the relative path from a the repo top to a doc
38
+ # in the dst tree
39
+ #
40
+ # target::
41
+ # format::
42
+ # opts:: additional options {"opt" => "value"}. Currently supported:
43
+ #
44
+ # cachedir:: the directory to use for storing files produced during diagram generation.
45
+ # svg-type:: how to embed svg images
46
+ #
47
+ def initialize(info_2_ids:, target: "gibgraph", format: "svg", opts: {"svg-type" => "inline"})
48
+ @info_2_ids = info_2_ids
49
+ @target = target
50
+ @format = format
51
+ @opts = opts
52
+
53
+ @noid_docs = {}
54
+ @next_id = 0
55
+ end
56
+
57
+ def source
58
+ <<~DOC_STR
59
+ #{graph_header}
60
+ #{generate_labels}
61
+ #{generate_deps}
62
+ #{graph_footer}
63
+ DOC_STR
64
+ end
65
+
66
+ private
67
+
68
+ def graph_header
69
+ opt_str = @opts.collect { |key, value| "#{key}=\"#{value}\"" }.join(",")
70
+ <<~DOC_STR
71
+ [graphviz,target="#{@target}",format="#{@format}",#{opt_str}]
72
+ ....
73
+ digraph document_deps {
74
+ bgcolor="#33333310"
75
+ labeljust=l
76
+ node [shape=note,
77
+ fillcolor="#ebf26680",
78
+ style="filled,solid"
79
+ ]
80
+
81
+ rankdir="LR"
82
+
83
+ DOC_STR
84
+ end
85
+
86
+ def graph_footer
87
+ <<~DOC_STR
88
+ }
89
+ ....
90
+ DOC_STR
91
+ end
92
+
93
+ def make_dot_entry(doc_dict, conv_info)
94
+ title = if conv_info&.title.nil?
95
+ ""
96
+ else
97
+ # remove html markup in the title for displaying in the tree
98
+ stripped_title = conv_info.title.gsub(/<.*?>/, "")
99
+ stripped_title.tr!('"', "'")
100
+ Giblish.break_line(stripped_title, 16).join("\n")
101
+ end
102
+
103
+ # title = conv_info&.title.nil? ? "" : Giblish.break_line(conv_info.title, 16).join("\n")
104
+ # create the label used to display the node in the graph
105
+ dot_entry = if conv_info.docid.nil?
106
+ doc_id = next_fake_id
107
+ @noid_docs[conv_info] = doc_id
108
+ "\"#{doc_id}\"[label=\"-\n#{title}\""
109
+ else
110
+ doc_id = conv_info.docid
111
+ "\"#{conv_info.docid}\"[label=\"#{conv_info.docid}\n#{title}\""
112
+ end
113
+
114
+ # add clickable links in the case of html output (this is not supported
115
+ # out-of-the-box for pdf).
116
+ rp = conv_info.dst_rel_path
117
+ dot_entry += case rp.extname
118
+ when ".html"
119
+ ", URL=\"#{rp}\" ]"
120
+ else
121
+ " ]"
122
+ end
123
+ doc_dict[doc_id] = dot_entry
124
+ end
125
+
126
+ # create an entry in the 'dot' description for each
127
+ # document, sort them according to descending doc id to
128
+ # get them displayed in the opposite order in the graph
129
+ def generate_labels
130
+ node_dict = {}
131
+ @info_2_ids.each_key do |conv_info|
132
+ next unless conv_info.converted
133
+
134
+ make_dot_entry node_dict, conv_info
135
+ end
136
+ # sort the nodes by reverse doc id
137
+ node_dict = node_dict.sort.reverse.to_h
138
+
139
+ # produce the string with all node entries
140
+ node_dict.map do |_k, v|
141
+ v
142
+ end.join("\n")
143
+ end
144
+
145
+ def generate_deps
146
+ dep_str = ""
147
+ @info_2_ids.each do |conv_info, targets|
148
+ # set either the real or the generated id as source
149
+ src_part = if conv_info.docid.nil?
150
+ "\"#{@noid_docs[conv_info]}\""
151
+ else
152
+ "\"#{conv_info.docid}\""
153
+ end
154
+
155
+ if targets.length.zero?
156
+ dep_str += "#{src_part}\n"
157
+ next
158
+ end
159
+
160
+ dep_str += "#{src_part} -> {" + targets.reduce("") do |acc, target|
161
+ acc + " \"#{target}\""
162
+ end
163
+ # replace last comma with newline
164
+ dep_str += "}\n"
165
+ end
166
+ dep_str
167
+ end
168
+
169
+ def next_fake_id
170
+ @next_id += 1
171
+ "_generated_id_#{@next_id.to_s.rjust(4, "0")}"
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,10 @@
1
+ = Documents under '<%= @title %>'
2
+ Generated at: <%= Time.now.strftime("%Y-%m-%d %H:%M") %>
3
+ :icons: font
4
+
5
+ <%= tree_summary %>
6
+
7
+ == Document Details
8
+
9
+ <%= document_details %>
10
+
@@ -0,0 +1,132 @@
1
+ require "erb"
2
+ require_relative "verbatimtree"
3
+ require_relative "d3treegraph"
4
+
5
+ module Giblish
6
+ class SubtreeIndexBase < SubtreeSrcItf
7
+ attr_reader :src_location
8
+
9
+ DEFAULT_INDEX_ERB = "/standard_index.erb"
10
+
11
+ def initialize(pathtree, output_basename)
12
+ @pathtree = pathtree
13
+ @output_basename = output_basename
14
+ @src_location = pathtree.pathname.dirname
15
+ @title = pathtree.segment
16
+ end
17
+
18
+ def adoc_source
19
+ erb_template = File.read(__dir__ + DEFAULT_INDEX_ERB)
20
+ ERB.new(erb_template, trim_mode: "<>").result(binding)
21
+ end
22
+
23
+ def tree_summary
24
+ VerbatimTree.new(@pathtree.sort_leaf_first!, {dir_index_base_name: @output_basename}).source
25
+ # str = "++++\n"
26
+ # str += D3TreeGraph.new(tree: @pathtree, options: {dir_index_base_name: @output_basename}).source
27
+ # str += "\n++++"
28
+ # str
29
+ end
30
+
31
+ def document_details
32
+ details_str = ""
33
+
34
+ @pathtree.traverse_preorder do |_level, node|
35
+ next unless node.leaf?
36
+
37
+ d = node.data
38
+ details_str << (d.converted ? document_detail(node) : document_detail_fail(d))
39
+ end
40
+ details_str
41
+ end
42
+
43
+ protected
44
+
45
+ def document_detail_fail(node_data)
46
+ <<~FAIL_INFO
47
+ === #{node_data.src_basename}
48
+
49
+ Source file::
50
+ #{node_data.src_node.segment}
51
+
52
+ Error detail::
53
+ #{node_data.error_msg}
54
+
55
+ ''''
56
+
57
+ FAIL_INFO
58
+ end
59
+
60
+ # Show some details about file content
61
+ def document_detail(node)
62
+ node_data = node.data
63
+ <<~DETAIL_SRC
64
+ [[#{Giblish.to_valid_id(node.pathname.to_s, "_", "_", true)}]]
65
+ === pass:[#{node_data.title.encode("utf-8")}]
66
+
67
+ #{"Doc id::\n_#{node_data.docid}_" unless node_data.docid.nil?}
68
+
69
+ #{"Purpose::\n#{node_data.purpose_str}" unless node_data.purpose_str.to_s.empty?}
70
+
71
+ #{if node_data.stderr.empty?
72
+ ""
73
+ else
74
+ "Conversion issues::\n"\
75
+ "#{node_data.stderr.gsub(/^/, " * ")}"
76
+ end
77
+ }
78
+
79
+ Source file::
80
+ #{node_data.src_node.segment}
81
+
82
+ '''
83
+
84
+ DETAIL_SRC
85
+ end
86
+ end
87
+
88
+ # Generates a directory index with history info for all files under the
89
+ # given subdir node.
90
+ class SubtreeIndexGit < SubtreeIndexBase
91
+ # The fixed heading of the table used to display file history
92
+ HISTORY_TABLE_HEADING = <<~HISTORY_HEADER
93
+ File history::
94
+
95
+ [cols=\"2,3,8,3\",options=\"header\"]
96
+ |===
97
+ |Date |Author |Message |Sha1
98
+ HISTORY_HEADER
99
+
100
+ HISTORY_TABLE_FOOTING = <<~HIST_FOOTER
101
+
102
+ |===\n\n
103
+ HIST_FOOTER
104
+
105
+ def subtitle(dst_node)
106
+ "from #{dst_node.data.branch}"
107
+ end
108
+
109
+ def document_detail_fail(node_data)
110
+ super(node_data) + generate_history_info(node_data)
111
+ end
112
+
113
+ def document_detail(node_data)
114
+ super(node_data) + generate_history_info(node_data)
115
+ end
116
+
117
+ def generate_history_info(node_data)
118
+ return "Could not find history information\n\n" unless node_data.respond_to?(:history)
119
+
120
+ # Generate table rows of history information
121
+ rows = node_data.history.collect do |h|
122
+ <<~HISTORY_ROW
123
+ |#{h.date.strftime("%Y-%m-%d")}
124
+ |#{h.author}
125
+ |#{h.message}
126
+ |#{h.sha1[0..7]} ...
127
+ HISTORY_ROW
128
+ end.join("\n\n")
129
+ HISTORY_TABLE_HEADING + rows + HISTORY_TABLE_FOOTING
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,111 @@
1
+ <!DOCTYPE html>
2
+ <meta charset="utf-8">
3
+ <style>
4
+
5
+ html, body{
6
+ height: 100%;
7
+ margin: 0;
8
+ padding: 0;
9
+ }
10
+
11
+ .node {
12
+ cursor: pointer;
13
+ }
14
+
15
+ .node:hover {
16
+ stroke: #000;
17
+ stroke-width: 1.5px;
18
+ }
19
+
20
+ .node--leaf {
21
+ fill: white;
22
+ }
23
+
24
+ .label {
25
+ font: 11px "Helvetica Neue", Helvetica, Arial, sans-serif;
26
+ text-anchor: middle;
27
+ text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff, 0 -1px 0 #fff;
28
+ }
29
+
30
+ .label,
31
+ .node--root,
32
+ .node--leaf {
33
+ pointer-events: none;
34
+ }
35
+
36
+ </style>
37
+ <svg width="100%" height="100%"></svg>
38
+ <script src="https://d3js.org/d3.v4.min.js"></script>
39
+ <script>
40
+ // Copied from https://bl.ocks.org/mbostock/7607535
41
+ var width = window.innerWidth,
42
+ height = window.innerHeight;
43
+ var svg = d3.select("svg"),
44
+ margin = 20,
45
+ diameter = Math.min(width, height),
46
+ g = svg.append("g").attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");
47
+
48
+ var color = d3.scaleLinear()
49
+ .domain([-1, 5])
50
+ .range(["hsl(152,80%,80%)", "hsl(228,30%,40%)"])
51
+ .interpolate(d3.interpolateHcl);
52
+
53
+ var pack = d3.pack()
54
+ .size([diameter - margin, diameter - margin])
55
+ .padding(2);
56
+
57
+ root = <%= tree.to_json %>;
58
+ root = d3.hierarchy(root)
59
+ .sum(function(d) { return d.children.length + 1; })
60
+ .sort(function(a, b) { return b.value - a.value; });
61
+
62
+ var focus = root,
63
+ nodes = pack(root).descendants(),
64
+ view;
65
+
66
+ var circle = g.selectAll("circle")
67
+ .data(nodes)
68
+ .enter().append("circle")
69
+ .attr("class", function(d) { return d.parent ? d.children ? "node" : "node node--leaf" : "node node--root"; })
70
+ .style("fill", function(d) { return d.children ? color(d.depth) : null; })
71
+ .on("click", function(d) { if (focus !== d) zoom(d), d3.event.stopPropagation(); });
72
+
73
+ var text = g.selectAll("text")
74
+ .data(nodes)
75
+ .enter().append("text")
76
+ .attr("class", "label")
77
+ .style("fill-opacity", function(d) { return d.parent === root ? 1 : 0; })
78
+ .style("display", function(d) { return d.parent === root ? "inline" : "none"; })
79
+ .text(function(d) { return d.data.name; });
80
+
81
+ var node = g.selectAll("circle,text");
82
+
83
+ svg
84
+ .style("background", color(-1))
85
+ .on("click", function() { zoom(root); });
86
+
87
+ zoomTo([root.x, root.y, root.r * 2 + margin]);
88
+
89
+ function zoom(d) {
90
+ var focus0 = focus; focus = d;
91
+
92
+ var transition = d3.transition()
93
+ .duration(d3.event.altKey ? 7500 : 750)
94
+ .tween("zoom", function(d) {
95
+ var i = d3.interpolateZoom(view, [focus.x, focus.y, focus.r * 2 + margin]);
96
+ return function(t) { zoomTo(i(t)); };
97
+ });
98
+
99
+ transition.selectAll("text")
100
+ .filter(function(d) { return d.parent === focus || this.style.display === "inline"; })
101
+ .style("fill-opacity", function(d) { return d.parent === focus ? 1 : 0; })
102
+ .on("start", function(d) { if (d.parent === focus) this.style.display = "inline"; })
103
+ .on("end", function(d) { if (d.parent !== focus) this.style.display = "none"; });
104
+ }
105
+
106
+ function zoomTo(v) {
107
+ var k = diameter / v[2]; view = v;
108
+ node.attr("transform", function(d) { return "translate(" + (d.x - v[0]) * k + "," + (d.y - v[1]) * k + ")"; });
109
+ circle.attr("r", function(d) { return d.r * k; });
110
+ }
111
+ </script>
@@ -0,0 +1,61 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+
5
+ <meta charset="utf-8">
6
+ <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/spiermar/d3-flame-graph@1.0.4/dist/d3.flameGraph.min.css">
7
+ <style>
8
+ html, body{
9
+ height: 100%;
10
+ margin: 0;
11
+ padding: 0;
12
+ font-size: 14px;
13
+ }
14
+ </style>
15
+ <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
16
+ <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.min.js"></script>
17
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/spiermar/d3-flame-graph@1.0.4/dist/d3.flameGraph.min.js"></script>
18
+
19
+ </head>
20
+ <body>
21
+
22
+ <div class="container">
23
+ <div id="chart">
24
+ </div>
25
+ </div>
26
+ <script>
27
+ // Uses D3js flamegraph: https://github.com/spiermar/d3-flame-graph
28
+ var flameGraph = d3.flameGraph()
29
+ .width(window.innerWidth)
30
+ .cellHeight(18)
31
+ .transitionDuration(750)
32
+ .transitionEase(d3.easeCubic)
33
+ .sort(true)
34
+ .title("");
35
+
36
+ var tip = d3.tip()
37
+ .direction("s")
38
+ .offset([8, 0])
39
+ .attr('class', 'd3-flame-graph-tip')
40
+ .html(function(d) { return "name: " + d.data.name + ", value: " + d.data.value; });
41
+
42
+ flameGraph.tooltip(tip);
43
+
44
+ function setValue(d) {
45
+ var val = 0;
46
+ for( var i=0; i<d.children.length; i++){
47
+ setValue(d.children[i]);
48
+ val += d.children[i].value;
49
+ }
50
+ d.value = val == 0 ? 1 : val;
51
+ }
52
+
53
+ root = <%= tree.to_json %>;
54
+ setValue(root)
55
+ d3.select("#chart")
56
+ .datum(root)
57
+ .call(flameGraph);
58
+ </script>
59
+
60
+ </body>
61
+ </html>