mirror of
https://github.com/nubenetes/awesome-kubernetes.git
synced 2026-08-18 20:07:06 +00:00
feat(v2): add Resource Density Heatmap to Topic Map page
Render a true colour-matrix heatmap on the Topic Map page (distinct from the size-based Label cloud on index/Tags). One tile per category, grouped by strategic dimension, with tile warmth (.th-1..6) encoding how many AI-curated resources it holds. Log scale since counts span ~1..160. The existing directory grid is preserved below a new "Full Category Directory" heading. Generator-only change; the publisher regenerates topic-map.md. CSS adds .topic-heatmap / .topic-heatcell with light + slate palettes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
d19031a65f
commit
154e6940c4
Vendored
+98
@@ -1576,6 +1576,104 @@ input[type="text"] {
|
||||
.topic-map-grid { column-count: 1; }
|
||||
}
|
||||
|
||||
/* ===================================================================
|
||||
Topic Map: Resource Density Heatmap
|
||||
A true colour matrix (distinct from the size-based Label cloud). Each
|
||||
category is a tile whose warmth (.th-1..6) encodes resource density,
|
||||
grouped by strategic dimension. Generated by v2_optimizer.py.
|
||||
=================================================================== */
|
||||
.topic-heatmap {
|
||||
margin: 1rem 0 2rem;
|
||||
padding: 1.1rem 1.2rem 1.3rem;
|
||||
border: 1px solid rgba(38, 50, 56, 0.12);
|
||||
border-radius: 10px;
|
||||
background: rgba(38, 50, 56, 0.04);
|
||||
}
|
||||
[data-md-color-scheme="slate"] .topic-heatmap {
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
border-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.topic-heatmap__legend {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.03em;
|
||||
color: var(--md-default-fg-color--light);
|
||||
}
|
||||
.topic-heatmap__legend .topic-heatcell {
|
||||
width: 26px;
|
||||
height: 14px;
|
||||
padding: 0;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.topic-heatmap__cap { text-transform: uppercase; opacity: 0.7; }
|
||||
.topic-heatmap__row {
|
||||
display: grid;
|
||||
grid-template-columns: 190px 1fr;
|
||||
gap: 0.5rem 1rem;
|
||||
align-items: start;
|
||||
padding: 0.6rem 0;
|
||||
border-top: 1px solid rgba(38, 50, 56, 0.08);
|
||||
}
|
||||
[data-md-color-scheme="slate"] .topic-heatmap__row {
|
||||
border-top-color: rgba(255, 255, 255, 0.07);
|
||||
}
|
||||
.topic-heatmap__row:first-of-type { border-top: none; padding-top: 0; }
|
||||
.topic-heatmap__dim {
|
||||
font-size: 0.78rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.25;
|
||||
padding-top: 0.25rem;
|
||||
color: var(--md-default-fg-color);
|
||||
}
|
||||
.topic-heatmap__cells {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
.topic-heatcell {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
padding: 0.28rem 0.5rem;
|
||||
border-radius: 5px;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
text-decoration: none;
|
||||
color: #1a2327;
|
||||
transition: transform 0.12s ease, box-shadow 0.12s ease;
|
||||
}
|
||||
.topic-heatcell:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 3px 9px rgba(0, 0, 0, 0.18);
|
||||
}
|
||||
.topic-heatcell__n {
|
||||
font-size: 0.62em;
|
||||
font-weight: 700;
|
||||
opacity: 0.7;
|
||||
}
|
||||
/* Sequential warmth ramp: th-1 = sparsest, th-6 = densest. */
|
||||
.th-1 { background: #e3f2fd; }
|
||||
.th-2 { background: #ffe0b2; }
|
||||
.th-3 { background: #ffcc80; }
|
||||
.th-4 { background: #ffa726; }
|
||||
.th-5 { background: #fb8c00; color: #fff; }
|
||||
.th-6 { background: #e64a19; color: #fff; }
|
||||
[data-md-color-scheme="slate"] .th-1 { background: #2d4456; color: #d7e3ea; }
|
||||
[data-md-color-scheme="slate"] .th-2 { background: #6d4c1f; color: #f5e7d3; }
|
||||
[data-md-color-scheme="slate"] .th-3 { background: #97601f; color: #fff3e0; }
|
||||
[data-md-color-scheme="slate"] .th-4 { background: #c2701a; color: #fff; }
|
||||
[data-md-color-scheme="slate"] .th-5 { background: #e2701a; color: #fff; }
|
||||
[data-md-color-scheme="slate"] .th-6 { background: #ff5722; color: #fff; }
|
||||
@media screen and (max-width: 44.9375em) {
|
||||
.topic-heatmap__row { grid-template-columns: 1fr; gap: 0.35rem; }
|
||||
.topic-heatmap__dim { padding-top: 0; }
|
||||
}
|
||||
|
||||
/* Visible label for each YouTube mosaic category block (was hidden in title=) */
|
||||
.mosaic-cat-label {
|
||||
margin: 0 0 0.5rem;
|
||||
|
||||
@@ -1257,6 +1257,59 @@ class V2VisionEngine:
|
||||
total += _count_links(v)
|
||||
return total
|
||||
|
||||
# Resource-density heatmap: a true colour matrix (distinct from the
|
||||
# size-based Label cloud on the index/Tags pages). One tile per category,
|
||||
# grouped by the same strategic dimensions as the directory below, with
|
||||
# tile warmth encoding how many AI-curated resources it holds. Counts span
|
||||
# ~1..160, so a LOG scale is used to avoid collapsing everything into the
|
||||
# lowest bucket. Six levels map onto .th-1..6.
|
||||
cat_counts = {f_name: _count_links(info["content"]) for f_name, info in data.items()}
|
||||
_all_counts = [c for c in cat_counts.values() if c > 0] or [1]
|
||||
_hmin, _hmax = math.log(min(_all_counts)), math.log(max(_all_counts))
|
||||
|
||||
def _topic_heat(count):
|
||||
if count <= 0:
|
||||
return 1
|
||||
if _hmax == _hmin:
|
||||
return 3
|
||||
return 1 + round((math.log(count) - _hmin) / (_hmax - _hmin) * 5) # 1..6
|
||||
|
||||
heatmap_md = (
|
||||
"## Resource Density Heatmap\n\n"
|
||||
"Each tile is a category; the warmer the colour, the more AI-curated "
|
||||
"resources it holds. A fast read of where the Cloud Native ecosystem's "
|
||||
"depth concentrates — click any tile to open its page.\n\n"
|
||||
"<div class=\"topic-heatmap\">\n"
|
||||
"<div class=\"topic-heatmap__legend\">"
|
||||
"<span class=\"topic-heatmap__cap\">Fewer</span>"
|
||||
"<span class=\"topic-heatcell th-1\"></span>"
|
||||
"<span class=\"topic-heatcell th-2\"></span>"
|
||||
"<span class=\"topic-heatcell th-3\"></span>"
|
||||
"<span class=\"topic-heatcell th-4\"></span>"
|
||||
"<span class=\"topic-heatcell th-5\"></span>"
|
||||
"<span class=\"topic-heatcell th-6\"></span>"
|
||||
"<span class=\"topic-heatmap__cap\">More</span>"
|
||||
"</div>\n"
|
||||
)
|
||||
for dim in self.dimensions.keys():
|
||||
if dim not in dim_groups:
|
||||
continue
|
||||
heatmap_md += "<div class=\"topic-heatmap__row\">\n"
|
||||
heatmap_md += f"<div class=\"topic-heatmap__dim\">{dim}</div>\n"
|
||||
heatmap_md += "<div class=\"topic-heatmap__cells\">\n"
|
||||
for f in sorted(dim_groups[dim], key=lambda x: cat_counts[x], reverse=True):
|
||||
count = cat_counts[f]
|
||||
lvl = _topic_heat(count)
|
||||
slug = f[:-3] if f.endswith(".md") else f
|
||||
heatmap_md += (
|
||||
f"<a class=\"topic-heatcell th-{lvl}\" href=\"./{slug}/\" "
|
||||
f"title=\"{data[f]['title']} — {count} resources\">"
|
||||
f"<span class=\"topic-heatcell__name\">{data[f]['title']}</span>"
|
||||
f"<span class=\"topic-heatcell__n\">{count}</span></a>\n"
|
||||
)
|
||||
heatmap_md += "</div>\n</div>\n"
|
||||
heatmap_md += "</div>\n\n"
|
||||
|
||||
topic_md = (
|
||||
"---\n"
|
||||
"description: \"The complete Nubenetes V2 directory: every curated Kubernetes, "
|
||||
@@ -1267,6 +1320,8 @@ class V2VisionEngine:
|
||||
" Every curated category across all strategic dimensions, with the number of "
|
||||
"AI-selected resources in each. Looking for the landing page? Back to the "
|
||||
"[**2026 Vision**](/).\n\n"
|
||||
+ heatmap_md +
|
||||
"## Full Category Directory\n\n"
|
||||
"<div class=\"topic-map-grid\" markdown=\"1\">\n\n"
|
||||
)
|
||||
for dim in self.dimensions.keys():
|
||||
|
||||
Reference in New Issue
Block a user