A little app to serve my photography from my personal website

blog index page layout

ericwood.org 94271ffa 97e56c89

Waiting for spindle ...
+167 -45
+19 -5
assets/app.js
··· 1 + const longFormatter = new Intl.DateTimeFormat(undefined, { 2 + month: "short", 3 + day: "numeric", 4 + year: "numeric" 5 + }); 6 + 7 + const shortFormatter = new Intl.DateTimeFormat(undefined, { 8 + month: "2-digit", 9 + day: "2-digit", 10 + year: "2-digit", 11 + }); 12 + 1 13 const initTimestamps = () => { 2 14 document.querySelectorAll('time').forEach((el) => { 15 + let formatter = longFormatter 16 + const isShort = el.dataset.short === "true"; 17 + if (isShort) { 18 + formatter = shortFormatter; 19 + } 20 + 3 21 const timeStr = el.attributes.datetime; 4 22 if (!timeStr || !timeStr.value) { 5 23 return; 6 24 } 7 25 8 26 const date = new Date(timeStr.value); 9 - const formatted = new Intl.DateTimeFormat(undefined, { 10 - month: "short", 11 - day: "numeric", 12 - year: "numeric" 13 - }).format(date); 27 + const formatted = formatter.format(date); 14 28 15 29 el.innerText = formatted; 16 30 })
+55
src/views/blog/index/style.css
··· 1 + .blog__title { 2 + font-size: 26pt; 3 + } 4 + 5 + .blog__tags { 6 + display: flex; 7 + align-items: center; 8 + gap: 10px; 9 + padding: 10px 0; 10 + border-bottom: solid var(--foreground) 2px; 11 + } 12 + 13 + .blog__tags-title { 14 + font-size: 10pt; 15 + text-transform: uppercase; 16 + font-weight: 600; 17 + } 18 + 19 + .blog__tag-list { 20 + display: flex; 21 + gap: 5px; 22 + margin: 0; 23 + padding: 0; 24 + list-style-type: none; 25 + } 26 + 27 + .blog__entries { 28 + display: flex; 29 + flex-direction: column; 30 + gap: 10px; 31 + padding: 0; 32 + list-style-type: none; 33 + } 34 + 35 + .blog__entries li { 36 + display: flex; 37 + justify-content: space-between; 38 + border-bottom: solid var(--light) 1px; 39 + padding-bottom: 10px; 40 + } 41 + 42 + .blog__entries li > a { 43 + color: var(--foreground); 44 + font-size: 12pt; 45 + text-decoration: none; 46 + } 47 + 48 + .blog__entries li > a:hover { 49 + text-decoration: underline; 50 + } 51 + 52 + .blog__entries li time { 53 + font-family: monospace; 54 + margin-left: 10px; 55 + }
+49 -23
src/views/blog/index/template.jinja
··· 1 1 {% extends "layout" %} 2 2 {% set active_page = 'blog' %} 3 3 {% block title %}Blog{% endblock %} 4 + {% block head %} 5 + {{ inline_style("src/views/blog/shared.css") }} 6 + {{ inline_style("src/views/blog/index/style.css") }} 7 + {% endblock %} 4 8 5 9 {% block body %} 6 - Tags: 7 - <ul> 8 - {% if tag %} 10 + <div class="blog__layout"> 11 + <h2 class="blog__title"> 12 + → Blog 13 + {% if tag %} 14 + / {{ tag }} 15 + {% endif %} 16 + </h2> 17 + <div class="blog__tags"> 18 + <span class="blog__tags-title">Categories</span> 19 + <ul class="blog__tag-list"> 20 + {% if tag %} 21 + <li> 22 + <a href="/blog" class="tag active"> 23 + {{ tag }} 24 + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> 25 + <use xlink:href="#close-icon" /> 26 + </svg> 27 + </a> 28 + </li> 29 + {% endif %} 30 + {% for t in tags %} 31 + {% if t[0] != tag %} 32 + <li> 33 + <a class="tag" href="/blog?tag={{ url_escape(t[0]) }}">{{ t[0] }}</a> 34 + </li> 35 + {% endif %} 36 + {% endfor %} 37 + </ul> 38 + </div> 39 + <ul class="blog__entries"> 40 + {% for post in posts %} 9 41 <li> 10 - {{ tag }} <a href="/blog">X</a> 42 + <a href="/blog/{{ post.slug }}">{{ post.title }}</a> 43 + <span> 44 + {% for t in post.tags %} 45 + <a class="tag" href="/blog?tag={{ url_escape(t) }}">{{ t }}</a> 46 + {% endfor %} 47 + <time datetime="{{ post.published_at }}" data-short="true">{{ post.published_at }}</time> 48 + </span> 11 49 </li> 12 - {% endif %} 13 - {% for t in tags %} 14 - {% if t[0] != tag %} 15 - <li> 16 - <a href="/blog?tag={{ url_escape(t[0]) }}">{{ t[0] }} {{ t[1] }}</a> 17 - </li> 18 - {% endif %} 19 50 {% endfor %} 20 - </ul> 21 - <ul> 22 - {% for post in posts %} 23 - <li> 24 - <a href="/blog/{{ post.slug }}">{{ post.title }}</a> 25 - {% for t in post.tags %} 26 - <a href="/blog?tag={{ url_escape(t) }}">{{ t }}</a> 27 - {% endfor %} 28 - <time datetime="{{ post.published_at }}">{{ post.published_at }}</time> 29 - </li> 30 - {% endfor %} 31 - </ul> 51 + </ul> 52 + </div> 53 + <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="display: none"> 54 + <defs> 55 + <path id="close-icon" d="M20.7457 3.32851C20.3552 2.93798 19.722 2.93798 19.3315 3.32851L12.0371 10.6229L4.74275 3.32851C4.35223 2.93798 3.71906 2.93798 3.32854 3.32851C2.93801 3.71903 2.93801 4.3522 3.32854 4.74272L10.6229 12.0371L3.32856 19.3314C2.93803 19.722 2.93803 20.3551 3.32856 20.7457C3.71908 21.1362 4.35225 21.1362 4.74277 20.7457L12.0371 13.4513L19.3315 20.7457C19.722 21.1362 20.3552 21.1362 20.7457 20.7457C21.1362 20.3551 21.1362 19.722 20.7457 19.3315L13.4513 12.0371L20.7457 4.74272C21.1362 4.3522 21.1362 3.71903 20.7457 3.32851Z" fill="currentColor"/> 56 + </defs> 57 + </svg> 32 58 {% endblock %}
+34
src/views/blog/shared.css
··· 1 + .blog__layout { 2 + width: fit-content; 3 + margin: 0 auto; 4 + max-width: 900px; 5 + width: 100%; 6 + } 7 + 8 + .blog__container { 9 + display: flex; 10 + gap: 60px; 11 + position: relative; 12 + } 13 + 14 + .tag { 15 + border-radius: 5px; 16 + padding: 3px 7px; 17 + background-color: var(--light); 18 + color: var(--foreground); 19 + text-decoration: none; 20 + display: inline-flex; 21 + align-items: center; 22 + gap: 5px; 23 + } 24 + 25 + .tag svg { 26 + width: 12px; 27 + height: 12px; 28 + } 29 + 30 + .tag.active { 31 + padding: 1px 5px; 32 + border: solid var(--foreground) 2px; 33 + background-color: var(--background); 34 + }
-11
src/views/blog/show/style.css
··· 1 - .blog__layout { 2 - width: fit-content; 3 - margin: 0 auto; 4 - } 5 - 6 - .blog__container { 7 - display: flex; 8 - gap: 60px; 9 - position: relative; 10 - } 11 - 12 1 .blog__header { 13 2 border-bottom: solid var(--foreground) 3px; 14 3 }
+10 -6
src/views/blog/show/template.jinja
··· 2 2 {% set active_page = 'blog' %} 3 3 {% block title %}Blog{% endblock %} 4 4 {% block head %} 5 + {{ inline_style("src/views/blog/shared.css") }} 5 6 {{ inline_style("src/views/blog/show/style.css") }} 6 7 {% if has_code %} 7 8 {{ inline_style("src/views/blog/show/syntax.css") }} ··· 10 11 {% block body %} 11 12 <div class="blog__layout"> 12 13 <div class="blog__header"> 13 - <h1 class="blog__title">{{ post.title }}</h1> 14 + <h2 class="blog__title">{{ post.title }}</h2> 14 15 <p> 15 16 <time datetime="{{ post.published_at }}">{{ post.published_at }}</time> 16 17 </p> 17 - <ul> 18 - {% for tag in post.tags %} 19 - <li><a href="/blog?tag={{ tag }}">{{ tag }}</a></li> 20 - {% endfor %} 21 - </ul> 18 + <div class="blog__tags"> 19 + <span class="blog__tags-title">Filed Under</span> 20 + <ul class="blog__tag-list"> 21 + {% for tag in post.tags %} 22 + <li><a href="/blog?tag={{ tag }}">{{ tag }}</a></li> 23 + {% endfor %} 24 + </ul> 25 + </div> 22 26 </div> 23 27 <div class="blog__container"> 24 28 <div class="blog__body">