my personal website!

blog thing

aylac.top 0097fb58 1db23a12

verified
+153 -18
+30
_data/blogEntries.js
···
··· 1 + import { XRPC, CredentialManager } from "@atcute/client"; 2 + 3 + const manager = new CredentialManager({ 4 + service: "https://inkcap.us-east.host.bsky.network", 5 + }); 6 + const rpc = new XRPC({ handler: manager }); 7 + 8 + let records = []; 9 + let cursor = undefined; 10 + do { 11 + const response = ( 12 + await rpc.get("com.atproto.repo.listRecords", { 13 + params: { 14 + repo: "did:plc:avlpu4l2j5u3johint7tqrmu", 15 + collection: "top.aylac.blog.entry", 16 + cursor: cursor, 17 + limit: 100, 18 + }, 19 + }) 20 + ).data; 21 + records = records.concat(response.records); 22 + cursor = response.cursor; 23 + } while (cursor); 24 + records.sort( 25 + (a, b) => new Date(b.value.createdAt) - new Date(a.value.createdAt), 26 + ); 27 + 28 + export default function () { 29 + return records; 30 + }
+3 -2
_includes/main_layout.njk
··· 3 <head> 4 <meta charset="utf-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 - <link rel="stylesheet" href="./styles.css" /> 7 <link rel="icon" href="./favicon.png" /> 8 <title>{{ title }}</title> 9 </head> 10 <body> 11 - {{ content | safe }} 12 </body> 13 </html>
··· 3 <head> 4 <meta charset="utf-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 + <link rel="stylesheet" href="/styles.css" /> 7 <link rel="icon" href="./favicon.png" /> 8 <title>{{ title }}</title> 9 </head> 10 <body> 11 + <div class="nav"><a href="/">home</a><span>ayla</span><a href="/blog">blog</a></div> 12 + {{ content | safe }} 13 </body> 14 </html>
+17
blog-entry.njk
···
··· 1 + --- 2 + layout: main_layout.njk 3 + pagination: 4 + data: blogEntries 5 + size: 1 6 + alias: blog 7 + addAllPagesToCollections: true 8 + permalink: "/blog/{{ blog.value.title | slugify }}/index.html" 9 + eleventyComputed: 10 + title: "{{ blog.value.title }} - ayla" 11 + --- 12 + 13 + <div class="header"> 14 + <h1>{{ blog.value.title }}</h1> 15 + <span class="date">{{ blog.value.createdAt | format_date }}</span> 16 + </div> 17 + {{ blog.value.content | markdown | safe }}
+13
blog-index.njk
···
··· 1 + --- 2 + layout: main_layout.njk 3 + permalink: "/blog/index.html" 4 + title: "blog - ayla" 5 + --- 6 + 7 + {% for entry in blogEntries %} 8 + <div class="entry"> 9 + <a class="entry-title" href="/blog/{{ entry.value.title | slugify }}">{{ entry.value.title }}</a> 10 + <span class="entry-excerpt">{{ entry.value.content | truncate }}</span> 11 + <span class="entry-date">{{ entry.value.createdAt | format_date }}</span> 12 + </div> 13 + {% endfor %}
+19 -7
eleventy.config.js
··· 1 - module.exports = function (eleventyConfig) { 2 - const htmlmin = require("html-minifier"); 3 - const sass = require("sass"); 4 - const path = require("path"); 5 6 eleventyConfig.addPassthroughCopy("favicon.png"); 7 - eleventyConfig.addPassthroughCopy("_config.yml"); 8 - eleventyConfig.addPassthroughCopy("CNAME"); 9 eleventyConfig.addPassthroughCopy(".well-known/*"); 10 11 eleventyConfig.addTemplateFormats("scss"); ··· 33 } 34 return content; 35 }); 36 - };
··· 1 + import htmlmin from "html-minifier"; 2 + import * as sass from "sass"; 3 + import path from "path"; 4 + import markdownit from "markdown-it"; 5 + const md = markdownit(); 6 7 + export default function (eleventyConfig) { 8 eleventyConfig.addPassthroughCopy("favicon.png"); 9 eleventyConfig.addPassthroughCopy(".well-known/*"); 10 11 eleventyConfig.addTemplateFormats("scss"); ··· 33 } 34 return content; 35 }); 36 + 37 + eleventyConfig.addNunjucksFilter("markdown", function (value) { 38 + return md.render(value); 39 + }); 40 + 41 + eleventyConfig.addNunjucksFilter("format_date", function (value) { 42 + return new Date(value).toISOString().slice(0, 16).replace("T", " "); 43 + }); 44 + 45 + eleventyConfig.addNunjucksFilter("truncate", function (value, length = 300) { 46 + return value.slice(0, length); 47 + }); 48 + }
+10 -5
package.json
··· 1 { 2 - "devDependencies": { 3 - "@11ty/eleventy": "^3.0.0", 4 - "html-minifier": "^4.0.0", 5 - "sass": "^1.85.1" 6 - } 7 }
··· 1 { 2 + "type": "module", 3 + "devDependencies": { 4 + "@11ty/eleventy": "^3.0.0", 5 + "html-minifier": "^4.0.0", 6 + "markdown-it": "^14.1.0", 7 + "sass": "^1.85.1" 8 + }, 9 + "dependencies": { 10 + "@atcute/client": "^2.0.9" 11 + } 12 }
+12
pnpm-lock.yaml
··· 7 importers: 8 9 .: 10 devDependencies: 11 '@11ty/eleventy': 12 specifier: ^3.0.0 ··· 14 html-minifier: 15 specifier: ^4.0.0 16 version: 4.0.0 17 sass: 18 specifier: ^1.85.1 19 version: 1.85.1 ··· 58 59 '@11ty/recursive-copy@3.0.1': 60 resolution: {integrity: sha512-suoSv7CanyKXIwwtLlzP43n3Mm3MTR7UzaLgnG+JP9wAdg4uCIUJiAhhgs/nkwtkvsuqfrGWrUiaG1K9mEoiPg==} 61 62 '@isaacs/cliui@8.0.2': 63 resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} ··· 995 promise: 7.3.1 996 rimraf: 5.0.10 997 slash: 1.0.0 998 999 '@isaacs/cliui@8.0.2': 1000 dependencies:
··· 7 importers: 8 9 .: 10 + dependencies: 11 + '@atcute/client': 12 + specifier: ^2.0.9 13 + version: 2.0.9 14 devDependencies: 15 '@11ty/eleventy': 16 specifier: ^3.0.0 ··· 18 html-minifier: 19 specifier: ^4.0.0 20 version: 4.0.0 21 + markdown-it: 22 + specifier: ^14.1.0 23 + version: 14.1.0 24 sass: 25 specifier: ^1.85.1 26 version: 1.85.1 ··· 65 66 '@11ty/recursive-copy@3.0.1': 67 resolution: {integrity: sha512-suoSv7CanyKXIwwtLlzP43n3Mm3MTR7UzaLgnG+JP9wAdg4uCIUJiAhhgs/nkwtkvsuqfrGWrUiaG1K9mEoiPg==} 68 + 69 + '@atcute/client@2.0.9': 70 + resolution: {integrity: sha512-QNDm9gMP6x9LY77ArwY+urQOBtQW74/onEAz42c40JxRm6Rl9K9cU4ROvNKJ+5cpVmEm1sthEWVRmDr5CSZENA==} 71 72 '@isaacs/cliui@8.0.2': 73 resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} ··· 1005 promise: 7.3.1 1006 rimraf: 5.0.10 1007 slash: 1.0.0 1008 + 1009 + '@atcute/client@2.0.9': {} 1010 1011 '@isaacs/cliui@8.0.2': 1012 dependencies:
+49 -4
styles.scss
··· 14 padding: 8px; 15 } 16 17 - ul p { 18 - margin: 0; 19 - } 20 - 21 .mono { 22 font-family: "JetBrains Mono", monospace; 23 word-wrap: break-word; 24 } 25 26 h1 { 27 font-weight: 800; 28 font-size: 20px; ··· 59 color: black; 60 } 61 62 @media (prefers-color-scheme: light) { 63 body { 64 background: white; ··· 66 } 67 ::selection { 68 color: white; 69 } 70 } 71
··· 14 padding: 8px; 15 } 16 17 .mono { 18 font-family: "JetBrains Mono", monospace; 19 word-wrap: break-word; 20 } 21 22 + .nav { 23 + display: flex; 24 + justify-content: space-around; 25 + align-items: center; 26 + margin-bottom: 8px; 27 + font-weight: 600; 28 + span { 29 + font-weight: 800; 30 + } 31 + } 32 + 33 + .header { 34 + margin-top: 0; 35 + padding-bottom: 14px; 36 + margin-bottom: 14px; 37 + border-bottom: 1px dashed rgba(255, 255, 255, 0.25); 38 + h1 { 39 + font-size: 28px; 40 + margin: 0; 41 + } 42 + .date { 43 + font-size: 12px; 44 + font-weight: 600; 45 + opacity: 0.9; 46 + } 47 + } 48 + 49 h1 { 50 font-weight: 800; 51 font-size: 20px; ··· 82 color: black; 83 } 84 85 + .entry { 86 + display: flex; 87 + flex-direction: column; 88 + gap: 8px; 89 + margin-bottom: 16px; 90 + } 91 + .entry-title { 92 + font-size: 28px; 93 + font-weight: 800; 94 + } 95 + .entry-excerpt { 96 + font-size: 16px; 97 + opacity: 0.9; 98 + } 99 + .entry-date { 100 + font-size: 12px; 101 + font-weight: 600; 102 + } 103 + 104 @media (prefers-color-scheme: light) { 105 body { 106 background: white; ··· 108 } 109 ::selection { 110 color: white; 111 + } 112 + .header { 113 + border-bottom: 1px dashed rgba(0, 0, 0, 0.25); 114 } 115 } 116