Skip to content

Commit 634dbb1

Browse files
committed
Add GitHub widget injection and styles
1 parent 5143cc9 commit 634dbb1

2 files changed

Lines changed: 226 additions & 0 deletions

File tree

great_docs/assets/post-render.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,3 +733,54 @@ def add_parens_to_functions(match):
733733
file.write(content)
734734

735735
print("Finished processing all files")
736+
737+
738+
# ============================================================================
739+
# GitHub Widget Injection
740+
# ============================================================================
741+
# Replace escaped GitHub widget placeholder with actual HTML
742+
# This handles cases where Quarto escapes the HTML in navbar text items
743+
744+
745+
def inject_github_widget():
746+
"""
747+
Find and replace escaped GitHub widget placeholders with actual widget HTML.
748+
749+
Quarto escapes HTML in navbar text items, so we need to post-process
750+
to inject the actual widget div.
751+
"""
752+
print("Checking for GitHub widget placeholders...")
753+
754+
widget_escaped_pattern = re.compile(
755+
r'<span class="menu-text">&lt;div id="github-widget" '
756+
r'data-owner="([^"]*)" data-repo="([^"]*)"&gt;&lt;/div&gt;</span>'
757+
)
758+
759+
widget_count = 0
760+
761+
for html_file in all_html_files:
762+
with open(html_file, "r") as file:
763+
content = file.read()
764+
765+
# Check if this file has an escaped widget placeholder
766+
match = widget_escaped_pattern.search(content)
767+
if match:
768+
owner = match.group(1)
769+
repo = match.group(2)
770+
771+
# Replace with actual widget HTML
772+
replacement = f'<div id="github-widget" data-owner="{owner}" data-repo="{repo}"></div>'
773+
content = widget_escaped_pattern.sub(replacement, content)
774+
775+
with open(html_file, "w") as file:
776+
file.write(content)
777+
778+
widget_count += 1
779+
780+
if widget_count > 0:
781+
print(f"Injected GitHub widget into {widget_count} HTML files")
782+
else:
783+
print("No GitHub widget placeholders found")
784+
785+
786+
inject_github_widget()

great_docs/assets/styles.css

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,3 +341,178 @@ a.sidebar-item-text.sidebar-link.text-start > span {
341341
padding-right: 12px;
342342
}
343343
}
344+
345+
/* ==========================================================================
346+
GitHub Widget Styles
347+
========================================================================== */
348+
349+
#github-widget {
350+
position: relative;
351+
display: inline-flex;
352+
align-items: center;
353+
margin-left: 8px;
354+
}
355+
356+
.gh-widget-trigger {
357+
display: flex;
358+
align-items: center;
359+
gap: 6px;
360+
padding: 6px 10px;
361+
background: rgba(255, 255, 255, 0.1);
362+
border: 1px solid rgba(255, 255, 255, 0.2);
363+
border-radius: 6px;
364+
color: white;
365+
cursor: pointer;
366+
transition: all 0.2s ease;
367+
font-size: 13px;
368+
}
369+
370+
.gh-widget-trigger:hover {
371+
background: rgba(255, 255, 255, 0.18);
372+
border-color: rgba(255, 255, 255, 0.3);
373+
}
374+
375+
.gh-widget-open .gh-widget-trigger {
376+
background: rgba(255, 255, 255, 0.2);
377+
border-color: rgba(255, 255, 255, 0.35);
378+
}
379+
380+
.gh-icon {
381+
flex-shrink: 0;
382+
}
383+
384+
.gh-stats {
385+
display: flex;
386+
align-items: center;
387+
gap: 10px;
388+
margin-left: 4px;
389+
}
390+
391+
.gh-stat {
392+
display: flex;
393+
align-items: center;
394+
gap: 3px;
395+
font-weight: 500;
396+
}
397+
398+
.gh-stat svg {
399+
opacity: 0.85;
400+
}
401+
402+
.gh-count {
403+
min-width: 16px;
404+
text-align: center;
405+
}
406+
407+
.gh-dropdown-arrow {
408+
margin-left: 2px;
409+
opacity: 0.7;
410+
transition: transform 0.2s ease;
411+
}
412+
413+
.gh-widget-open .gh-dropdown-arrow {
414+
transform: rotate(180deg);
415+
}
416+
417+
.gh-dropdown {
418+
position: absolute;
419+
top: calc(100% + 6px);
420+
right: 0;
421+
min-width: 180px;
422+
background: #ffffff;
423+
border: 1px solid #d0d7de;
424+
border-radius: 8px;
425+
box-shadow: 0 8px 24px rgba(31, 35, 40, 0.12);
426+
opacity: 0;
427+
visibility: hidden;
428+
transform: translateY(-8px);
429+
transition: all 0.2s ease;
430+
z-index: 1000;
431+
overflow: hidden;
432+
}
433+
434+
.gh-widget-open .gh-dropdown {
435+
opacity: 1;
436+
visibility: visible;
437+
transform: translateY(0);
438+
}
439+
440+
.gh-dropdown-item {
441+
display: flex;
442+
align-items: center;
443+
gap: 10px;
444+
padding: 10px 14px;
445+
color: #24292f !important;
446+
text-decoration: none !important;
447+
font-size: 14px;
448+
font-weight: 500;
449+
transition: background 0.15s ease;
450+
}
451+
452+
.gh-dropdown-item:hover {
453+
background: #f6f8fa;
454+
text-decoration: none !important;
455+
}
456+
457+
.gh-dropdown-item svg {
458+
color: #57606a;
459+
flex-shrink: 0;
460+
}
461+
462+
.gh-dropdown-divider {
463+
height: 1px;
464+
margin: 4px 0;
465+
background: #d8dee4;
466+
}
467+
468+
.gh-badge {
469+
display: inline-flex;
470+
align-items: center;
471+
justify-content: center;
472+
min-width: 20px;
473+
height: 20px;
474+
padding: 0 6px;
475+
margin-left: auto;
476+
background: #ddf4ff;
477+
color: #0969da;
478+
border-radius: 10px;
479+
font-size: 12px;
480+
font-weight: 600;
481+
}
482+
483+
/* Mobile responsive adjustments */
484+
@media (max-width: 768px) {
485+
.gh-stats {
486+
display: none;
487+
}
488+
489+
.gh-widget-trigger {
490+
padding: 6px 8px;
491+
}
492+
493+
.gh-dropdown {
494+
right: auto;
495+
left: 0;
496+
min-width: 160px;
497+
}
498+
}
499+
500+
/* Ensure navbar doesn't clip the dropdown */
501+
#quarto-header,
502+
#quarto-header nav,
503+
#quarto-header .navbar,
504+
#quarto-header .container-fluid,
505+
#navbarCollapse,
506+
.navbar-nav,
507+
.navbar-nav.ms-auto,
508+
.navbar-nav.ms-auto > li,
509+
.navbar-nav.ms-auto > li > .nav-link {
510+
overflow: visible !important;
511+
}
512+
513+
/* Print styles - hide widget */
514+
@media print {
515+
#github-widget {
516+
display: none;
517+
}
518+
}

0 commit comments

Comments
 (0)