Skip to content

Commit 82f9e36

Browse files
committed
[DOC] add section for opt. backends
1 parent a4c4c15 commit 82f9e36

7 files changed

Lines changed: 427 additions & 63 deletions

File tree

docs/source/_static/css/custom.css

Lines changed: 158 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@
2222
--card-shadow-hover: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
2323
/* Neutral separator color */
2424
--separator-color: #dee2e6;
25+
26+
/* Backend brand colors - from official logos */
27+
--gfo-light: #80b4ff;
28+
--gfo-dark: #000054;
29+
--gfo-grey: #555555;
30+
--optuna-dark: #123692;
31+
--optuna-light: #3b82c4;
32+
--sklearn-orange: #F7931E;
33+
--sklearn-blue: #29ABE2;
2534
}
2635

2736
html[data-theme="dark"] {
@@ -187,16 +196,54 @@ html[data-theme="dark"] .feature-card:hover {
187196

188197
.feature-card .sd-card-footer {
189198
font-size: 0.85rem;
190-
color: var(--hyperactive-secondary);
199+
color: var(--hyperactive-dark);
200+
padding: 0;
201+
background: #f0f1f3;
202+
border-top: 1px solid #e0e2e6;
203+
}
204+
205+
.feature-card .sd-card-footer p {
206+
margin: 0;
207+
}
208+
209+
.feature-card .sd-card-footer a {
210+
display: block;
191211
padding: 0.75rem 1.25rem;
192-
background: #f8f9fa;
193-
border-top: 1px solid #e9ecef;
212+
color: var(--hyperactive-dark);
213+
text-decoration: none;
214+
transition: all 0.2s ease;
215+
position: relative;
216+
}
217+
218+
.feature-card .sd-card-footer a::after {
219+
content: " →";
220+
opacity: 0;
221+
transition: opacity 0.2s ease, transform 0.2s ease;
222+
display: inline-block;
223+
}
224+
225+
.feature-card .sd-card-footer a:hover {
226+
background: var(--hyperactive-primary);
227+
color: #ffffff;
228+
}
229+
230+
.feature-card .sd-card-footer a:hover::after {
231+
opacity: 1;
194232
}
195233

196234
html[data-theme="dark"] .feature-card .sd-card-footer {
197-
background: #252530;
235+
background: #2a2a3a;
198236
border-top-color: #3d3d4d;
199-
color: var(--hyperactive-accent);
237+
color: #c8c8d8;
238+
}
239+
240+
html[data-theme="dark"] .feature-card .sd-card-footer a {
241+
color: #c8c8d8;
242+
}
243+
244+
html[data-theme="dark"] .feature-card .sd-card-footer a:hover {
245+
background: var(--hyperactive-secondary);
246+
color: #ffffff;
200247
}
201248

202249
/* ============================================
@@ -235,6 +282,112 @@ html[data-theme="dark"] .algo-card {
235282
border-left-color: var(--hyperactive-primary) !important;
236283
}
237284

285+
/* ============================================
286+
Backend Cards (GFO, Optuna, sklearn)
287+
============================================ */
288+
.backend-card {
289+
border-radius: 8px !important;
290+
overflow: hidden;
291+
box-shadow: var(--card-shadow);
292+
border: none !important;
293+
position: relative;
294+
background: var(--pst-color-surface);
295+
}
296+
297+
/* Side accent bar using pseudo-element for multi-color support */
298+
.backend-card::before {
299+
content: '';
300+
position: absolute;
301+
left: 0;
302+
top: 0;
303+
bottom: 0;
304+
width: 6px;
305+
border-radius: 8px 0 0 8px;
306+
}
307+
308+
.backend-card .sd-card-header {
309+
padding: 1.25rem 1.5rem 0.75rem;
310+
border-bottom: none;
311+
background: transparent;
312+
}
313+
314+
.backend-card .sd-card-header .sd-card-text {
315+
font-size: 1.25rem;
316+
font-weight: 600;
317+
margin: 0;
318+
}
319+
320+
.backend-card .sd-card-header a {
321+
text-decoration: none;
322+
transition: opacity 0.2s ease;
323+
}
324+
325+
.backend-card .sd-card-header a:hover {
326+
text-decoration: underline;
327+
}
328+
329+
.backend-card .sd-card-body {
330+
padding: 0.5rem 1.5rem 1rem;
331+
font-size: 0.95rem;
332+
line-height: 1.6;
333+
}
334+
335+
.backend-card .sd-card-body ul {
336+
margin: 0.75rem 0 0 0;
337+
padding-left: 1.25rem;
338+
}
339+
340+
.backend-card .sd-card-body li {
341+
margin-bottom: 0.4rem;
342+
}
343+
344+
.backend-card .sd-card-footer {
345+
padding: 0;
346+
border-top: 1px solid var(--pst-color-border);
347+
background: transparent;
348+
}
349+
350+
.backend-card .sd-card-footer a {
351+
display: block;
352+
padding: 0.875rem 1.5rem;
353+
text-decoration: none;
354+
font-weight: 500;
355+
transition: all 0.2s ease;
356+
position: relative;
357+
}
358+
359+
.backend-card .sd-card-footer a::after {
360+
content: " →";
361+
opacity: 0.5;
362+
transition: all 0.2s ease;
363+
}
364+
365+
.backend-card .sd-card-footer a:hover {
366+
padding-left: 1.75rem;
367+
}
368+
369+
.backend-card .sd-card-footer a:hover::after {
370+
opacity: 1;
371+
}
372+
373+
/* GFO: Tri-color (dark navy | light blue | grey) */
374+
.backend-card-gfo::before {
375+
background: linear-gradient(to bottom,
376+
var(--gfo-dark) 0%, var(--gfo-dark) 33%,
377+
var(--gfo-light) 33%, var(--gfo-light) 66%,
378+
var(--gfo-grey) 66%, var(--gfo-grey) 100%);
379+
}
380+
381+
/* Optuna: Vertical gradient (dark blue → light blue) */
382+
.backend-card-optuna::before {
383+
background: linear-gradient(to bottom, var(--optuna-dark) 0%, var(--optuna-light) 100%);
384+
}
385+
386+
/* sklearn: 50/50 split (orange | cyan) */
387+
.backend-card-sklearn::before {
388+
background: linear-gradient(to bottom, var(--sklearn-orange) 50%, var(--sklearn-blue) 50%);
389+
}
390+
238391
/* ============================================
239392
Integration Cards
240393
============================================ */
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Badge Generator for Hyperactive Documentation
4+
5+
Generates local SVG badges based on project information from pyproject.toml.
6+
This eliminates dependency on external badge services like shields.io.
7+
8+
Usage:
9+
python generate_badges.py
10+
11+
Output:
12+
- version.svg
13+
- python.svg
14+
- license.svg
15+
- sponsor.svg
16+
"""
17+
18+
import re
19+
from pathlib import Path
20+
21+
try:
22+
import tomllib
23+
except ImportError:
24+
import tomli as tomllib
25+
26+
27+
# Hyperactive color palette
28+
COLORS = {
29+
"primary": "#5D5D7A",
30+
"secondary": "#7070A0",
31+
"dark": "#4A4A65",
32+
"light": "#f8f9fa",
33+
"sponsor": "#0eac92",
34+
"label_bg": "#555",
35+
}
36+
37+
38+
def create_badge_svg(label: str, value: str, color: str, label_width: int = None, value_width: int = None) -> str:
39+
"""
40+
Create an SVG badge in shields.io flat-square style.
41+
42+
Args:
43+
label: Left side text (e.g., "version")
44+
value: Right side text (e.g., "5.0.2")
45+
color: Hex color for the value background
46+
label_width: Override calculated label width
47+
value_width: Override calculated value width
48+
49+
Returns:
50+
SVG string
51+
"""
52+
# Approximate width calculation (7px per character + padding)
53+
char_width = 6.5
54+
padding = 10
55+
56+
lw = label_width or int(len(label) * char_width + padding * 2)
57+
vw = value_width or int(len(value) * char_width + padding * 2)
58+
total_width = lw + vw
59+
height = 20
60+
61+
svg = f'''<svg xmlns="http://www.w3.org/2000/svg" width="{total_width}" height="{height}">
62+
<title>{label}: {value}</title>
63+
<!-- Label background -->
64+
<rect width="{lw}" height="{height}" fill="{COLORS['label_bg']}"/>
65+
<!-- Value background -->
66+
<rect x="{lw}" width="{vw}" height="{height}" fill="{color}"/>
67+
<!-- Label text -->
68+
<text x="{lw/2}" y="14" fill="#fff" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11" text-anchor="middle">{label}</text>
69+
<!-- Value text -->
70+
<text x="{lw + vw/2}" y="14" fill="#fff" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11" text-anchor="middle">{value}</text>
71+
</svg>'''
72+
73+
return svg
74+
75+
76+
def create_simple_badge_svg(text: str, color: str, width: int = None) -> str:
77+
"""
78+
Create a simple single-section SVG badge.
79+
80+
Args:
81+
text: Badge text
82+
color: Background color
83+
width: Override calculated width
84+
85+
Returns:
86+
SVG string
87+
"""
88+
char_width = 7
89+
padding = 16
90+
w = width or int(len(text) * char_width + padding * 2)
91+
height = 20
92+
93+
svg = f'''<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{height}">
94+
<title>{text}</title>
95+
<rect width="{w}" height="{height}" fill="{color}"/>
96+
<text x="{w/2}" y="14" fill="#fff" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11" text-anchor="middle" font-weight="600">{text}</text>
97+
</svg>'''
98+
99+
return svg
100+
101+
102+
def extract_python_versions(classifiers: list) -> str:
103+
"""Extract Python version range from classifiers."""
104+
versions = []
105+
pattern = r"Programming Language :: Python :: (\d+\.\d+)"
106+
107+
for classifier in classifiers:
108+
match = re.match(pattern, classifier)
109+
if match:
110+
versions.append(match.group(1))
111+
112+
if not versions:
113+
return "3.10+"
114+
115+
versions.sort(key=lambda v: tuple(map(int, v.split("."))))
116+
117+
if len(versions) == 1:
118+
return versions[0]
119+
120+
return f"{versions[0]} - {versions[-1]}"
121+
122+
123+
def main():
124+
# Find pyproject.toml
125+
script_dir = Path(__file__).parent
126+
project_root = script_dir.parents[4] # Go up from docs/source/_static/images/badges
127+
pyproject_path = project_root / "pyproject.toml"
128+
129+
if not pyproject_path.exists():
130+
print(f"Error: pyproject.toml not found at {pyproject_path}")
131+
return
132+
133+
# Read project info
134+
with open(pyproject_path, "rb") as f:
135+
pyproject = tomllib.load(f)
136+
137+
project = pyproject.get("project", {})
138+
version = project.get("version", "0.0.0")
139+
classifiers = project.get("classifiers", [])
140+
141+
# Extract license from classifiers
142+
license_name = "MIT" # Default
143+
for classifier in classifiers:
144+
if "License :: OSI Approved ::" in classifier:
145+
license_name = classifier.split("::")[-1].strip()
146+
# Shorten common license names
147+
if "MIT" in license_name:
148+
license_name = "MIT"
149+
elif "BSD" in license_name:
150+
license_name = "BSD"
151+
elif "Apache" in license_name:
152+
license_name = "Apache 2.0"
153+
break
154+
155+
python_range = extract_python_versions(classifiers)
156+
157+
print(f"Generating badges for Hyperactive v{version}")
158+
print(f" Python: {python_range}")
159+
print(f" License: {license_name}")
160+
161+
# Generate badges
162+
badges = {
163+
"version.svg": create_badge_svg("version", f"v{version}", COLORS["primary"]),
164+
"python.svg": create_badge_svg("python", python_range, COLORS["primary"]),
165+
"license.svg": create_badge_svg("license", license_name, COLORS["primary"]),
166+
"sponsor.svg": create_simple_badge_svg("GC.OS Sponsored", COLORS["sponsor"], width=110),
167+
}
168+
169+
# Write badges
170+
for filename, svg_content in badges.items():
171+
filepath = script_dir / filename
172+
with open(filepath, "w") as f:
173+
f.write(svg_content)
174+
print(f" Created: {filename}")
175+
176+
print("\nDone! Badges generated successfully.")
177+
178+
179+
if __name__ == "__main__":
180+
main()
Lines changed: 11 additions & 0 deletions
Loading
Lines changed: 11 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)