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.
- checksums.yaml +4 -4
- data/.github/workflows/unit_tests.yml +30 -0
- data/.gitignore +7 -3
- data/.ruby-version +1 -1
- data/Changelog.adoc +61 -0
- data/README.adoc +267 -0
- data/docs/concepts/text_search.adoc +213 -0
- data/docs/concepts/text_search_im/cgi-search_request.puml +35 -0
- data/docs/concepts/text_search_im/cgi-search_request.svg +397 -0
- data/docs/concepts/text_search_im/search_request.puml +40 -0
- data/docs/concepts/text_search_im/search_request.svg +408 -0
- data/docs/howtos/trigger_generation.adoc +180 -0
- data/docs/{setup_server_assets → howtos/trigger_generation_im}/Render Documents.png +0 -0
- data/docs/{setup_server_assets → howtos/trigger_generation_im}/View Documents.png +0 -0
- data/docs/{setup_server_assets → howtos/trigger_generation_im}/deploy_with_hooks.graphml +0 -0
- data/docs/{setup_server_assets → howtos/trigger_generation_im}/deploy_with_hooks.svg +0 -0
- data/docs/{setup_server_assets → howtos/trigger_generation_im}/deploy_with_jenkins.graphml +0 -0
- data/docs/{setup_server_assets → howtos/trigger_generation_im}/deploy_with_jenkins.svg +0 -0
- data/docs/howtos/trigger_generation_im/docgen_github.puml +51 -0
- data/docs/{setup_server_assets → howtos/trigger_generation_im}/giblish_deployment.graphml +0 -0
- data/docs/howtos/trigger_generation_im/post-receive-example.sh +50 -0
- data/docs/reference/box_flow_spec.adoc +22 -0
- data/docs/reference/search_spec.adoc +185 -0
- data/giblish.gemspec +47 -29
- data/lib/giblish/adocsrc_providers.rb +23 -0
- data/lib/giblish/application.rb +214 -41
- data/lib/giblish/cmdline.rb +273 -259
- data/lib/giblish/config_utils.rb +41 -0
- data/lib/giblish/configurator.rb +163 -0
- data/lib/giblish/conversion_info.rb +120 -0
- data/lib/giblish/docattr_providers.rb +125 -0
- data/lib/giblish/docid/docid.rb +181 -0
- data/lib/giblish/github_trigger/webhook_manager.rb +64 -0
- data/lib/giblish/gitrepos/checkoutmanager.rb +124 -0
- data/lib/giblish/{gititf.rb → gitrepos/gititf.rb} +30 -4
- data/lib/giblish/gitrepos/gitsummary.erb +61 -0
- data/lib/giblish/gitrepos/gitsummaryprovider.rb +78 -0
- data/lib/giblish/gitrepos/history_pb.rb +41 -0
- data/lib/giblish/indexbuilders/d3treegraph.rb +88 -0
- data/lib/giblish/indexbuilders/depgraphbuilder.rb +109 -0
- data/lib/giblish/indexbuilders/dotdigraphadoc.rb +174 -0
- data/lib/giblish/indexbuilders/standard_index.erb +10 -0
- data/lib/giblish/indexbuilders/subtree_indices.rb +132 -0
- data/lib/giblish/indexbuilders/templates/circles.html.erb +111 -0
- data/lib/giblish/indexbuilders/templates/flame.html.erb +61 -0
- data/lib/giblish/indexbuilders/templates/tree.html.erb +366 -0
- data/lib/giblish/indexbuilders/templates/treemap.html.erb +127 -0
- data/lib/giblish/indexbuilders/verbatimtree.rb +94 -0
- data/lib/giblish/pathtree.rb +473 -74
- data/lib/giblish/resourcepaths.rb +150 -0
- data/lib/giblish/search/expand_adoc.rb +55 -0
- data/lib/giblish/search/headingindexer.rb +312 -0
- data/lib/giblish/search/request_manager.rb +110 -0
- data/lib/giblish/search/searchquery.rb +68 -0
- data/lib/giblish/search/textsearcher.rb +349 -0
- data/lib/giblish/subtreeinfobuilder.rb +77 -0
- data/lib/giblish/treeconverter.rb +272 -0
- data/lib/giblish/utils.rb +142 -294
- data/lib/giblish/version.rb +1 -1
- data/lib/giblish.rb +10 -7
- data/scripts/hooks/post-receive.example +66 -0
- data/{docgen/scripts/githook_examples → scripts/hooks}/post-update.example +0 -0
- data/{docgen → scripts}/resources/css/adoc-colony.css +0 -0
- data/scripts/resources/css/giblish-serif.css +419 -0
- data/scripts/resources/css/giblish.css +1979 -419
- data/{docgen → scripts}/resources/fonts/Ubuntu-B.ttf +0 -0
- data/{docgen → scripts}/resources/fonts/Ubuntu-BI.ttf +0 -0
- data/{docgen → scripts}/resources/fonts/Ubuntu-R.ttf +0 -0
- data/{docgen → scripts}/resources/fonts/Ubuntu-RI.ttf +0 -0
- data/{docgen → scripts}/resources/fonts/mplus1p-regular-fallback.ttf +0 -0
- data/{docgen → scripts}/resources/images/giblish_logo.png +0 -0
- data/{docgen → scripts}/resources/images/giblish_logo.svg +0 -0
- data/{docgen → scripts}/resources/themes/giblish.yml +0 -0
- data/scripts/wserv_development.rb +32 -0
- data/web_apps/cgi_search/gibsearch.rb +43 -0
- data/web_apps/gh_webhook_trigger/config.ru +2 -0
- data/web_apps/gh_webhook_trigger/gh_webhook_trigger.rb +73 -0
- data/web_apps/gh_webhook_trigger/public/dummy.txt +3 -0
- data/web_apps/sinatra_search/config.ru +2 -0
- data/web_apps/sinatra_search/public/dummy.txt +3 -0
- data/web_apps/sinatra_search/sinatra_search.rb +34 -0
- data/web_apps/sinatra_search/tmp/restart.txt +0 -0
- metadata +168 -73
- data/.rubocop.yml +0 -7
- data/.travis.yml +0 -3
- data/Changelog +0 -16
- data/Gemfile +0 -4
- data/README.adoc +0 -1
- data/Rakefile +0 -41
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/data/testdocs/malformed/no_header.adoc +0 -5
- data/data/testdocs/toplevel.adoc +0 -19
- data/data/testdocs/wellformed/adorned_purpose.adoc +0 -17
- data/data/testdocs/wellformed/docidtest/docid_1.adoc +0 -24
- data/data/testdocs/wellformed/docidtest/docid_2.adoc +0 -8
- data/data/testdocs/wellformed/simple.adoc +0 -14
- data/data/testdocs/wellformed/source_highlighting/highlight_source.adoc +0 -38
- data/docgen/resources/css/giblish.css +0 -1979
- data/docgen/scripts/Jenkinsfile +0 -18
- data/docgen/scripts/gen_adoc_org.sh +0 -58
- data/docs/README.adoc +0 -387
- data/docs/setup_server.adoc +0 -202
- data/lib/giblish/buildgraph.rb +0 -216
- data/lib/giblish/buildindex.rb +0 -459
- data/lib/giblish/core.rb +0 -451
- data/lib/giblish/docconverter.rb +0 -308
- data/lib/giblish/docid.rb +0 -180
- data/lib/giblish/docinfo.rb +0 -75
- data/lib/giblish/indexheadings.rb +0 -251
- data/lib/giblish-search.cgi +0 -459
- data/scripts/hooks/post-receive +0 -57
- 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,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>
|