{% extends "base.html" %} {% block title %}{{ post.title }} - {{ config.title }}{% endblock %} {% block content %} <div class="article-container"> <article class="article-content"> <header class="article-header"> <h1 class="article-title">{{ post.title }}</h1> <div class="article-meta"> <time class="article-date">{{ post.date }}</time> {% if post.language %} <span class="article-lang">{{ post.language }}</span> {% endif %} </div> <div class="article-actions"> {% if post.markdown_url %} <a href="{{ post.markdown_url }}" class="action-btn markdown-btn" title="View Markdown"> .md </a> {% endif %} {% if post.translation_url %} <a href="{{ post.translation_url }}" class="action-btn translation-btn" title="View Translation"> 🌐 {% if post.language == 'ja' %}English{% else %}日本語{% endif %} </a> {% endif %} </div> </header> <div class="article-body"> {{ post.content | safe }} </div> <!-- Simple Comment Section --> <section class="comment-section"> <div class="comment-container"> <h3>Comments</h3> <!-- Simple OAuth Button --> <div class="simple-oauth"> <p>📝 To comment, authenticate with Bluesky:</p> <button id="bluesky-auth" class="oauth-button"> 🦋 Login with Bluesky </button> <p class="oauth-note"> <small>After authentication, you can post comments that will be stored in your ATProto PDS.</small> </p> </div> <div id="comments-list" class="comments-list"> <p class="no-comments">Comments will appear here when posted via ATProto.</p> </div> </div> </section> </article> <aside class="article-sidebar"> <nav class="toc"> <h3>Contents</h3> <div id="toc-content"> <!-- TOC will be generated by JavaScript --> </div> </nav> </aside> </div> {% endblock %} {% block sidebar %} <script> document.addEventListener('DOMContentLoaded', function() { generateTableOfContents(); initializeSimpleAuth(); }); function generateTableOfContents() { const tocContainer = document.getElementById('toc-content'); const headings = document.querySelectorAll('.article-body h1, .article-body h2, .article-body h3, .article-body h4, .article-body h5, .article-body h6'); if (headings.length === 0) { tocContainer.innerHTML = '<p class="no-toc">No headings found</p>'; return; } const tocList = document.createElement('ul'); tocList.className = 'toc-list'; headings.forEach((heading, index) => { const id = `heading-${index}`; heading.id = id; const listItem = document.createElement('li'); listItem.className = `toc-item toc-${heading.tagName.toLowerCase()}`; const link = document.createElement('a'); link.href = `#${id}`; link.textContent = heading.textContent; link.className = 'toc-link'; link.addEventListener('click', function(e) { e.preventDefault(); heading.scrollIntoView({ behavior: 'smooth' }); }); listItem.appendChild(link); tocList.appendChild(listItem); }); tocContainer.appendChild(tocList); } function initializeSimpleAuth() { const authButton = document.getElementById('bluesky-auth'); authButton.addEventListener('click', function() { // Simple approach: Direct redirect to Bluesky OAuth const isProduction = window.location.hostname === 'log.syui.ai'; const clientId = isProduction ? 'https://log.syui.ai/client-metadata.json' : window.location.origin + '/client-metadata.json'; const authUrl = `https://bsky.social/oauth/authorize?` + `client_id=${encodeURIComponent(clientId)}&` + `redirect_uri=${encodeURIComponent(window.location.href)}&` + `response_type=code&` + `scope=atproto%20transition:generic&` + `state=demo-state`; console.log('Redirecting to:', authUrl); // Open in new tab for now (safer for testing) window.open(authUrl, '_blank'); // Show status message authButton.innerHTML = '✅ Check the new tab for authentication'; authButton.disabled = true; }); // Check if we're returning from OAuth const urlParams = new URLSearchParams(window.location.search); if (urlParams.has('code')) { console.log('OAuth callback detected:', urlParams.get('code')); document.querySelector('.simple-oauth').innerHTML = ` <div class="oauth-success"> ✅ OAuth callback received!<br> <small>Code: ${urlParams.get('code')}</small><br> <small>In a full implementation, this would exchange the code for tokens.</small> </div> `; } } </script> <style> .simple-oauth { background: #f8f9fa; border: 1px solid #e9ecef; border-radius: 8px; padding: 20px; margin: 20px 0; text-align: center; } .oauth-button { background: #1185fe; color: white; border: none; padding: 12px 24px; border-radius: 6px; font-size: 16px; cursor: pointer; margin: 10px 0; } .oauth-button:hover { background: #0d6efd; } .oauth-button:disabled { background: #6c757d; cursor: not-allowed; } .oauth-note { color: #6c757d; font-style: italic; } .oauth-success { background: #d1edff; border: 1px solid #b6d7ff; border-radius: 4px; padding: 15px; color: #0c5460; } </style> {% endblock %}