Files
kennethreitz.org/templates/base.html
T
2025-09-13 07:38:43 -04:00

339 lines
15 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{% block title %}{{ title }} - Kenneth Reitz{% endblock %}</title>
<!-- SEO and Meta -->
<meta name="description" content="{% block description %}Kenneth Reitz - Creator of Requests and Certifi, trusted by millions of developers worldwide. Thoughts on technology, philosophy, and building software for humans.{% endblock %}" />
<meta name="author" content="Kenneth Reitz" />
<!-- OpenGraph -->
<meta property="og:title" content="{% block og_title %}{{ title }} - Kenneth Reitz{% endblock %}" />
<meta property="og:description" content="{% block og_description %}Creator of Requests and Certifi - libraries trusted by millions of developers worldwide{% endblock %}" />
<meta property="og:type" content="{% block og_type %}website{% endblock %}" />
<meta property="og:url" content="{% block og_url %}https://kennethreitz.org{% endblock %}" />
<meta property="og:image" content="{% block og_image %}https://kennethreitz.org/static/images/social-card.jpg{% endblock %}" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:site_name" content="Kenneth Reitz" />
<!-- Twitter Card -->
<meta name="twitter:card" content="{% block twitter_card %}summary_large_image{% endblock %}" />
<meta name="twitter:creator" content="@kennethreitz42" />
<meta name="twitter:title" content="{% block twitter_title %}{{ title }} - Kenneth Reitz{% endblock %}" />
<meta name="twitter:description" content="{% block twitter_description %}Creator of Requests and Certifi - libraries trusted by millions of developers worldwide{% endblock %}" />
<meta name="twitter:image" content="{% block twitter_image %}https://kennethreitz.org/static/images/social-card.jpg{% endblock %}" />
<!-- RSS Feed -->
<link rel="alternate" type="application/rss+xml" title="Kenneth Reitz - Essays &amp; AI Writings" href="/feed.xml" />
<!-- Tufte CSS -->
<link rel="stylesheet" href="/static/tufte/tufte.css" />
<!-- Custom Site CSS -->
<link rel="stylesheet" href="/static/custom.css" />
<style>
/* Only page-specific or dynamic styles that can't be in external CSS */
</style>
<!-- Structured Data (JSON-LD) -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "{% block schema_type %}WebSite{% endblock %}",
"name": "{% block schema_name %}Kenneth Reitz{% endblock %}",
"url": "https://kennethreitz.org{% block schema_url %}/{% endblock %}",
"description": "{% block schema_description %}Kenneth Reitz - Creator of Requests and Certifi, trusted by millions of developers worldwide. Thoughts on technology, philosophy, and building software for humans.{% endblock %}",
"author": {
"@type": "Person",
"name": "Kenneth Reitz",
"url": "https://kennethreitz.org",
"sameAs": [
"https://github.com/kennethreitz",
"https://twitter.com/kennethreitz42"
],
"jobTitle": "Python Developer",
"worksFor": {
"@type": "Organization",
"name": "Independent"
},
"knowsAbout": [
"Python Programming",
"API Design",
"Software Architecture",
"Open Source Development",
"Artificial Intelligence",
"Mental Health Advocacy"
]
},
"publisher": {
"@type": "Person",
"name": "Kenneth Reitz",
"url": "https://kennethreitz.org"
}{% block schema_extra %}{% endblock %}
}
</script>
{% block extra_head %}{% endblock %}
<!-- Analytics -->
{% if not (config.get('DISABLE_ANALYTICS') or request.environ.get('DISABLE_ANALYTICS')) %}
<script type="text/javascript">
var _gauges = _gauges || [];
(function() {
var t = document.createElement('script');
t.type = 'text/javascript';
t.async = true;
t.id = 'gauges-tracker';
t.setAttribute('data-site-id', '65529a9abd1a3b3101979d52');
t.setAttribute('data-track-path', 'https://track.gaug.es/track.gif');
t.src = 'https://d2fuc4clr7gvcn.cloudfront.net/track.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(t, s);
})();
</script>
{% endif %}
</head>
<body>
<article>
<header>
<nav>
<a href="/">Home</a>
<a href="/archive">Archive</a>
<a href="/themes">Themes</a>
<a href="/directory">Directory</a>
<a href="/random" class="random-link">[random]</a>
</nav>
{% if current_path or breadcrumbs %}
<div class="breadcrumbs">
<a href="/">Home</a>
{% if breadcrumbs %}
{% for crumb in breadcrumbs %}
<span class="breadcrumb-separator">/</span>
<a href="{{ crumb.url }}">{{ crumb.name }}</a>
{% endfor %}
{% elif current_path %}
{% set path_parts = current_path.strip('/').split('/') %}
{% for part in path_parts if part %}
<span class="breadcrumb-separator">/</span>
{% set partial_path = '/' + path_parts[:loop.index]|join('/') %}
<a href="{{ partial_path }}">{{ part }}</a>
{% endfor %}
{% endif %}
</div>
{% endif %}
</header>
<main>
{% block content %}{% endblock %}
</main>
<footer>
<div class="footer-content">
<div class="footer-note">
<p>&copy; {{ "now"|strftime("%Y") }} Kenneth Reitz. Made with <a href="https://kjvstudy.org/book/1%20Corinthians/chapter/13">love</a>.</p>
</div>
</div>
</footer>
</article>
{% block extra_scripts %}{% endblock %}
<!-- Force light mode, especially on mobile -->
<style>
@media (prefers-color-scheme: dark) {
body {
background-color: rgb(255, 255, 248) !important;
color: #111 !important;
}
h1, h2, h3, h4, h5, h6 {
color: #333 !important;
}
a {
color: #111 !important;
}
/* Force light backgrounds on all elements */
* {
background-color: transparent !important;
color: inherit !important;
}
/* Override any dark mode styling */
body, html {
background: rgb(255, 255, 248) !important;
color: #111 !important;
}
}
/* Mobile-specific light mode enforcement */
@media (max-width: 760px) {
body {
background-color: rgb(255, 255, 248) !important;
color: #111 !important;
}
* {
background-color: transparent !important;
}
body, html {
background: rgb(255, 255, 248) !important;
color: #111 !important;
}
}
</style>
<!-- Simplified Color System (light themes only) -->
<script>
(function() {
// Check if user prefers light mode or is on mobile
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
const isMobile = window.innerWidth <= 760;
// Force light mode on mobile or if user prefers dark (override their dark preference)
if (isMobile || prefersDark) {
document.body.style.backgroundColor = 'rgb(255, 255, 248)';
document.body.style.color = '#111';
return; // Skip color schemes entirely
}
const lightColorSchemes = [
'scheme-ocean',
'scheme-forest',
'scheme-sunset',
'scheme-lavender',
'scheme-rose',
'scheme-sage',
'scheme-amber'
];
// Get or generate a scheme based on the current page
let scheme = localStorage.getItem('current-color-scheme');
// Change scheme occasionally (20% chance on page load)
if (!scheme || Math.random() < 0.2) {
scheme = lightColorSchemes[Math.floor(Math.random() * lightColorSchemes.length)];
localStorage.setItem('current-color-scheme', scheme);
}
// Apply the scheme
document.body.className = (document.body.className + ' ' + scheme).trim();
})();
</script>
<script>
// Add copy buttons to code blocks and subtle syntax highlighting
document.addEventListener('DOMContentLoaded', function() {
// Find all pre elements (code blocks)
const codeBlocks = document.querySelectorAll('pre');
// Function to add subtle comment highlighting
function highlightComments(pre) {
const code = pre.querySelector('code') || pre;
let html = code.innerHTML;
// Python/Shell comments (# comment) - both line start and inline
html = html.replace(/(^|\s+)(#.*)$/gm, '$1<span style="color: #888; font-style: italic;">$2</span>');
// Python docstrings (""" or ''')
html = html.replace(/("""[\s\S]*?""")/g, '<span style="color: #888; font-style: italic;">$1</span>');
html = html.replace(/('''[\s\S]*?''')/g, '<span style="color: #888; font-style: italic;">$1</span>');
// Python class names (class ClassName)
html = html.replace(/(\bclass\s+)([A-Za-z_][A-Za-z0-9_]*)/g, '$1<span style="font-weight: bold;">$2</span>');
// JavaScript/C++/Java comments (// comment)
html = html.replace(/(\s*\/\/.*)$/gm, '<span style="color: #888; font-style: italic;">$1</span>');
// CSS/C/Java block comments (/* comment */)
html = html.replace(/(\/\*[\s\S]*?\*\/)/g, '<span style="color: #888; font-style: italic;">$1</span>');
// HTML comments (<!-- comment -->)
html = html.replace(/(&lt;!--[\s\S]*?--&gt;)/g, '<span style="color: #888; font-style: italic;">$1</span>');
code.innerHTML = html;
}
codeBlocks.forEach(function(pre) {
// Add subtle comment highlighting first
highlightComments(pre);
// Skip if already wrapped
if (pre.parentElement.classList.contains('code-block-wrapper')) {
return;
}
// Create wrapper div
const wrapper = document.createElement('div');
wrapper.className = 'code-block-wrapper';
// Create copy button
const copyButton = document.createElement('button');
copyButton.className = 'copy-button';
copyButton.textContent = 'Copy';
copyButton.setAttribute('aria-label', 'Copy code to clipboard');
// Add click handler
copyButton.addEventListener('click', async function() {
try {
// Get the text content of the pre element
const codeText = pre.textContent || pre.innerText;
// Use modern clipboard API if available
if (navigator.clipboard && window.isSecureContext) {
await navigator.clipboard.writeText(codeText);
} else {
// Fallback for older browsers
const textArea = document.createElement('textarea');
textArea.value = codeText;
textArea.style.position = 'fixed';
textArea.style.left = '-999999px';
textArea.style.top = '-999999px';
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
document.execCommand('copy');
textArea.remove();
}
// Show feedback
const originalText = copyButton.textContent;
copyButton.textContent = 'Copied!';
copyButton.classList.add('copied');
setTimeout(function() {
copyButton.textContent = originalText;
copyButton.classList.remove('copied');
}, 2000);
} catch (err) {
console.error('Failed to copy code: ', err);
// Show error feedback
const originalText = copyButton.textContent;
copyButton.textContent = 'Failed';
setTimeout(function() {
copyButton.textContent = originalText;
}, 2000);
}
});
// Wrap the pre element and add the button
pre.parentNode.insertBefore(wrapper, pre);
wrapper.appendChild(pre);
wrapper.appendChild(copyButton);
});
});
</script>
</body>
</html>