mirror of
https://github.com/kennethreitz/kennethreitz.org.git
synced 2026-10-24 14:39:14 +00:00
Publish the Obsidian vault's Knowledge folder as /knowledge (881 notes, 67 folders), with a Knowledge item in the nav and footer. - scripts/import_knowledge.py regenerates data/knowledge from the vault: slugged paths, folder notes as index pages, wikilinks resolved to site links (or plain text), callouts, highlights, and Dataview tables rendered statically. Personal notes are withheld via an exclusion list plus a privacy guard. - tuftecms/core/knowledge.py builds a concept index from note titles and aliases. First mentions on ordinary pages link to their Knowledge note (capped, never in headings, code, links, or sidenotes); Knowledge pages list related notes and where they're mentioned across the site; other pages get a Related Knowledge block. - Knowledge URLs join sitemap.xml (so the sweep test covers them), never displace existing legacy slugs, list alphabetically, and mermaid diagrams render client-side only on pages that have them.
778 lines
23 KiB
HTML
778 lines
23 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block og_title %}{{ title }}{% endblock %}
|
|
{% block og_description %}{% if description %}{{ description[:160] }}{% else %}{{ content | striptags | truncate(160) }}{% endif %}{% endblock %}
|
|
{% block og_type %}article{% endblock %}
|
|
{% block og_url %}https://kennethreitz.org{{ request.path }}{% endblock %}
|
|
{% block og_image %}https://kennethreitz.org/og-image{{ request.path }}.png{% endblock %}
|
|
|
|
{% block twitter_title %}{{ title }}{% endblock %}
|
|
{% block twitter_description %}{% if description %}{{ description[:160] }}{% else %}{{ content | striptags | truncate(160) }}{% endif %}{% endblock %}
|
|
{% block twitter_image %}https://kennethreitz.org/og-image{{ request.path }}.png{% endblock %}
|
|
|
|
{% block og_image_alt %}{{ title }} - An article by Kenneth Reitz{% endblock %}
|
|
|
|
{% block extra_meta %}{% if published_iso %}<meta property="article:published_time" content="{{ published_iso }}" />
|
|
{% endif %}{% if modified_iso %}<meta property="article:modified_time" content="{{ modified_iso }}" />{% endif %}{% endblock %}
|
|
|
|
{% block description %}{% if description %}{{ description }}{% else %}{{ content | striptags | truncate(200) }}{% endif %}{% endblock %}
|
|
|
|
{% block schema_type %}Article{% endblock %}
|
|
{% block schema_name %}{{ title }}{% endblock %}
|
|
{% block schema_url %}{{ current_path }}{% endblock %}
|
|
{% block schema_description %}{% if metadata.description %}{{ metadata.description }}{% else %}{{ title }} - An essay by Kenneth Reitz{% endif %}{% endblock %}
|
|
|
|
{% block schema_extra %},
|
|
"headline": "{{ title }}",
|
|
"articleSection": "{% if 'artificial-intelligence' in current_path %}AI & Consciousness{% elif 'essays' in current_path %}Essays{% elif 'poetry' in current_path %}Poetry{% elif 'software' in current_path %}Software{% elif 'music' in current_path %}Music{% else %}Writing{% endif %}",
|
|
"wordCount": {{ (content | length / 5) | int }},
|
|
{% if metadata and metadata.date %}
|
|
"datePublished": "{{ metadata.date[0] if metadata.date is iterable and metadata.date is not string else metadata.date }}",
|
|
"dateModified": "{{ metadata.date[0] if metadata.date is iterable and metadata.date is not string else metadata.date }}",
|
|
{% endif %}
|
|
"keywords": {% if 'artificial-intelligence' in current_path %}["artificial intelligence", "consciousness", "AI philosophy", "human-AI collaboration", "machine learning"]{% elif 'mental-health' in current_path %}["mental health", "bipolar disorder", "neurodivergent", "tech industry wellness", "psychology"]{% elif 'poetry' in current_path %}["poetry", "creative writing", "verse", "contemplation", "language"]{% elif 'software' in current_path %}["software development", "Python", "open source", "programming", "API design"]{% elif 'music' in current_path %}["music", "audio", "creative arts", "sound design"]{% elif 'essays' in current_path %}["technology", "software development", "Python", "philosophy", "programming"]{% else %}["writing", "thoughts", "contemplation", "technology"]{% endif %},
|
|
"inLanguage": "en-US",
|
|
"isAccessibleForFree": true,
|
|
"mainEntityOfPage": {
|
|
"@type": "WebPage",
|
|
"@id": "https://kennethreitz.org{{ current_path }}"
|
|
},
|
|
"image": {
|
|
"@type": "ImageObject",
|
|
"url": "https://kennethreitz.org/og-image{{ current_path }}.png",
|
|
"width": 1200,
|
|
"height": 630
|
|
}{% endblock %}
|
|
|
|
{% block extra_head %}
|
|
<style>
|
|
.post-shell {
|
|
padding: 0 !important;
|
|
}
|
|
|
|
.post-header {
|
|
margin-bottom: 2.75rem;
|
|
padding-bottom: 1.4rem;
|
|
border-bottom: 1px solid var(--line-soft);
|
|
width: 70%;
|
|
}
|
|
|
|
.post-header--no-breadcrumb {
|
|
margin-top: 1.35rem;
|
|
}
|
|
|
|
/* Post header: Tufte-style, colored entirely by the design tokens. */
|
|
.post-title-container {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 1.1rem;
|
|
margin-bottom: 0.5rem;
|
|
width: 100%;
|
|
}
|
|
|
|
.post-title-text {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.post-title {
|
|
font-size: 3.2rem;
|
|
font-style: italic;
|
|
font-weight: 400;
|
|
line-height: 1.05;
|
|
margin: 0;
|
|
color: var(--ink);
|
|
text-rendering: optimizeLegibility;
|
|
text-wrap: balance;
|
|
}
|
|
|
|
.post-title-icon {
|
|
width: 48px;
|
|
height: 48px;
|
|
flex-shrink: 0;
|
|
margin-left: -4rem;
|
|
margin-top: 0.45rem;
|
|
}
|
|
|
|
.post-description {
|
|
color: var(--ink-muted);
|
|
font-size: 1.25rem;
|
|
font-style: italic;
|
|
line-height: 1.45;
|
|
margin: 1rem 0 0;
|
|
width: 92% !important;
|
|
text-align: left !important;
|
|
}
|
|
|
|
/* A fleuron closes each dated essay. */
|
|
.dated-post::after {
|
|
content: "❦";
|
|
display: block;
|
|
width: 65%;
|
|
text-align: center;
|
|
margin-top: 3rem;
|
|
color: var(--ink-faint);
|
|
font-size: 1.3rem;
|
|
line-height: 1;
|
|
}
|
|
|
|
/* Chronological neighbors */
|
|
.post-nav {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
gap: 2rem;
|
|
width: 65%;
|
|
margin-top: 3rem;
|
|
padding-top: 1.5rem;
|
|
border-top: 1px solid var(--line-soft);
|
|
}
|
|
|
|
.post-nav-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.35rem;
|
|
max-width: 46%;
|
|
}
|
|
|
|
.post-nav-newer {
|
|
text-align: right;
|
|
margin-left: auto;
|
|
}
|
|
|
|
.post-nav-label {
|
|
font-variant: small-caps;
|
|
letter-spacing: 0.06em;
|
|
font-size: 0.85rem;
|
|
color: var(--ink-faint);
|
|
}
|
|
|
|
.post-nav a {
|
|
font-size: 1.05rem;
|
|
line-height: 1.25;
|
|
text-decoration-thickness: 0.05em;
|
|
}
|
|
|
|
.post-shell .related-essays {
|
|
width: 65%;
|
|
margin-top: 3.75rem;
|
|
padding-top: 1.5rem;
|
|
border-top: 1px solid var(--line-soft);
|
|
}
|
|
|
|
.post-shell .related-essays h2 {
|
|
color: var(--ink-muted);
|
|
font-size: 1.15rem !important;
|
|
font-style: normal;
|
|
font-variant: small-caps;
|
|
font-weight: 400;
|
|
letter-spacing: 0.06em;
|
|
margin: 0 0 1rem !important;
|
|
}
|
|
|
|
.post-shell .related-essays li {
|
|
gap: 0.7rem;
|
|
margin: 0.65rem 0;
|
|
line-height: 1.25;
|
|
}
|
|
|
|
.post-shell .related-essays a {
|
|
text-decoration-thickness: 0.05em;
|
|
}
|
|
|
|
.post-subtitle {
|
|
font-size: 0.98rem;
|
|
color: var(--ink-muted);
|
|
margin-top: 1.25rem;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 1rem;
|
|
font-family: et-book-roman-old-style, et-book, Palatino, "Palatino Linotype", "Book Antiqua", Georgia, serif;
|
|
}
|
|
|
|
.post-meta-primary,
|
|
.post-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: 0.55rem;
|
|
}
|
|
|
|
.post-date {
|
|
color: var(--ink-muted);
|
|
font-variant: small-caps;
|
|
letter-spacing: 0.08em;
|
|
}
|
|
|
|
/* Quiet badges: date companions. */
|
|
.reading-time-badge,
|
|
.themes-badge,
|
|
.pdf-badge,
|
|
.markdown-badge {
|
|
font-variant: normal;
|
|
font-size: 0.85rem;
|
|
letter-spacing: normal;
|
|
font-weight: 400;
|
|
font-family: et-book, Palatino, "Palatino Linotype", "Palatino LT STD", "Book Antiqua", Georgia, serif;
|
|
color: var(--ink-muted);
|
|
background: color-mix(in srgb, var(--surface) 82%, transparent);
|
|
border: 1px solid var(--line-soft);
|
|
border-radius: 999px;
|
|
padding: 0.18rem 0.68rem;
|
|
text-decoration: none;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
min-height: 1.5rem;
|
|
transition: color 0.2s ease, border-color 0.2s ease, background-color 0.2s ease;
|
|
}
|
|
|
|
.themes-badge {
|
|
cursor: pointer;
|
|
}
|
|
|
|
.themes-badge:hover,
|
|
.pdf-badge:hover,
|
|
.markdown-badge:hover {
|
|
color: var(--accent);
|
|
border-color: var(--accent);
|
|
background: color-mix(in srgb, var(--accent) 7%, transparent);
|
|
}
|
|
|
|
.pdf-badge,
|
|
.markdown-badge {
|
|
margin-left: 0;
|
|
}
|
|
|
|
.formats-label {
|
|
font-variant: small-caps;
|
|
font-size: 0.85rem;
|
|
color: var(--ink-muted);
|
|
margin-left: 0.5rem;
|
|
letter-spacing: 0.05em;
|
|
font-family: et-book, Palatino, "Palatino Linotype", "Palatino LT STD", "Book Antiqua", Georgia, serif;
|
|
}
|
|
|
|
.themes-dropdown {
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
|
|
.themes-dropdown-content {
|
|
display: none;
|
|
position: absolute;
|
|
background-color: var(--surface);
|
|
min-width: 220px;
|
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
|
border: 1px solid var(--line);
|
|
border-radius: 6px;
|
|
z-index: 9999;
|
|
margin-top: 0.25rem;
|
|
top: 100%;
|
|
left: 0;
|
|
}
|
|
|
|
.themes-dropdown-content a {
|
|
color: var(--ink-muted);
|
|
padding: 0.5rem 1rem;
|
|
text-decoration: none;
|
|
display: block;
|
|
transition: background 0.2s ease;
|
|
font-variant: normal;
|
|
letter-spacing: normal;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.themes-dropdown-content a:hover {
|
|
background-color: var(--line-soft);
|
|
color: var(--ink);
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.post-subtitle {
|
|
flex-wrap: wrap;
|
|
gap: 0.75rem;
|
|
}
|
|
|
|
.reading-time-badge,
|
|
.themes-badge,
|
|
.pdf-badge,
|
|
.markdown-badge {
|
|
font-size: 0.8rem;
|
|
padding: 0.1rem 0.55rem;
|
|
}
|
|
|
|
.pdf-badge,
|
|
.markdown-badge {
|
|
display: none;
|
|
}
|
|
|
|
.themes-dropdown-content {
|
|
min-width: 150px;
|
|
font-size: 0.85rem;
|
|
}
|
|
}
|
|
|
|
.themes-dropdown-content.show {
|
|
display: block;
|
|
}
|
|
|
|
.sidenote-highlighted {
|
|
background: color-mix(in srgb, var(--accent) 11%, transparent);
|
|
border-left: 2px solid color-mix(in srgb, var(--accent) 50%, var(--line));
|
|
color: var(--ink);
|
|
padding-left: 0.75rem;
|
|
transition: background-color 0.2s ease, border-color 0.2s ease;
|
|
}
|
|
|
|
/* Reading body */
|
|
.post-body p,
|
|
.post-body li,
|
|
.post-body blockquote {
|
|
line-height: 1.55;
|
|
}
|
|
|
|
.post-body p,
|
|
.post-shell p:not(.sidenote):not(.marginnote) {
|
|
text-align: justify;
|
|
text-justify: inter-word;
|
|
hyphens: auto;
|
|
-webkit-hyphens: auto;
|
|
-ms-hyphens: auto;
|
|
word-break: normal;
|
|
overflow-wrap: break-word;
|
|
margin-left: 0 !important;
|
|
margin-right: auto !important;
|
|
}
|
|
|
|
.post-body > p:first-child {
|
|
margin-top: 0;
|
|
}
|
|
|
|
.post-body > p:first-child:not(:has(img)) {
|
|
font-size: 1.45rem;
|
|
line-height: 1.48;
|
|
}
|
|
|
|
.post-body h2,
|
|
.post-body h3,
|
|
.post-body h4 {
|
|
text-wrap: balance;
|
|
}
|
|
|
|
/* Asterism HR styling */
|
|
.post-shell hr {
|
|
width: 65%;
|
|
max-width: 65%;
|
|
margin: 4rem 0;
|
|
}
|
|
|
|
/* Directory listing - appears at top when items exist */
|
|
.directory-listing {
|
|
margin-bottom: 3rem;
|
|
padding-bottom: 2rem;
|
|
border-bottom: 1px solid var(--line-soft);
|
|
width: 65%;
|
|
}
|
|
|
|
.directory-listing h2,
|
|
.directory-about h2 {
|
|
font-size: 1.1rem;
|
|
margin-bottom: 1.25rem;
|
|
font-weight: 400;
|
|
font-variant: small-caps;
|
|
letter-spacing: 0.05em;
|
|
color: var(--ink-muted);
|
|
}
|
|
|
|
.items-list {
|
|
list-style: none;
|
|
padding-left: 0;
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
|
gap: 0.75rem 1.5rem;
|
|
}
|
|
|
|
.items-list li {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.items-list a {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.6rem;
|
|
text-decoration: none;
|
|
color: var(--ink-muted);
|
|
transition: color 0.2s ease;
|
|
padding: 0.4rem 0;
|
|
}
|
|
|
|
.items-list a:hover {
|
|
color: var(--ink);
|
|
}
|
|
|
|
.item-icon {
|
|
width: 22px;
|
|
height: 22px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.item-name {
|
|
line-height: 1.3;
|
|
font-size: 0.95rem;
|
|
}
|
|
|
|
/* About section that follows directory listing */
|
|
.directory-about {
|
|
margin-top: 0;
|
|
}
|
|
|
|
/* Parent navigation */
|
|
.parent-navigation {
|
|
margin-top: 4rem;
|
|
padding-top: 2rem;
|
|
border-top: 1px solid var(--line-soft);
|
|
width: 65%;
|
|
}
|
|
|
|
.parent-link {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.75rem;
|
|
text-decoration: none;
|
|
color: var(--ink-muted);
|
|
font-size: 0.95rem;
|
|
font-style: italic;
|
|
transition: color 0.2s ease;
|
|
}
|
|
|
|
.parent-link:hover {
|
|
color: var(--ink);
|
|
}
|
|
|
|
.parent-icon {
|
|
width: 20px;
|
|
height: 20px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.parent-text {
|
|
line-height: 1.2;
|
|
}
|
|
|
|
@media (max-width: 760px) {
|
|
|
|
.post-shell {
|
|
padding: 0 !important;
|
|
}
|
|
|
|
.post-header {
|
|
width: 100%;
|
|
margin-bottom: 2.2rem;
|
|
padding-bottom: 1.15rem;
|
|
}
|
|
|
|
.post-title {
|
|
font-size: 2.25rem;
|
|
width: 100%;
|
|
}
|
|
|
|
.post-subtitle {
|
|
align-items: flex-start;
|
|
font-size: 0.92rem;
|
|
margin-top: 1rem;
|
|
}
|
|
|
|
.post-title-container {
|
|
display: block;
|
|
width: 100%;
|
|
}
|
|
|
|
.post-title-icon {
|
|
margin-left: 0;
|
|
margin-top: 0;
|
|
margin-bottom: 0.85rem;
|
|
width: 30px;
|
|
height: 30px;
|
|
}
|
|
|
|
.post-description {
|
|
font-size: 1.08rem;
|
|
width: 100% !important;
|
|
}
|
|
|
|
.post-shell hr {
|
|
width: 100%;
|
|
max-width: 100%;
|
|
}
|
|
|
|
.post-body p,
|
|
.post-body li,
|
|
.post-shell p:not(.sidenote):not(.marginnote) {
|
|
width: 100% !important;
|
|
max-width: 100% !important;
|
|
text-align: left !important;
|
|
hyphens: none;
|
|
-webkit-hyphens: none;
|
|
}
|
|
|
|
.post-body > p:first-child:not(:has(img)) {
|
|
font-size: 1.22rem;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.directory-listing {
|
|
width: 100%;
|
|
margin-bottom: 2rem;
|
|
padding-bottom: 1.5rem;
|
|
}
|
|
|
|
.directory-listing h2,
|
|
.directory-about h2 {
|
|
font-size: 1rem;
|
|
}
|
|
|
|
.items-list {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.parent-navigation {
|
|
width: 100%;
|
|
margin-top: 3rem;
|
|
padding-top: 1.5rem;
|
|
}
|
|
|
|
.dated-post::after,
|
|
.post-nav,
|
|
.post-shell .related-essays {
|
|
width: 100%;
|
|
}
|
|
|
|
.post-nav {
|
|
flex-direction: column;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.post-nav-newer {
|
|
text-align: left;
|
|
margin-left: 0;
|
|
}
|
|
|
|
.post-nav-item {
|
|
max-width: 100%;
|
|
}
|
|
|
|
.parent-link {
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.parent-icon {
|
|
width: 18px;
|
|
height: 18px;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
// When arriving at a page with a hash pointing to a sidenote, auto-open it
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
if (window.location.hash) {
|
|
const sidenoteId = window.location.hash.substring(1);
|
|
const checkbox = document.getElementById(sidenoteId);
|
|
if (checkbox && checkbox.type === 'checkbox') {
|
|
// Check the checkbox to reveal the sidenote
|
|
checkbox.checked = true;
|
|
|
|
// Find the label or parent paragraph to scroll to
|
|
const label = document.querySelector(`label[for="${sidenoteId}"]`);
|
|
const scrollTarget = label ? label : checkbox.parentElement;
|
|
|
|
// Scroll to the sidenote after a brief delay
|
|
setTimeout(() => {
|
|
if (scrollTarget) {
|
|
scrollTarget.scrollIntoView({behavior: 'smooth', block: 'center'});
|
|
}
|
|
|
|
// Highlight the sidenote permanently
|
|
const sidenote = checkbox.nextElementSibling;
|
|
if (sidenote && sidenote.classList.contains('sidenote')) {
|
|
sidenote.classList.add('sidenote-highlighted');
|
|
}
|
|
}, 100);
|
|
}
|
|
}
|
|
|
|
// Themes dropdown
|
|
const themesButton = document.querySelector('.themes-badge');
|
|
const themesDropdown = document.querySelector('.themes-dropdown-content');
|
|
|
|
if (themesButton && themesDropdown) {
|
|
themesButton.addEventListener('click', function(e) {
|
|
e.stopPropagation();
|
|
const isOpen = themesDropdown.classList.toggle('show');
|
|
themesButton.setAttribute('aria-expanded', String(isOpen));
|
|
});
|
|
|
|
// Close dropdown when clicking outside
|
|
document.addEventListener('click', function() {
|
|
themesDropdown.classList.remove('show');
|
|
themesButton.setAttribute('aria-expanded', 'false');
|
|
});
|
|
}
|
|
|
|
});
|
|
</script>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
{% set post_path_parts = current_path.strip('/').split('/') if current_path else [] %}
|
|
{% set has_visible_breadcrumbs = post_path_parts|length > 1 %}
|
|
<article class="post-shell">
|
|
<header class="post-header{% if not has_visible_breadcrumbs %} post-header--no-breadcrumb{% endif %}">
|
|
<div class="post-title-container{% if unique_icon %} has-icon{% endif %}">
|
|
{% if unique_icon %}
|
|
<img src="{{ unique_icon }}" alt="Icon for {{ title }}" class="post-title-icon">
|
|
{% endif %}
|
|
<div class="post-title-text">
|
|
<h1 class="post-title">{{ title }}</h1>
|
|
{% if description %}
|
|
<p class="post-description">{{ description }}</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% if metadata and metadata.date %}
|
|
{% set post_date = metadata.date if metadata.date is string else metadata.date[0] %}
|
|
<div class="post-subtitle" aria-label="Article metadata">
|
|
<div class="post-meta-primary">
|
|
<time class="post-date" datetime="{{ published_iso or post_date }}">{{ post_date }}</time>
|
|
{% if reading_time %}
|
|
<span class="reading-time-badge">{{ reading_time }} min read</span>
|
|
{% endif %}
|
|
</div>
|
|
<div class="post-actions">
|
|
{% if article_themes and article_themes|length > 0 %}
|
|
<div class="themes-dropdown">
|
|
<button class="themes-badge" type="button" aria-expanded="false" aria-haspopup="true">{{ article_themes|length }} theme{{ 's' if article_themes|length != 1 else '' }}</button>
|
|
<div class="themes-dropdown-content">
|
|
{% for theme in article_themes %}
|
|
<a href="/archive/themes#{{ theme.name|replace(' ', '-') }}">{{ theme.name }}</a>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% if pdf_available %}
|
|
<a href="{{ request.path }}.pdf" class="pdf-badge" title="Download as PDF">PDF</a>
|
|
{% endif %}
|
|
<a href="{{ request.path }}.md" class="markdown-badge" title="View Markdown source">Markdown</a>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</header>
|
|
|
|
{% if items %}
|
|
<div class="directory-listing">
|
|
<h2>In This Section</h2>
|
|
<ul class="items-list">
|
|
{% for item in items %}
|
|
<li class="item {% if item.is_dir %}folder{% else %}file{% endif %}">
|
|
<a href="{{ item.url_path }}">
|
|
{% if item.unique_icon %}
|
|
<img src="{{ item.unique_icon }}" alt="{{ item.name }}" class="item-icon">
|
|
{% endif %}
|
|
<span class="item-name">{{ item.display_name or item.name }}</span>
|
|
</a>
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if items and content and content|striptags|trim %}
|
|
<div class="directory-about">
|
|
<h2>About</h2>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<section class="post-body{% if metadata and metadata.date %} dated-post{% endif %}">
|
|
{{ content | safe }}
|
|
</section>
|
|
|
|
{% if knowledge_related or knowledge_mentions %}
|
|
<section class="knowledge-connections">
|
|
{% if knowledge_related %}
|
|
<h2>Related Knowledge</h2>
|
|
<ul class="knowledge-list">
|
|
{% for k in knowledge_related %}
|
|
<li><a href="{{ k.url }}">{{ k.title }}</a></li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% endif %}
|
|
{% if knowledge_mentions %}
|
|
<h2>Mentioned Across the Site</h2>
|
|
<ul class="knowledge-mentions">
|
|
{% for p in knowledge_mentions %}
|
|
<li><a href="{{ p.url }}">{{ p.title }}</a>{% if p.date %}<span class="recent-post-date">{{ p.date[:4] }}</span>{% endif %}</li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% endif %}
|
|
</section>
|
|
{% endif %}
|
|
|
|
{% if related_knowledge %}
|
|
<section class="knowledge-connections related-knowledge">
|
|
<h2>Related Knowledge</h2>
|
|
<ul class="knowledge-list">
|
|
{% for k in related_knowledge %}
|
|
<li><a href="{{ k.url }}">{{ k.title }}</a></li>
|
|
{% endfor %}
|
|
</ul>
|
|
</section>
|
|
{% endif %}
|
|
|
|
{% if related_posts %}
|
|
<section class="related-essays">
|
|
<h2>Keep Reading</h2>
|
|
<ul>
|
|
{% for p in related_posts %}
|
|
<li>
|
|
{% if p.unique_icon %}<img src="{{ p.unique_icon }}" alt="" class="related-icon">{% endif %}
|
|
<a href="{{ p.url }}">{{ p.title }}</a>{% if p.date %}<span class="recent-post-date">{{ p.date[:4] }}</span>{% endif %}
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</section>
|
|
{% endif %}
|
|
|
|
{% if newer_post or older_post %}
|
|
<nav class="post-nav" aria-label="Chronological navigation">
|
|
<div class="post-nav-item post-nav-older">
|
|
{% if older_post %}
|
|
<span class="post-nav-label">← Older</span>
|
|
<a href="{{ older_post.url }}">{{ older_post.title }}</a>
|
|
{% endif %}
|
|
</div>
|
|
<div class="post-nav-item post-nav-newer">
|
|
{% if newer_post %}
|
|
<span class="post-nav-label">Newer →</span>
|
|
<a href="{{ newer_post.url }}">{{ newer_post.title }}</a>
|
|
{% endif %}
|
|
</div>
|
|
</nav>
|
|
{% endif %}
|
|
|
|
<!-- Comments disabled for now -->
|
|
|
|
{% if parent_directory %}
|
|
<div class="parent-navigation">
|
|
<a href="{{ parent_directory.url }}" class="parent-link">
|
|
{% if parent_directory.icon %}
|
|
<img src="{{ parent_directory.icon }}" alt="Parent directory icon" class="parent-icon">
|
|
{% endif %}
|
|
<span class="parent-text">← {{ parent_directory.display_name }}</span>
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
</article>
|
|
|
|
{% endblock %}
|