yjernite's picture
yjernite HF Staff
Update index.html
96ab310 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>EU AI Act Open Source Guide</title>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<style>
* {
box-sizing: border-box;
}
body {
font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
line-height: 1.75;
margin: 0;
padding: 0;
color: #374151;
background-color: #ffffff;
font-size: 16px;
}
/* Layout container */
.layout {
display: flex;
min-height: 100vh;
}
/* TOC Sidebar */
.toc-sidebar {
position: fixed;
left: 0;
top: 0;
width: 280px;
height: 100vh;
background-color: #f9fafb;
border-right: 1px solid #e5e7eb;
padding: 24px 16px;
overflow-y: auto;
z-index: 100;
transition: transform 0.3s ease;
}
.toc-sidebar.collapsed {
transform: translateX(-240px);
}
.toc-toggle {
position: absolute;
top: 20px;
right: -5px;
width: 40px;
height: 40px;
background: #3b82f6;
color: white;
border: none;
border-radius: 0 6px 6px 0;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
z-index: 101;
transition: all 0.3s ease;
}
.toc-sidebar h3 {
margin: 0 0 16px 0;
font-size: 1.125rem;
font-weight: 600;
color: #111827;
border-bottom: 1px solid #e5e7eb;
padding-bottom: 8px;
}
.toc-sidebar ul {
list-style: none;
margin: 0;
padding: 0;
}
.toc-sidebar li {
margin: 0;
padding: 0;
}
.toc-sidebar a {
display: block;
padding: 6px 12px;
color: #6b7280;
text-decoration: none;
font-size: 0.875rem;
border-radius: 4px;
transition: all 0.2s;
}
.toc-sidebar a:hover {
background-color: #e5e7eb;
color: #374151;
}
.toc-sidebar a.active {
background-color: #dbeafe;
color: #1d4ed8;
font-weight: 500;
}
/* Nested TOC items */
.toc-sidebar .toc-level-2 {
padding-left: 16px;
}
.toc-sidebar .toc-level-3 {
padding-left: 32px;
}
/* Main content area - always centered */
.main-content {
max-width: 1000px;
margin: 0 auto;
padding: 32px 48px;
width: 100%;
}
/* Content wrapper */
.content-wrapper {
flex: 1;
display: flex;
justify-content: center;
min-height: 100vh;
}
/* Typography - Hugging Face style */
h1 {
font-size: 2.25rem;
font-weight: 700;
line-height: 1.2;
margin: 0 0 2rem 0;
color: #111827;
}
h2 {
font-size: 1.875rem;
font-weight: 600;
line-height: 1.3;
margin: 3rem 0 1.5rem 0;
color: #111827;
scroll-margin-top: 20px;
}
h3 {
font-size: 1.5rem;
font-weight: 600;
line-height: 1.4;
margin: 2.5rem 0 1rem 0;
color: #111827;
scroll-margin-top: 20px;
}
h4 {
font-size: 1.25rem;
font-weight: 600;
line-height: 1.5;
margin: 2rem 0 1rem 0;
color: #111827;
scroll-margin-top: 20px;
}
h5, h6 {
font-size: 1.125rem;
font-weight: 600;
line-height: 1.5;
margin: 1.5rem 0 1rem 0;
color: #111827;
scroll-margin-top: 20px;
}
p {
margin: 0 0 1.5rem 0;
color: #374151;
}
strong {
font-weight: 600;
color: #111827;
}
em {
font-style: italic;
}
a {
color: #3b82f6;
text-decoration: none;
font-weight: 500;
}
a:hover {
text-decoration: underline;
}
code {
background-color: #f3f4f6;
color: #374151;
padding: 0.125rem 0.375rem;
border-radius: 0.375rem;
font-family: "SF Mono", Monaco, "Cascadia Code", "Roboto Mono", Consolas, "Courier New", monospace;
font-size: 0.875em;
}
pre {
background-color: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
padding: 1.5rem;
overflow-x: auto;
margin: 1.5rem 0;
}
pre code {
background: none;
padding: 0;
border-radius: 0;
font-size: 0.875rem;
}
ul, ol {
margin: 0 0 1.5rem 0;
padding-left: 1.5rem;
}
li {
margin: 0.5rem 0;
}
blockquote {
border-left: 4px solid #e5e7eb;
margin: 1.5rem 0;
padding-left: 1.5rem;
color: #6b7280;
font-style: italic;
word-wrap: break-word;
overflow-wrap: break-word;
white-space: normal;
max-width: 100%;
}
table {
border-collapse: collapse;
width: 100%;
margin: 1.5rem 0;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
overflow: hidden;
}
th, td {
border-bottom: 1px solid #e5e7eb;
padding: 0.75rem 1rem;
text-align: left;
vertical-align: top;
}
th {
background-color: #f9fafb;
font-weight: 600;
color: #374151;
}
tr:last-child td {
border-bottom: none;
}
hr {
border: none;
border-top: 1px solid #e5e7eb;
margin: 3rem 0;
}
img, iframe {
max-width: 100%;
height: auto;
border-radius: 0.5rem;
}
iframe {
border: 1px solid #e5e7eb;
}
input[type="checkbox"] {
margin-right: 0.5rem;
transform: scale(1.1);
}
/* Custom styled boxes */
div[style*="border: 2px solid black"] {
border: 1px solid #e5e7eb !important;
border-radius: 0.75rem !important;
background-color: #f9fafb !important;
padding: 1.5rem !important;
margin: 2rem 0 !important;
}
#loading {
text-align: center;
padding: 3rem;
color: #6b7280;
font-size: 1.125rem;
}
/* Mobile responsiveness */
@media (max-width: 1024px) {
.toc-sidebar {
transform: translateX(-100%);
}
.toc-sidebar.open {
transform: translateX(0);
}
.main-content {
padding: 16px;
}
.mobile-toc-toggle {
display: block;
position: fixed;
top: 16px;
left: 16px;
z-index: 102;
background: #3b82f6;
color: white;
border: none;
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
}
}
.mobile-toc-toggle {
display: none;
}
</style>
</head>
<body>
<div class="layout">
<!-- TOC Sidebar -->
<aside class="toc-sidebar" id="toc-sidebar">
<button class="toc-toggle" onclick="toggleTOC()" id="toc-toggle"></button>
<h3>Table of Contents</h3>
<div id="toc-content">
<!-- TOC will be generated here -->
</div>
</aside>
<!-- Mobile TOC Toggle -->
<button class="mobile-toc-toggle" onclick="toggleMobileTOC()">☰ TOC</button>
<!-- Main Content Wrapper -->
<div class="content-wrapper">
<main class="main-content">
<div id="loading">Loading...</div>
<div id="content"></div>
</main>
</div>
</div>
<script>
function generateTOC(content) {
const headings = content.querySelectorAll('h1, h2, h3, h4, h5, h6');
const toc = document.getElementById('toc-content');
let tocHTML = '<ul>';
headings.forEach((heading, index) => {
const level = parseInt(heading.tagName.charAt(1));
const text = heading.textContent;
const id = text.toLowerCase()
.replace(/[^\w\s-]/g, '')
.replace(/\s+/g, '-')
.replace(/-+/g, '-')
.replace(/^-|-$/g, '');
heading.id = id;
const tocClass = `toc-level-${level}`;
tocHTML += `<li><a href="#${id}" class="${tocClass}" onclick="setActiveLink(this)">${text}</a></li>`;
});
tocHTML += '</ul>';
toc.innerHTML = tocHTML;
}
function setActiveLink(clickedLink) {
document.querySelectorAll('.toc-sidebar a').forEach(link => {
link.classList.remove('active');
});
clickedLink.classList.add('active');
}
function toggleTOC() {
const sidebar = document.getElementById('toc-sidebar');
const btn = document.getElementById('toc-toggle');
sidebar.classList.toggle('collapsed');
btn.innerHTML = sidebar.classList.contains('collapsed') ? '▶' : '◀';
}
function toggleMobileTOC() {
document.getElementById('toc-sidebar').classList.toggle('open');
}
function highlightCurrentSection() {
const headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6');
const tocLinks = document.querySelectorAll('.toc-sidebar a');
let current = '';
headings.forEach(heading => {
const rect = heading.getBoundingClientRect();
if (rect.top <= 100) {
current = heading.id;
}
});
tocLinks.forEach(link => {
link.classList.remove('active');
if (link.getAttribute('href') === `#${current}`) {
link.classList.add('active');
}
});
}
async function loadMarkdown() {
try {
const response = await fetch('eu-act-os-guideai.md');
const markdown = await response.text();
marked.setOptions({
breaks: true,
gfm: true
});
const html = marked.parse(markdown);
const contentDiv = document.getElementById('content');
contentDiv.innerHTML = html;
generateTOC(contentDiv);
document.getElementById('loading').style.display = 'none';
window.addEventListener('scroll', highlightCurrentSection);
} catch (error) {
document.getElementById('loading').innerHTML = 'Error loading content: ' + error.message;
}
}
loadMarkdown();
</script>
</body>
</html>