Update app.py
Browse files
app.py
CHANGED
|
@@ -135,42 +135,15 @@ def markdown_to_html(text: str) -> str:
|
|
| 135 |
)
|
| 136 |
|
| 137 |
def render_article(article_path: str, component_inserts: dict[str, callable]):
|
| 138 |
-
""
|
| 139 |
-
|
| 140 |
-
raw_content = Path(article_path).read_text(encoding="utf-8")
|
| 141 |
-
else:
|
| 142 |
-
raw_content = f"**Missing article**: `{article_path}` not found."
|
| 143 |
-
|
| 144 |
-
# Split on {{TOKEN}} markers (e.g., {{ALLOC_PLOT}})
|
| 145 |
-
content_parts = re.split(r"\{\{([A-Z_]+)\}\}", raw_content)
|
| 146 |
-
|
| 147 |
with gr.Column():
|
| 148 |
-
for
|
| 149 |
-
if
|
| 150 |
-
|
| 151 |
-
html_content = markdown_to_html(part)
|
| 152 |
-
# Add syntax highlighting script
|
| 153 |
-
highlighted_html = f'''
|
| 154 |
-
<div class="article">{html_content}</div>
|
| 155 |
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
| 156 |
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/python.min.js"></script>
|
| 157 |
-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css">
|
| 158 |
-
<script>
|
| 159 |
-
document.addEventListener('DOMContentLoaded', function() {{
|
| 160 |
-
document.querySelectorAll('pre code').forEach((block) => {{
|
| 161 |
-
hljs.highlightElement(block);
|
| 162 |
-
}});
|
| 163 |
-
}});
|
| 164 |
-
</script>
|
| 165 |
-
'''
|
| 166 |
-
gr.HTML(highlighted_html)
|
| 167 |
else:
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
if component_builder is None:
|
| 171 |
-
gr.HTML(f"<p><em>Unknown component: {part}</em></p>")
|
| 172 |
-
else:
|
| 173 |
-
component_builder()
|
| 174 |
|
| 175 |
# ---------------------------
|
| 176 |
# Terminal (safe, simplified)
|
|
@@ -425,57 +398,19 @@ def build_image(filename):
|
|
| 425 |
return _build
|
| 426 |
|
| 427 |
def build_d3_graph():
|
| 428 |
-
"""Build interactive D3 dependency graph."""
|
| 429 |
with gr.Group():
|
| 430 |
gr.Markdown("### 🔗 Interactive Model Dependency Graph")
|
| 431 |
-
gr.Markdown("Explore how transformers models inherit from each other using the modular system. Click and drag nodes to interact!")
|
| 432 |
-
|
| 433 |
-
# Check if the HTML file exists
|
| 434 |
html_file = Path("static/d3_dependency_graph.html")
|
| 435 |
if html_file.exists():
|
| 436 |
-
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
else:
|
| 444 |
-
body_content = html_content
|
| 445 |
-
|
| 446 |
-
# Get the script content
|
| 447 |
-
script_match = re.search(r'<script.*?>(.*?)</script>', html_content, re.DOTALL)
|
| 448 |
-
script_content = script_match.group(1) if script_match else ""
|
| 449 |
-
|
| 450 |
-
# Create a clean embedded version
|
| 451 |
-
wrapped_html = f'''
|
| 452 |
-
<div id="d3-graph-container" style="width: 100%; height: 600px; border: 1px solid #e2e8f0; border-radius: 8px; overflow: hidden; background: white; position: relative;">
|
| 453 |
-
{body_content}
|
| 454 |
-
</div>
|
| 455 |
-
<script src="https://d3js.org/d3.v7.min.js"></script>
|
| 456 |
-
<script>
|
| 457 |
-
{script_content}
|
| 458 |
-
</script>
|
| 459 |
-
<style>
|
| 460 |
-
#d3-graph-container svg {{
|
| 461 |
-
width: 100% !important;
|
| 462 |
-
height: 100% !important;
|
| 463 |
-
}}
|
| 464 |
-
#d3-graph-container #legend {{
|
| 465 |
-
position: absolute !important;
|
| 466 |
-
top: 10px !important;
|
| 467 |
-
left: 10px !important;
|
| 468 |
-
z-index: 1000 !important;
|
| 469 |
-
background: rgba(255,255,255,0.9) !important;
|
| 470 |
-
padding: 12px !important;
|
| 471 |
-
border-radius: 6px !important;
|
| 472 |
-
font-size: 14px !important;
|
| 473 |
-
}}
|
| 474 |
-
</style>
|
| 475 |
-
'''
|
| 476 |
-
gr.HTML(wrapped_html)
|
| 477 |
else:
|
| 478 |
-
gr.Markdown("⚠️ **D3 dependency graph not found.**
|
| 479 |
|
| 480 |
# ---------------------------
|
| 481 |
# Inserts registry
|
|
@@ -498,6 +433,23 @@ INSERTS = {
|
|
| 498 |
# ---------------------------
|
| 499 |
# Layout / CSS / App
|
| 500 |
# ---------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 501 |
|
| 502 |
CSS = """
|
| 503 |
/* Force light palette + high contrast */
|
|
@@ -548,91 +500,35 @@ html, body, .gradio-container { background: #fff !important; }
|
|
| 548 |
.article a { color: var(--link-text-color) !important; text-decoration: underline; }
|
| 549 |
.article a:hover { text-decoration: none; }
|
| 550 |
|
| 551 |
-
/* Code blocks
|
| 552 |
.article pre {
|
| 553 |
-
background: #f8fafc !important;
|
| 554 |
-
border: 1px solid #e2e8f0 !important;
|
| 555 |
border-radius: 8px !important;
|
| 556 |
-
padding: 1.
|
| 557 |
-
margin:
|
| 558 |
overflow-x: auto !important;
|
| 559 |
-
font-family:
|
| 560 |
-
font-size:
|
| 561 |
-
line-height: 1.
|
| 562 |
-
color: #1e293b !important;
|
| 563 |
-
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06) !important;
|
| 564 |
-
}
|
| 565 |
-
|
| 566 |
-
/* Code block syntax highlighting */
|
| 567 |
-
.article pre code {
|
| 568 |
-
background: transparent !important;
|
| 569 |
-
color: #1e293b !important;
|
| 570 |
-
padding: 0 !important;
|
| 571 |
-
border-radius: 0 !important;
|
| 572 |
-
font-weight: 400 !important;
|
| 573 |
-
font-size: inherit !important;
|
| 574 |
-
line-height: inherit !important;
|
| 575 |
-
}
|
| 576 |
-
|
| 577 |
-
/* Inline code */
|
| 578 |
-
.article code {
|
| 579 |
-
background: #f1f5f9 !important;
|
| 580 |
-
color: #dc2626 !important;
|
| 581 |
-
padding: 0.125rem 0.375rem !important;
|
| 582 |
-
border-radius: 4px !important;
|
| 583 |
-
font-weight: 500 !important;
|
| 584 |
-
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace !important;
|
| 585 |
-
font-size: 0.875rem !important;
|
| 586 |
-
}
|
| 587 |
-
|
| 588 |
-
/* Python syntax highlighting with Highlight.js integration */
|
| 589 |
-
.article pre code {
|
| 590 |
-
background: transparent !important;
|
| 591 |
-
color: #1e293b !important;
|
| 592 |
-
padding: 0 !important;
|
| 593 |
-
border-radius: 0 !important;
|
| 594 |
-
font-weight: 400 !important;
|
| 595 |
-
font-size: inherit !important;
|
| 596 |
-
line-height: inherit !important;
|
| 597 |
-
}
|
| 598 |
-
|
| 599 |
-
/* Highlight.js Python syntax highlighting */
|
| 600 |
-
.article pre code .hljs-keyword,
|
| 601 |
-
.article pre code .hljs-built_in {
|
| 602 |
-
color: #7c3aed !important; /* Purple for keywords like def, class, import */
|
| 603 |
-
font-weight: 600 !important;
|
| 604 |
-
}
|
| 605 |
-
|
| 606 |
-
.article pre code .hljs-string {
|
| 607 |
-
color: #059669 !important; /* Green for strings */
|
| 608 |
-
}
|
| 609 |
-
|
| 610 |
-
.article pre code .hljs-comment {
|
| 611 |
-
color: #6b7280 !important; /* Gray for comments */
|
| 612 |
-
font-style: italic !important;
|
| 613 |
-
}
|
| 614 |
-
|
| 615 |
-
.article pre code .hljs-number {
|
| 616 |
-
color: #dc2626 !important; /* Red for numbers */
|
| 617 |
}
|
|
|
|
| 618 |
|
| 619 |
-
|
| 620 |
-
.
|
| 621 |
-
color: #2563eb !important; /* Blue for class/function names */
|
| 622 |
-
font-weight: 600 !important;
|
| 623 |
-
}
|
| 624 |
|
| 625 |
-
|
| 626 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 627 |
}
|
|
|
|
|
|
|
| 628 |
|
| 629 |
-
.article pre code .hljs-attr {
|
| 630 |
-
color: #0d9488 !important; /* Teal for attributes */
|
| 631 |
-
}
|
| 632 |
|
| 633 |
-
.article pre code .hljs-type {
|
| 634 |
-
color: #7c3aed !important; /* Purple for types */
|
| 635 |
-
}
|
| 636 |
|
| 637 |
/* Blockquotes, images, rules */
|
| 638 |
.article blockquote { border-left: 4px solid var(--link-text-color); padding-left: 1rem; margin: 1.25rem 0; color: #334155 !important; font-style: italic; }
|
|
@@ -790,7 +686,8 @@ hr { border: 0; border-top: 1px solid var(--border-color); margin: 2rem 0; }
|
|
| 790 |
|
| 791 |
"""
|
| 792 |
|
| 793 |
-
with gr.Blocks(css=CSS, fill_height=True, title="Interactive Blog — Transformers Feature Showcase") as demo
|
|
|
|
| 794 |
gr.HTML("<h1>Transformers Feature Showcase</h1><p>Interactive, scrollable demo.</p>")
|
| 795 |
with gr.Row(elem_id="layout"):
|
| 796 |
with gr.Column(scale=0):
|
|
|
|
| 135 |
)
|
| 136 |
|
| 137 |
def render_article(article_path: str, component_inserts: dict[str, callable]):
|
| 138 |
+
raw = Path(article_path).read_text(encoding="utf-8") if Path(article_path).exists() else f"**Missing article**: `{article_path}`."
|
| 139 |
+
parts = re.split(r"\{\{([A-Z_]+)\}\}", raw)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 140 |
with gr.Column():
|
| 141 |
+
for i, part in enumerate(parts):
|
| 142 |
+
if i % 2 == 0:
|
| 143 |
+
gr.HTML(f'<div class="article">{markdown_to_html(part)}</div>')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
else:
|
| 145 |
+
(component_inserts.get(part) or (lambda: gr.HTML(f"<p><em>Unknown component: {part}</em></p>")))()
|
| 146 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
|
| 148 |
# ---------------------------
|
| 149 |
# Terminal (safe, simplified)
|
|
|
|
| 398 |
return _build
|
| 399 |
|
| 400 |
def build_d3_graph():
|
|
|
|
| 401 |
with gr.Group():
|
| 402 |
gr.Markdown("### 🔗 Interactive Model Dependency Graph")
|
|
|
|
|
|
|
|
|
|
| 403 |
html_file = Path("static/d3_dependency_graph.html")
|
| 404 |
if html_file.exists():
|
| 405 |
+
gr.HTML(
|
| 406 |
+
f"""
|
| 407 |
+
<iframe src="file=static/d3_dependency_graph.html"
|
| 408 |
+
style="width:100%;height:640px;border:1px solid #e2e8f0;border-radius:8px"
|
| 409 |
+
loading="lazy"></iframe>
|
| 410 |
+
"""
|
| 411 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 412 |
else:
|
| 413 |
+
gr.Markdown("⚠️ **D3 dependency graph not found.** Put it at `static/d3_dependency_graph.html`.")
|
| 414 |
|
| 415 |
# ---------------------------
|
| 416 |
# Inserts registry
|
|
|
|
| 433 |
# ---------------------------
|
| 434 |
# Layout / CSS / App
|
| 435 |
# ---------------------------
|
| 436 |
+
HLJS = """
|
| 437 |
+
<link rel="stylesheet"
|
| 438 |
+
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css">
|
| 439 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
| 440 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/python.min.js"></script>
|
| 441 |
+
<script>
|
| 442 |
+
(function(){
|
| 443 |
+
function run() {
|
| 444 |
+
document.querySelectorAll('pre code').forEach((el) => { hljs.highlightElement(el); });
|
| 445 |
+
}
|
| 446 |
+
run();
|
| 447 |
+
const mo = new MutationObserver(run);
|
| 448 |
+
mo.observe(document.body, {subtree: true, childList: true});
|
| 449 |
+
})();
|
| 450 |
+
</script>
|
| 451 |
+
"""
|
| 452 |
+
|
| 453 |
|
| 454 |
CSS = """
|
| 455 |
/* Force light palette + high contrast */
|
|
|
|
| 500 |
.article a { color: var(--link-text-color) !important; text-decoration: underline; }
|
| 501 |
.article a:hover { text-decoration: none; }
|
| 502 |
|
| 503 |
+
/* Code blocks (keep container styling, let hljs theme handle token colors) */
|
| 504 |
.article pre {
|
| 505 |
+
background: #f8fafc !important;
|
| 506 |
+
border: 1px solid #e2e8f0 !important;
|
| 507 |
border-radius: 8px !important;
|
| 508 |
+
padding: 1.25rem !important;
|
| 509 |
+
margin: 1.5rem 0 !important;
|
| 510 |
overflow-x: auto !important;
|
| 511 |
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace !important;
|
| 512 |
+
font-size: .92rem !important;
|
| 513 |
+
line-height: 1.6 !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 514 |
}
|
| 515 |
+
.article pre code { background: transparent !important; padding: 0 !important; }
|
| 516 |
|
| 517 |
+
/* Let the theme show through */
|
| 518 |
+
.hljs { background: transparent !important; }
|
|
|
|
|
|
|
|
|
|
| 519 |
|
| 520 |
+
/* Tenets highlight: any list item that contains an anchor id gets a card look */
|
| 521 |
+
.article ol > li:has(> a[id]) {
|
| 522 |
+
border-left: 4px solid #1d4ed8;
|
| 523 |
+
background: #f8fafc;
|
| 524 |
+
padding: .75rem 1rem;
|
| 525 |
+
margin: .5rem 0;
|
| 526 |
+
border-radius: 8px;
|
| 527 |
}
|
| 528 |
+
.article ol > li:has(> a[id])::marker { color: #1d4ed8; font-weight: 700; }
|
| 529 |
+
.article ol > li:has(> a[id]) code { background: #e0e7ff !important; }
|
| 530 |
|
|
|
|
|
|
|
|
|
|
| 531 |
|
|
|
|
|
|
|
|
|
|
| 532 |
|
| 533 |
/* Blockquotes, images, rules */
|
| 534 |
.article blockquote { border-left: 4px solid var(--link-text-color); padding-left: 1rem; margin: 1.25rem 0; color: #334155 !important; font-style: italic; }
|
|
|
|
| 686 |
|
| 687 |
"""
|
| 688 |
|
| 689 |
+
with gr.Blocks(css=CSS, fill_height=True, title="Interactive Blog — Transformers Feature Showcase") as demo
|
| 690 |
+
gr.HTML(HLJS)
|
| 691 |
gr.HTML("<h1>Transformers Feature Showcase</h1><p>Interactive, scrollable demo.</p>")
|
| 692 |
with gr.Row(elem_id="layout"):
|
| 693 |
with gr.Column(scale=0):
|