feat(ui): replace text suffixes with color-coded SVG badges (THE-73)

Parse (T)/(D)/(R)/(M) suffixes from tool names and render them as
colored tspan elements in the SVG tree. Add matching badge pill styles
to the HTML legend so it visually matches the tree indicators.

- T (tool) → blue #4a9eda
- D (dork) → orange #e8944a
- R (registration) → amber #c8a030
- M (manual URL) → purple #9a7eda

Badge colors are theme-invariant; they work on both dark and light
backgrounds without separate light-mode overrides.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
s0lray
2026-03-24 18:51:15 -04:00
co-authored by Paperclip
parent 2435807c29
commit b684b3cd88
3 changed files with 56 additions and 6 deletions
+21
View File
@@ -12,6 +12,12 @@
--color-noscript-border: #7a4a00;
--color-legend: #e0e0e0;
--color-header: #e0e0e0;
/* Status badge colors — saturated enough for both light and dark backgrounds */
--badge-T: #4a9eda;
--badge-D: #e8944a;
--badge-R: #c8a030;
--badge-M: #9a7eda;
}
body.light-mode {
@@ -105,3 +111,18 @@ h3 {
a {
color: var(--color-node-stroke);
}
/* Status badge pills (used in legend) */
.badge {
display: inline-block;
font-size: 10px;
font-weight: bold;
padding: 1px 4px;
border-radius: 3px;
color: #fff;
vertical-align: middle;
}
.badge-T { background-color: var(--badge-T); }
.badge-D { background-color: var(--badge-D); }
.badge-R { background-color: var(--badge-R); }
.badge-M { background-color: var(--badge-M); }
+6 -4
View File
@@ -32,10 +32,12 @@
<script src="js/arf.js"></script>
<div class="legend"><p>(T) - Indicates a link to a tool that must be installed and run locally<br>
(D) - Google Dork, for more information: <a href="https://en.wikipedia.org/wiki/Google_hacking">Google Hacking</a><br>
(R) - Requires registration<br>
(M) - Indicates a URL that contains the search term and the URL itself must be edited manually<br></p>
<div class="legend"><p>
<span class="badge badge-T">T</span> - Indicates a link to a tool that must be installed and run locally<br>
<span class="badge badge-D">D</span> - Google Dork, for more information: <a href="https://en.wikipedia.org/wiki/Google_hacking">Google Hacking</a><br>
<span class="badge badge-R">R</span> - Requires registration<br>
<span class="badge badge-M">M</span> - Indicates a URL that contains the search term and the URL itself must be edited manually<br>
</p>
<button id="theme-toggle" onclick="goDark()">Switch to light mode</button>
<script>
(function() {
+29 -2
View File
@@ -22,6 +22,22 @@ function getCSSVar(name) {
return getComputedStyle(document.body).getPropertyValue(name).trim();
}
// Parse "(T)", "(D)", "(R)", "(M)" suffixes out of a tool name.
// Returns { cleanName: string, badges: string[] }.
var BADGE_TYPES = ['T', 'D', 'R', 'M'];
function parseName(name) {
var badges = [];
var clean = name;
BADGE_TYPES.forEach(function(b) {
var suffix = ' (' + b + ')';
if (clean.indexOf(suffix) !== -1) {
badges.push(b);
clean = clean.replace(suffix, '');
}
});
return { cleanName: clean, badges: badges };
}
d3.json("arf.json").then(function(json) {
root = d3.hierarchy(json, function(d) {
return d && d.children ? d.children.filter(function(c) { return c != null; }) : null;
@@ -72,11 +88,22 @@ function update(source) {
.attr("x", function(d) { return d.children || d._children ? -10 : 10; })
.attr("dy", ".35em")
.attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
.text(function(d) { return d.data.name; })
.style("fill", function(d) {
return d.data.free ? getCSSVar("--color-text-primary") : getCSSVar("--color-text-secondary");
})
.style("fill-opacity", 1e-6);
.style("fill-opacity", 1e-6)
.each(function(d) {
var parsed = parseName(d.data.name);
var el = d3.select(this);
el.append("tspan").text(parsed.cleanName);
parsed.badges.forEach(function(b) {
el.append("tspan")
.attr("dx", "4")
.style("font-size", "10px")
.style("fill", getCSSVar("--badge-" + b))
.text("(" + b + ")");
});
});
nodeEnter.append("title")
.text(function(d) {