Spaces:
Running
Running
thibaud frere
commited on
Commit
·
3f64d97
1
Parent(s):
d8d4124
feat(astro): port base Distill-like template into index.astro with TOC and Plotly
Browse files- app/src/pages/index.astro +143 -7
app/src/pages/index.astro
CHANGED
|
@@ -1,21 +1,157 @@
|
|
| 1 |
---
|
| 2 |
import { Image } from 'astro:assets';
|
| 3 |
import banner from "../assets/images/banner.png";
|
| 4 |
-
const title = '
|
| 5 |
---
|
| 6 |
<html lang="en">
|
| 7 |
<head>
|
| 8 |
<meta charset="utf-8" />
|
| 9 |
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
|
|
| 10 |
<title>{title}</title>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
</head>
|
| 12 |
<body>
|
| 13 |
-
<main
|
| 14 |
-
<
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
</main>
|
| 20 |
</body>
|
| 21 |
</html>
|
|
|
|
| 1 |
---
|
| 2 |
import { Image } from 'astro:assets';
|
| 3 |
import banner from "../assets/images/banner.png";
|
| 4 |
+
const title = 'The Distill Blog Template (Astro)';
|
| 5 |
---
|
| 6 |
<html lang="en">
|
| 7 |
<head>
|
| 8 |
<meta charset="utf-8" />
|
| 9 |
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
| 10 |
+
<base target="_blank" />
|
| 11 |
<title>{title}</title>
|
| 12 |
+
<script src="https://cdn.plot.ly/plotly-3.0.0.min.js" charset="utf-8"></script>
|
| 13 |
+
<style>
|
| 14 |
+
:root { --page-width: 980px; }
|
| 15 |
+
body { margin:0; font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji; }
|
| 16 |
+
main { max-width: var(--page-width); margin: 24px auto; padding: 16px; }
|
| 17 |
+
.l-page { max-width: var(--page-width); margin: 0 auto; }
|
| 18 |
+
.l-screen { width: 100%; }
|
| 19 |
+
figure { margin: 16px 0; }
|
| 20 |
+
.figcaption, figcaption { color: rgba(0,0,0,.6); font-size: 12px; }
|
| 21 |
+
.plot-card { background: #fff; border: 1px solid rgba(0,0,0,.1); border-radius: 8px; padding: 12px; }
|
| 22 |
+
d-contents nav { border-left: 1px solid rgba(0,0,0,.1); padding-left: 16px; margin: 16px 0; }
|
| 23 |
+
.toc-header { display:flex; align-items:center; gap: 8px; cursor: pointer; user-select:none; }
|
| 24 |
+
.toc-title { font-weight: 600; }
|
| 25 |
+
.toggle-icon { transition: transform .2s ease; display:inline-block; }
|
| 26 |
+
.toggle-icon.collapsed { transform: rotate(-90deg); }
|
| 27 |
+
.toc-content.collapsed { display:none; }
|
| 28 |
+
d-article pre, d-code[block] { overflow:auto; background:#f6f8fa; border:1px solid #d0d7de; border-radius:6px; padding:12px; }
|
| 29 |
+
d-article table { border-collapse: collapse; width: 100%; }
|
| 30 |
+
d-article th, d-article td { border-bottom: 1px solid rgba(0,0,0,.1); padding: 6px 8px; text-align: left; }
|
| 31 |
+
aside { color: rgba(0,0,0,.6); font-size: 14px; }
|
| 32 |
+
</style>
|
| 33 |
</head>
|
| 34 |
<body>
|
| 35 |
+
<main>
|
| 36 |
+
<d-front-matter>
|
| 37 |
+
<script id='distill-front-matter' type="application/json">{ "title": "The Distill Blog Template", "description": "Building beautiful blog posts.", "published": "Feb 19, 2025", "affiliation": {"name": "YourCompany"}, "authors": [ { "author":"The Author (you!)", "authorURL":"https://huggingface.co/" } ] }</script>
|
| 38 |
+
</d-front-matter>
|
| 39 |
+
|
| 40 |
+
<d-title>
|
| 41 |
+
<h1 class="l-page" style="text-align: center;">The Distill Template:<br/>Craft Beautiful Blogs</h1>
|
| 42 |
+
<div id="title-plot" class="main-plot-container l-screen" style="overflow-x: hidden; width: 100%; text-align: center;">
|
| 43 |
+
<div style="display: flex; justify-content: center; position: relative;">
|
| 44 |
+
<figure class="l-page" style="margin:0;">
|
| 45 |
+
<Image src={banner} alt="Banner" widths={[480,768,1080,1440]} formats={["avif","webp","png"]} sizes="(max-width: 768px) 100vw, var(--page-width)" loading="eager" />
|
| 46 |
+
</figure>
|
| 47 |
+
</div>
|
| 48 |
+
<p style="text-align: center; font-style: italic; margin-top: 10px; max-width: 900px; margin-left: auto; margin-right: auto;">It's nice to have a cute interactive banner!</p>
|
| 49 |
+
</div>
|
| 50 |
+
</d-title>
|
| 51 |
+
|
| 52 |
+
<d-byline></d-byline>
|
| 53 |
+
|
| 54 |
+
<d-article>
|
| 55 |
+
<d-contents></d-contents>
|
| 56 |
+
|
| 57 |
+
<p>Welcome to the Distill Blog Template! This framework is based on the <a href="https://distill.pub/">distill.pub</a> design and has been adapted to make it easy for you to create beautiful, interactive technical blogs.</p>
|
| 58 |
+
<aside>Reading time: 10-15 minutes.</aside>
|
| 59 |
+
<p>This template includes support for mathematics, interactive visualizations, citations, footnotes, and more.</p>
|
| 60 |
+
|
| 61 |
+
<h2>Getting Started with the Template</h2>
|
| 62 |
+
<h3>Installation and Setup</h3>
|
| 63 |
+
<d-code block language="bash">npm install\nnpm run dev</d-code>
|
| 64 |
+
|
| 65 |
+
<h3>Mathematical Equations</h3>
|
| 66 |
+
<p>You can include inline math using <code>x^2 + y^2 = z^2</code>.</p>
|
| 67 |
+
|
| 68 |
+
<h3>Figures and Images</h3>
|
| 69 |
+
<figure>
|
| 70 |
+
<Image src={banner} alt="Example figure" widths={[480,768,1080]} formats={["avif","webp","png"]} sizes="(max-width: 768px) 100vw, var(--page-width)" />
|
| 71 |
+
<figcaption>Caption for your figure</figcaption>
|
| 72 |
+
</figure>
|
| 73 |
+
|
| 74 |
+
<h3>Tables</h3>
|
| 75 |
+
<table>
|
| 76 |
+
<thead>
|
| 77 |
+
<tr><th><strong>Model</strong></th><th><strong>Accuracy</strong></th><th><strong>Speed</strong></th></tr>
|
| 78 |
+
</thead>
|
| 79 |
+
<tbody>
|
| 80 |
+
<tr><td>Model A</td><td>95%</td><td>Fast</td></tr>
|
| 81 |
+
<tr><td>Model B</td><td>98%</td><td>Medium</td></tr>
|
| 82 |
+
<tr><td>Model C</td><td>99%</td><td>Slow</td></tr>
|
| 83 |
+
</tbody>
|
| 84 |
+
</table>
|
| 85 |
+
|
| 86 |
+
<h2>Interactive Components</h2>
|
| 87 |
+
<div class="plot-card">
|
| 88 |
+
<div id="fragment-line"></div>
|
| 89 |
+
</div>
|
| 90 |
+
<script>
|
| 91 |
+
// Example: simple Plotly line chart using the CDN
|
| 92 |
+
const container = document.getElementById('fragment-line');
|
| 93 |
+
if (container && window.Plotly) {
|
| 94 |
+
window.Plotly.newPlot(container, [{x:[1,2,3,4], y:[1,3,2,4], type:'scatter'}], {margin:{t:16,r:16,b:32,l:32}});
|
| 95 |
+
}
|
| 96 |
+
</script>
|
| 97 |
+
|
| 98 |
+
</d-article>
|
| 99 |
+
|
| 100 |
+
<d-appendix>
|
| 101 |
+
<h3 id="citation">Citation</h3>
|
| 102 |
+
<pre class="citation short">"The Distill Blog Template", 2025.</pre>
|
| 103 |
+
</d-appendix>
|
| 104 |
+
|
| 105 |
+
<script>
|
| 106 |
+
function toggleTOC() {
|
| 107 |
+
const content = document.querySelector('.toc-content');
|
| 108 |
+
const icon = document.querySelector('.toggle-icon');
|
| 109 |
+
if (content) content.classList.toggle('collapsed');
|
| 110 |
+
if (icon) icon.classList.toggle('collapsed');
|
| 111 |
+
}
|
| 112 |
+
</script>
|
| 113 |
+
|
| 114 |
+
<script>
|
| 115 |
+
const article = document.querySelector('d-article');
|
| 116 |
+
const toc = document.querySelector('d-contents');
|
| 117 |
+
if (toc && article) {
|
| 118 |
+
const headings = article.querySelectorAll('h2, h3, h4');
|
| 119 |
+
let ToC = `<nav role="navigation" class="l-text figcaption"><div class="toc-header" onclick="toggleTOC()"><span class="toc-title">Table of Contents</span><span class="toggle-icon">▼</span></div><div class="toc-content">`;
|
| 120 |
+
let prevLevel = 0;
|
| 121 |
+
for (const el of headings) {
|
| 122 |
+
const isInTitle = el.parentElement.tagName == 'D-TITLE';
|
| 123 |
+
const isException = el.getAttribute('no-toc');
|
| 124 |
+
if (isInTitle || isException) continue;
|
| 125 |
+
el.setAttribute('id', el.textContent.toLowerCase().replaceAll(" ", "_"));
|
| 126 |
+
const link = '<a target="_self" href="#' + el.getAttribute('id') + '">' + el.textContent + '</a>';
|
| 127 |
+
const level = el.tagName === 'H2' ? 0 : (el.tagName === 'H3' ? 1 : 2);
|
| 128 |
+
while (prevLevel < level) { ToC += '<ul>'; prevLevel++; }
|
| 129 |
+
while (prevLevel > level) { ToC += '</ul>'; prevLevel--; }
|
| 130 |
+
if (level === 0) ToC += '<div>' + link + '</div>'; else ToC += '<li>' + link + '</li>';
|
| 131 |
+
}
|
| 132 |
+
while (prevLevel > 0) { ToC += '</ul>'; prevLevel--; }
|
| 133 |
+
ToC += '</div></nav>';
|
| 134 |
+
toc.innerHTML = ToC;
|
| 135 |
+
toc.setAttribute('prerendered', 'true');
|
| 136 |
+
const toc_links = document.querySelectorAll('d-contents > nav div a');
|
| 137 |
+
window.addEventListener('scroll', () => {
|
| 138 |
+
if (!headings || !toc_links) return;
|
| 139 |
+
for (let i = headings.length - 1; i >= 0; i--) {
|
| 140 |
+
const heading = headings[i];
|
| 141 |
+
if (heading.parentElement.tagName == 'D-TITLE' || heading.getAttribute('no-toc')) continue;
|
| 142 |
+
if (heading.getBoundingClientRect().top - 50 <= 0) {
|
| 143 |
+
const headingId = heading.getAttribute('id');
|
| 144 |
+
const activeLink = Array.from(toc_links).find(link => link.getAttribute('href') === '#' + headingId);
|
| 145 |
+
if (activeLink && !activeLink.classList.contains('active')) {
|
| 146 |
+
toc_links.forEach(link => link.classList.remove('active'));
|
| 147 |
+
activeLink.classList.add('active');
|
| 148 |
+
}
|
| 149 |
+
break;
|
| 150 |
+
}
|
| 151 |
+
}
|
| 152 |
+
});
|
| 153 |
+
}
|
| 154 |
+
</script>
|
| 155 |
</main>
|
| 156 |
</body>
|
| 157 |
</html>
|