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,366 @@
|
|
1
|
+
<style type="text/css">
|
2
|
+
.node {
|
3
|
+
cursor: pointer;
|
4
|
+
}
|
5
|
+
|
6
|
+
.overlay {
|
7
|
+
background-color: white;
|
8
|
+
}
|
9
|
+
|
10
|
+
.node circle {
|
11
|
+
fill: lightblue;
|
12
|
+
stroke: steelblue;
|
13
|
+
stroke-width: 1.5px;
|
14
|
+
}
|
15
|
+
|
16
|
+
.node text {
|
17
|
+
font-size: 12px;
|
18
|
+
font-family: sans-serif;
|
19
|
+
}
|
20
|
+
|
21
|
+
.link {
|
22
|
+
fill: none;
|
23
|
+
stroke: #ccc;
|
24
|
+
stroke-width: 1.5px;
|
25
|
+
}
|
26
|
+
</style>
|
27
|
+
|
28
|
+
<div id="tree-container"></div>
|
29
|
+
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
|
30
|
+
<script src="http://d3js.org/d3.v3.min.js"></script>
|
31
|
+
<script>
|
32
|
+
/*Copyright (c) 2013-2016, Rob Schmuecker
|
33
|
+
All rights reserved.
|
34
|
+
|
35
|
+
Redistribution and use in source and binary forms, with or without
|
36
|
+
modification, are permitted provided that the following conditions are met:
|
37
|
+
|
38
|
+
* Redistributions of source code must retain the above copyright notice, this
|
39
|
+
list of conditions and the following disclaimer.
|
40
|
+
|
41
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
42
|
+
this list of conditions and the following disclaimer in the documentation
|
43
|
+
and/or other materials provided with the distribution.
|
44
|
+
|
45
|
+
* The name Rob Schmuecker may not be used to endorse or promote products
|
46
|
+
derived from this software without specific prior written permission.
|
47
|
+
|
48
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
49
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
50
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
51
|
+
DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
|
52
|
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
53
|
+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
54
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
55
|
+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
56
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
57
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
|
58
|
+
|
59
|
+
|
60
|
+
treeData = <%= @tree.to_json %>;
|
61
|
+
|
62
|
+
// Calculate total nodes, max label length
|
63
|
+
var maxLabelLength = 0;
|
64
|
+
// panning variables
|
65
|
+
var panSpeed = 200;
|
66
|
+
// Misc. variables
|
67
|
+
var i = 0;
|
68
|
+
var duration = 750;
|
69
|
+
var root;
|
70
|
+
|
71
|
+
// size of the diagram
|
72
|
+
var viewerWidth = $(document).width() / 2;
|
73
|
+
var viewerHeight = $(document).height() / 2;
|
74
|
+
// var viewerWidth = $(document).width();
|
75
|
+
// var viewerHeight = $(document).height();
|
76
|
+
|
77
|
+
var tree = d3.layout.tree()
|
78
|
+
.size([viewerHeight, viewerWidth])
|
79
|
+
.separation(function (a, b) {
|
80
|
+
// return (a.parent == b.parent ? 1 : 2);// * 3 * a.depth;
|
81
|
+
return 1;
|
82
|
+
});
|
83
|
+
|
84
|
+
// define a d3 diagonal projection for use by the node paths later on.
|
85
|
+
var diagonal = d3.svg.diagonal()
|
86
|
+
.projection(function (d) {
|
87
|
+
return [d.y, d.x];
|
88
|
+
// return [d.x, d.y];
|
89
|
+
});
|
90
|
+
|
91
|
+
// A recursive helper function for performing some setup by walking through all nodes
|
92
|
+
function visit(parent, visitFn, childrenFn) {
|
93
|
+
if (!parent) return;
|
94
|
+
|
95
|
+
visitFn(parent);
|
96
|
+
|
97
|
+
var children = childrenFn(parent);
|
98
|
+
if (children) {
|
99
|
+
var count = children.length;
|
100
|
+
for (var i = 0; i < count; i++) {
|
101
|
+
visit(children[i], visitFn, childrenFn);
|
102
|
+
}
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
// Call visit function to establish maxLabelLength
|
107
|
+
visit(treeData, function (d) {
|
108
|
+
maxLabelLength = Math.max(d.name.length, maxLabelLength);
|
109
|
+
|
110
|
+
}, function (d) {
|
111
|
+
return d.children && d.children.length > 0 ? d.children : null;
|
112
|
+
});
|
113
|
+
|
114
|
+
function pan(domNode, direction) {
|
115
|
+
var speed = panSpeed;
|
116
|
+
if (panTimer) {
|
117
|
+
clearTimeout(panTimer);
|
118
|
+
translateCoords = d3.transform(svgGroup.attr("transform"));
|
119
|
+
if (direction == 'left' || direction == 'right') {
|
120
|
+
translateX = direction == 'left' ? translateCoords.translate[0] + speed : translateCoords.translate[0] - speed;
|
121
|
+
translateY = translateCoords.translate[1];
|
122
|
+
} else if (direction == 'up' || direction == 'down') {
|
123
|
+
translateX = translateCoords.translate[0];
|
124
|
+
translateY = direction == 'up' ? translateCoords.translate[1] + speed : translateCoords.translate[1] - speed;
|
125
|
+
}
|
126
|
+
scaleX = translateCoords.scale[0];
|
127
|
+
scaleY = translateCoords.scale[1];
|
128
|
+
scale = zoomListener.scale();
|
129
|
+
svgGroup.transition().attr("transform", "translate(" + translateX + "," + translateY + ")scale(" + scale + ")");
|
130
|
+
d3.select(domNode).select('g.node').attr("transform", "translate(" + translateX + "," + translateY + ")");
|
131
|
+
zoomListener.scale(zoomListener.scale());
|
132
|
+
zoomListener.translate([translateX, translateY]);
|
133
|
+
panTimer = setTimeout(function () {
|
134
|
+
pan(domNode, speed, direction);
|
135
|
+
}, 50);
|
136
|
+
}
|
137
|
+
}
|
138
|
+
|
139
|
+
// Define the zoom function for the zoomable tree
|
140
|
+
function zoom() {
|
141
|
+
svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
|
142
|
+
}
|
143
|
+
|
144
|
+
|
145
|
+
// define the zoomListener which calls the zoom function on the "zoom" event constrained within the scaleExtents
|
146
|
+
var zoomListener = d3.behavior.zoom().scaleExtent([0.1, 3]).on("zoom", zoom);
|
147
|
+
|
148
|
+
// define the baseSvg, attaching a class for styling and the zoomListener
|
149
|
+
var baseSvg = d3.select("#tree-container").append("svg")
|
150
|
+
.attr("width", viewerWidth)
|
151
|
+
.attr("height", viewerHeight)
|
152
|
+
.attr("class", "overlay")
|
153
|
+
.call(zoomListener);
|
154
|
+
|
155
|
+
// Function to center node when clicked/dropped so node doesn't get lost when collapsing/moving with large amount of children.
|
156
|
+
|
157
|
+
function centerNode(source) {
|
158
|
+
scale = zoomListener.scale();
|
159
|
+
x = -source.y0;
|
160
|
+
y = -source.x0;
|
161
|
+
x = x * scale + viewerWidth / 2;
|
162
|
+
y = y * scale + viewerHeight / 2;
|
163
|
+
d3.select('g').transition()
|
164
|
+
.duration(duration)
|
165
|
+
.attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")");
|
166
|
+
zoomListener.scale(scale);
|
167
|
+
zoomListener.translate([x, y]);
|
168
|
+
}
|
169
|
+
|
170
|
+
// Toggle children function
|
171
|
+
|
172
|
+
function toggleChildren(d) {
|
173
|
+
if (d.children) {
|
174
|
+
d._children = d.children;
|
175
|
+
d.children = null;
|
176
|
+
} else if (d._children) {
|
177
|
+
d.children = d._children;
|
178
|
+
d._children = null;
|
179
|
+
}
|
180
|
+
return d;
|
181
|
+
}
|
182
|
+
|
183
|
+
// Toggle children on click.
|
184
|
+
function click(d) {
|
185
|
+
if (d3.event.defaultPrevented) return; // click suppressed
|
186
|
+
d = toggleChildren(d);
|
187
|
+
update(d);
|
188
|
+
centerNode(d);
|
189
|
+
}
|
190
|
+
|
191
|
+
function update(source) {
|
192
|
+
// Compute the new height, function counts total children of root node and sets tree height accordingly.
|
193
|
+
// This prevents the layout looking squashed when new nodes are made visible or looking sparse when nodes are removed
|
194
|
+
// This makes the layout more consistent.
|
195
|
+
var levelWidth = [1];
|
196
|
+
var childCount = function (level, n) {
|
197
|
+
|
198
|
+
if (n.children && n.children.length > 0) {
|
199
|
+
if (levelWidth.length <= level + 1) levelWidth.push(1);
|
200
|
+
|
201
|
+
levelWidth[level + 1] += n.children.length;
|
202
|
+
n.children.forEach(function (d) {
|
203
|
+
childCount(level + 1, d);
|
204
|
+
});
|
205
|
+
}
|
206
|
+
};
|
207
|
+
childCount(0, root);
|
208
|
+
var newHeight = d3.max(levelWidth) * 50; // 50 pixels per line
|
209
|
+
tree = tree.size([newHeight, viewerWidth]);
|
210
|
+
|
211
|
+
// Compute the new tree layout.
|
212
|
+
var nodes = tree.nodes(root).reverse(),
|
213
|
+
links = tree.links(nodes);
|
214
|
+
|
215
|
+
// Set widths between levels based on maxLabelLength.
|
216
|
+
nodes.forEach(function (d) {
|
217
|
+
d.y = (d.depth * (maxLabelLength * 5)); //maxLabelLength * 10px
|
218
|
+
// alternatively to keep a fixed scale one can set a fixed depth per level
|
219
|
+
// Normalize for fixed-depth by commenting out below line
|
220
|
+
// d.y = (d.depth * 500); //500px per level.
|
221
|
+
});
|
222
|
+
|
223
|
+
// Update the nodes…
|
224
|
+
node = svgGroup.selectAll("g.node")
|
225
|
+
.data(nodes, function (d) {
|
226
|
+
return d.id || (d.id = ++i);
|
227
|
+
});
|
228
|
+
|
229
|
+
// Enter any new nodes at the parent's previous position.
|
230
|
+
var nodeEnter = node.enter().append("g")
|
231
|
+
.attr("class", "node")
|
232
|
+
.attr("transform", function (d) {
|
233
|
+
return "translate(" + source.y0 + "," + source.x0 + ")";
|
234
|
+
})
|
235
|
+
.on('click', click);
|
236
|
+
|
237
|
+
nodeEnter.append("circle")
|
238
|
+
.attr('class', 'nodeCircle')
|
239
|
+
.attr("r", 0)
|
240
|
+
.style("fill", function (d) {
|
241
|
+
return d._children ? "lightsteelblue" : "#fff";
|
242
|
+
});
|
243
|
+
|
244
|
+
nodeEnter.append("svg:a").attr("xlink:href", function (d) { return d.dst_ref })
|
245
|
+
.append("text")
|
246
|
+
.attr("x", function (d) {
|
247
|
+
return d.children || d._children ? -20 : 20;
|
248
|
+
})
|
249
|
+
.attr("dy", ".35em")
|
250
|
+
.attr('class', 'nodeText')
|
251
|
+
.attr("text-anchor", function (d) {
|
252
|
+
return d.children || d._children ? "end" : "start";
|
253
|
+
})
|
254
|
+
.text(function (d) {
|
255
|
+
return d.name;
|
256
|
+
})
|
257
|
+
.style("fill-opacity", 50);
|
258
|
+
|
259
|
+
// Update the text to reflect whether node has children or not.
|
260
|
+
node.select('text')
|
261
|
+
.attr("x", function (d) {
|
262
|
+
return d.children || d._children ? -20 : 20;
|
263
|
+
})
|
264
|
+
.attr("text-anchor", function (d) {
|
265
|
+
return d.children || d._children ? "end" : "start";
|
266
|
+
})
|
267
|
+
.text(function (d) {
|
268
|
+
return d.name;
|
269
|
+
});
|
270
|
+
|
271
|
+
// Change the circle fill depending on whether it has children and is collapsed
|
272
|
+
node.select("circle.nodeCircle")
|
273
|
+
.attr("r", 7)
|
274
|
+
.style("fill", function (d) {
|
275
|
+
return d._children ? "lightsteelblue" : "#fff";
|
276
|
+
});
|
277
|
+
|
278
|
+
// Transition nodes to their new position.
|
279
|
+
var nodeUpdate = node.transition()
|
280
|
+
.duration(duration)
|
281
|
+
.attr("transform", function (d) {
|
282
|
+
// var x = d.x + (d.depth % 2 * 15)
|
283
|
+
// return "translate(" + d.y + "," + x + ")";
|
284
|
+
return "translate(" + d.y + "," + d.x + ")";
|
285
|
+
// return "translate(" + d.x + "," + d.y + ")";
|
286
|
+
});
|
287
|
+
|
288
|
+
// Fade the text in
|
289
|
+
nodeUpdate.select("text")
|
290
|
+
.style("fill-opacity", 1);
|
291
|
+
|
292
|
+
// Transition exiting nodes to the parent's new position.
|
293
|
+
var nodeExit = node.exit().transition()
|
294
|
+
.duration(duration)
|
295
|
+
.attr("transform", function (d) {
|
296
|
+
return "translate(" + source.y + "," + source.x + ")";
|
297
|
+
// return "translate(" + source.x + "," + source.y + ")";
|
298
|
+
})
|
299
|
+
.remove();
|
300
|
+
|
301
|
+
nodeExit.select("circle")
|
302
|
+
.attr("r", 0);
|
303
|
+
|
304
|
+
nodeExit.select("text")
|
305
|
+
.style("fill-opacity", 0);
|
306
|
+
|
307
|
+
// Update the links…
|
308
|
+
var link = svgGroup.selectAll("path.link")
|
309
|
+
.data(links, function (d) {
|
310
|
+
return d.target.id;
|
311
|
+
});
|
312
|
+
|
313
|
+
// Enter any new links at the parent's previous position.
|
314
|
+
link.enter().insert("path", "g")
|
315
|
+
.attr("class", "link")
|
316
|
+
.attr("d", function (d) {
|
317
|
+
var o = {
|
318
|
+
x: source.x0,
|
319
|
+
y: source.y0
|
320
|
+
};
|
321
|
+
return diagonal({
|
322
|
+
source: o,
|
323
|
+
target: o
|
324
|
+
});
|
325
|
+
});
|
326
|
+
|
327
|
+
// Transition links to their new position.
|
328
|
+
link.transition()
|
329
|
+
.duration(duration)
|
330
|
+
.attr("d", diagonal);
|
331
|
+
|
332
|
+
// Transition exiting nodes to the parent's new position.
|
333
|
+
link.exit().transition()
|
334
|
+
.duration(duration)
|
335
|
+
.attr("d", function (d) {
|
336
|
+
var o = {
|
337
|
+
x: source.x,
|
338
|
+
y: source.y
|
339
|
+
};
|
340
|
+
return diagonal({
|
341
|
+
source: o,
|
342
|
+
target: o
|
343
|
+
});
|
344
|
+
})
|
345
|
+
.remove();
|
346
|
+
|
347
|
+
// Stash the old positions for transition.
|
348
|
+
nodes.forEach(function (d) {
|
349
|
+
d.x0 = d.x;
|
350
|
+
d.y0 = d.y;
|
351
|
+
});
|
352
|
+
}
|
353
|
+
|
354
|
+
// Append a group which holds all nodes and which the zoom Listener can act upon.
|
355
|
+
var svgGroup = baseSvg.append("g");
|
356
|
+
|
357
|
+
// Define the root
|
358
|
+
root = treeData;
|
359
|
+
// root.x0 = viewerHeight / 2;
|
360
|
+
root.x0 = 0;
|
361
|
+
root.y0 = viewerWidth / 2;
|
362
|
+
|
363
|
+
// Layout the tree initially and center on the root node.
|
364
|
+
update(root);
|
365
|
+
// centerNode(root);
|
366
|
+
</script>
|
@@ -0,0 +1,127 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<head>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<style>
|
6
|
+
html, body {
|
7
|
+
padding: 0;
|
8
|
+
margin: 0;
|
9
|
+
width: 100%;
|
10
|
+
height: 100%;
|
11
|
+
overflow: hidden;
|
12
|
+
}
|
13
|
+
|
14
|
+
text {
|
15
|
+
font: 12px sans-serif;
|
16
|
+
}
|
17
|
+
|
18
|
+
tspan:last-child {
|
19
|
+
font-size: 12px;
|
20
|
+
fill-opacity: 0.8;
|
21
|
+
}
|
22
|
+
|
23
|
+
.node rect {
|
24
|
+
shape-rendering: crispEdges;
|
25
|
+
}
|
26
|
+
|
27
|
+
.node--hover rect {
|
28
|
+
stroke: #000;
|
29
|
+
}
|
30
|
+
|
31
|
+
</style>
|
32
|
+
<svg width="100%" height="100%"></svg>
|
33
|
+
<script src="http://d3js.org/d3.v4.0.0-alpha.35.min.js"></script>
|
34
|
+
<script>
|
35
|
+
|
36
|
+
var svg = d3.select("svg"),
|
37
|
+
width = window.innerWidth,
|
38
|
+
height = window.innerHeight;
|
39
|
+
|
40
|
+
svg.attr("width", width + "px");
|
41
|
+
svg.attr("height", height + "px");
|
42
|
+
|
43
|
+
var format = d3.format(",d");
|
44
|
+
|
45
|
+
var color = d3.scaleMagma()
|
46
|
+
.domain([-4, 4]);
|
47
|
+
|
48
|
+
var treemap = d3.treemap()
|
49
|
+
.size([width, height])
|
50
|
+
.paddingOuter(3)
|
51
|
+
.paddingTop(19)
|
52
|
+
.paddingInner(1)
|
53
|
+
.round(true);
|
54
|
+
|
55
|
+
|
56
|
+
var data = <%= tree.to_json %>
|
57
|
+
var root = d3.hierarchy(data)
|
58
|
+
.sum(function(d) {
|
59
|
+
var value = 1;
|
60
|
+
d.children.forEach(function(i){ value += i.value; })
|
61
|
+
return value;
|
62
|
+
})
|
63
|
+
.sort(function(a, b) { return b.height - a.height || b.value - a.value; })
|
64
|
+
|
65
|
+
var counter = 0;
|
66
|
+
root.each(function(d){ d.id = counter++; })
|
67
|
+
treemap(root)
|
68
|
+
|
69
|
+
var cell = svg
|
70
|
+
.selectAll(".node")
|
71
|
+
.data(root.descendants())
|
72
|
+
.enter().append("g")
|
73
|
+
.attr("transform", function(d) { return "translate(" + d.x0 + "," + d.y0 + ")"; })
|
74
|
+
.attr("class", "node")
|
75
|
+
.each(function(d) { d.node = this; })
|
76
|
+
.on("mouseover", hovered(true))
|
77
|
+
.on("mouseout", hovered(false));
|
78
|
+
|
79
|
+
cell.append("rect")
|
80
|
+
.attr("id", function(d) { return "rect-" + d.id; })
|
81
|
+
.attr("width", function(d) { return d.x1 - d.x0; })
|
82
|
+
.attr("height", function(d) { return d.y1 - d.y0; })
|
83
|
+
.style("fill", function(d) { return color(d.depth); });
|
84
|
+
|
85
|
+
cell.append("clipPath")
|
86
|
+
.attr("id", function(d) { return "clip-" + d.id; })
|
87
|
+
.append("use")
|
88
|
+
.attr("xlink:href", function(d) { return "#rect-" + d.id + ""; });
|
89
|
+
|
90
|
+
var label = cell.append("text")
|
91
|
+
.attr("clip-path", function(d) { return "url(#clip-" + d.id + ")"; });
|
92
|
+
|
93
|
+
label
|
94
|
+
.filter(function(d) { return d.children; })
|
95
|
+
.selectAll("tspan")
|
96
|
+
.data(function(d) { return [d.data.name]; })
|
97
|
+
.enter().append("tspan")
|
98
|
+
.attr("x", function(d, i) { return i ? null : 4; })
|
99
|
+
.attr("y", 13)
|
100
|
+
.text(function(d) { return d; });
|
101
|
+
|
102
|
+
label
|
103
|
+
.filter(function(d) { return !d.children; })
|
104
|
+
.selectAll("tspan")
|
105
|
+
.data(function(d) { return [d.data.name]; })
|
106
|
+
.enter().append("tspan")
|
107
|
+
.attr("x", 4)
|
108
|
+
.attr("y", function(d, i) { return 13 + i * 10; })
|
109
|
+
.text(function(d) { return d; });
|
110
|
+
|
111
|
+
cell.append("title")
|
112
|
+
.text(function(d) { return d.data.name; });
|
113
|
+
|
114
|
+
function hovered(hover) {
|
115
|
+
return function(d) {
|
116
|
+
d3.selectAll(d.ancestors().map(function(d) { return d.node; }))
|
117
|
+
.classed("node--hover", hover)
|
118
|
+
.select("rect")
|
119
|
+
.attr("width", function(d) { return d.x1 - d.x0 - hover; })
|
120
|
+
.attr("height", function(d) { return d.y1 - d.y0 - hover; });
|
121
|
+
};
|
122
|
+
}
|
123
|
+
|
124
|
+
</script>
|
125
|
+
</head>
|
126
|
+
<body></body>
|
127
|
+
</head>
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Giblish
|
4
|
+
# Generate asciidoc that represents a given pathtree as a
|
5
|
+
# verbatim block with indented, clickable entries.
|
6
|
+
class VerbatimTree
|
7
|
+
# options:
|
8
|
+
# dir_index_base_name: String - the basename of the index file
|
9
|
+
# residing in each directory
|
10
|
+
def initialize(tree, options = {dir_index_base_name: "index"})
|
11
|
+
@tree = tree
|
12
|
+
@nof_missing_titles = 0
|
13
|
+
@options = options.dup
|
14
|
+
end
|
15
|
+
|
16
|
+
def source
|
17
|
+
# output tree intro
|
18
|
+
tree_string = +<<~DOC_HEADER
|
19
|
+
[subs=\"normal\"]
|
20
|
+
----
|
21
|
+
DOC_HEADER
|
22
|
+
|
23
|
+
# generate each tree entry string
|
24
|
+
@tree.traverse_preorder do |level, node|
|
25
|
+
next if level == 0
|
26
|
+
|
27
|
+
tree_string << tree_entry_string(level, node)
|
28
|
+
end
|
29
|
+
|
30
|
+
# generate the tree footer
|
31
|
+
tree_string << "\n----\n"
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def tree_entry_string(level, node)
|
37
|
+
# indent 2 * level
|
38
|
+
prefix_str = " " * (level + 1)
|
39
|
+
|
40
|
+
# return only name for directories
|
41
|
+
return directory_entry(prefix_str, node) unless node.leaf?
|
42
|
+
|
43
|
+
# return links to content and details for files
|
44
|
+
d = node.data
|
45
|
+
if d.converted
|
46
|
+
tree_entry_converted(prefix_str, node)
|
47
|
+
else
|
48
|
+
# no converted file exists, show what we know
|
49
|
+
"#{prefix_str} FAIL: #{d.src_basename} <<#{d.src_basename},details>>\n"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def directory_entry(prefix_str, node)
|
54
|
+
p = node.pathname.relative_path_from(@tree.pathname).join(@options[:dir_index_base_name])
|
55
|
+
"#{prefix_str} <<#{p}#,#{node.segment}>>\n"
|
56
|
+
end
|
57
|
+
|
58
|
+
# Generate an adoc string that will display as
|
59
|
+
# DocTitle (conv issues) details
|
60
|
+
# Where the DocTitle and details are links to the doc itself and a section
|
61
|
+
# identified with the doc's title respectively.
|
62
|
+
def tree_entry_converted(prefix_str, node)
|
63
|
+
# Get the elements of the entry
|
64
|
+
doc_title, doc_link, doc_details = format_title_and_ref(node)
|
65
|
+
warning_label = node.data.stderr.empty? ? "" : "(conv issues)"
|
66
|
+
|
67
|
+
# Calculate padding to get (conv issues) and details aligned in columns
|
68
|
+
padding = 70
|
69
|
+
[doc_title, prefix_str, warning_label].each { |p| padding -= p.length }
|
70
|
+
padding = 0 unless padding.positive?
|
71
|
+
|
72
|
+
"#{prefix_str} #{doc_link}#{" " * padding}#{warning_label} #{doc_details}"
|
73
|
+
end
|
74
|
+
|
75
|
+
# Private: Return adoc elements for displaying a clickable title
|
76
|
+
# and a 'details' ref that points to a section that uses the title as an id.
|
77
|
+
#
|
78
|
+
# Returns [ title, clickableTitleStr, clickableDetailsStr ]
|
79
|
+
def format_title_and_ref(node)
|
80
|
+
conv_info = node.data
|
81
|
+
|
82
|
+
# Use docid and title in title reference
|
83
|
+
title_ref = (conv_info.docid.nil? ? "" : "#{conv_info.docid} - ") + conv_info.title
|
84
|
+
|
85
|
+
# find relative source path from the file to this tree's root
|
86
|
+
p = node.pathname.relative_path_from(@tree.pathname).sub_ext(".adoc")
|
87
|
+
|
88
|
+
# remove html markup in the title for displaying in the tree
|
89
|
+
stripped_title = title_ref.gsub(/<.*?>/, "")
|
90
|
+
[stripped_title, "<<#{p}#,#{stripped_title}>>",
|
91
|
+
"<<#{Giblish.to_valid_id(node.pathname.to_s, "_", "_", true)},details>>\n"]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|