Personal Site
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 236 lines 6.3 kB view raw
1import BoxTlbr from "/assets/box-tlbr.png"; 2import Box4x3Mask from "/assets/box-4x3-mask.png"; 3import { experimental_AstroContainer } from "astro/container"; 4import Header from "/components/Header.astro"; 5 6const header = await experimental_AstroContainer 7 .create() 8 .then((x) => x.renderToString(Header)) 9 .then((x) => 10 // match data-astro-cid attributes where there no value 11 // this is because xml hates boolean attributes for some reason. :( 12 x.replaceAll(/data-astro-cid-[a-zA-Z0-9]*(?!=["'])/gm, (m) => m + '=""'), 13 ) 14 .then((x) => 15 // match wbr tags (with data astro cid) and close em 16 x.replaceAll(/<wbr data-astro-cid-[a-zA-Z0-9]*="">/gm, (m) => m + "</wbr>"), 17 ); 18 19export async function GET() { 20 return new Response( 21 ` 22<!DOCTYPE XSL [ <!ENTITY shy "­"> ]> 23<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 24 <xsl:output method="html" /> 25 26 <xsl:template match="/"> 27 <html lang="en"> 28 <head> 29 <title>RSS | vielle.dev</title> 30 <style> 31 :root { 32 font-family: sans-serif; 33 interpolate-size: allow-keywords; 34 image-rendering: pixelated; 35 } 36 37 * { 38 margin: 0; 39 padding: 0; 40 } 41 42 html, 43 body { 44 min-width: 30ch; 45 } 46 47 .blog { 48 width: 30ch; 49 margin: auto; 50 } 51 52 .intro { 53 max-width: 60ch; 54 padding-inline: 20px; 55 margin: 20px auto; 56 } 57 58 img, 59 svg, 60 iframe, 61 audio, 62 video { 63 max-width: 100%; 64 display: block; 65 } 66 67 .post { 68 border-image: url("${BoxTlbr.src}") 10 10 fill / 20px 20px round; 69 padding: 30px; 70 } 71 72 img { 73 width: 100%; 74 aspect-ratio: 4/3; 75 object-fit: cover; 76 mask-image: url("${Box4x3Mask.src}"); 77 mask-size: 100%; 78 } 79 80 a { 81 color: black; 82 text-decoration-line: none; 83 } 84 85 a:hover, 86 a:focus, 87 a:active { 88 text-decoration-line: underline; 89 } 90 91 a:active { 92 text-decoration-style: dashed; 93 } 94 95 /* from Header.astro */ 96 header { 97 border-image: var(--box-blr-png) 10 fill / 20px / 20px round; 98 margin: 0 20px 20px; 99 padding: 10px 20px; 100 height: 3rem; /* 2rem * 1.5 */ 101 /* render over feed bg */ 102 z-index: 2; 103 104 display: flex; 105 flex-direction: row; 106 justify-content: space-between; 107 align-items: center; 108 109 @media (max-width: 650px) { 110 flex-direction: column; 111 align-items: start; 112 height: 4.5rem; /* (2rem + 1rem) * 1.5 */ 113 114 nav { 115 margin-inline: auto; 116 contain: inline-size; 117 width: 100%; 118 overflow: auto; 119 scrollbar-width: thin; 120 } 121 122 h1 { 123 width: 100%; 124 text-align: center; 125 } 126 } 127 128 &amp; > nav > ul { 129 display: flex; 130 flex-direction: row; 131 align-items: center; 132 justify-content: start; 133 gap: 10px; 134 z-index: 999; 135 width: fit-content; 136 margin-inline: auto; 137 138 &amp; > li { 139 display: flex; 140 flex-direction: row; 141 align-items: center; 142 gap: 10px; 143 144 &amp;::marker { 145 content: none; 146 } 147 148 &amp; + &amp;::before { 149 content: ""; 150 background-image: var(--dot-png); 151 background-size: contain; 152 width: 9px; 153 height: 9px; 154 display: block; 155 } 156 } 157 } 158 } 159 160 nav > ul > li:last-child > details > ul { 161 right: 10px; 162 } 163 164 details { 165 summary { 166 cursor: pointer; 167 text-wrap: nowrap; 168 } 169 170 &amp; > ul { 171 position: absolute; 172 z-index: 99999; 173 174 @media (max-width: 650px) { 175 inset: auto 15px; 176 } 177 178 margin-top: 10px; 179 padding: 20px; 180 padding-left: 40px; 181 &amp; ul { 182 margin-left: 10px; 183 } 184 185 border-image: var(--box-tlbr-png) 10 fill / 20px round; 186 } 187 } 188 189 header h1 { 190 margin-block: 0; 191 position: sticky; 192 inset: 0; 193 } 194 </style> 195 </head> 196 197 <body> 198 ${header} 199 <section class="intro"> 200 <h1>Blog Posts</h1> 201 <p>If you want to use this page in your RSS reader, simply paste this page's URL in and it'll just work. To view the original RSS, view the page source. The styling of this page is made possible by <a href="https://developer.mozilla.org/en-US/docs/Web/XML/XSLT" target="_blank">XSLT</a></p> 202 </section> 203 <section class="blog"> 204 <xsl:for-each select="/rss/channel/item"> 205 <a target="_blank"> 206 <xsl:attribute name="href"> 207 <xsl:value-of select="link" /> 208 </xsl:attribute> 209 <article class="post"> 210 211 <img alt=""> 212 <xsl:attribute name="src"> 213 <xsl:value-of select="image" /> 214 </xsl:attribute> 215 </img> 216 217 <h2 class="title"><xsl:value-of select="title" /></h2> 218 <div class="bio"><xsl:value-of select="description" /></div> 219 <time><xsl:value-of select="pubDate" /></time> 220 221 </article> 222 </a> 223 </xsl:for-each> 224 </section> 225 </body> 226 </html> 227 </xsl:template> 228</xsl:stylesheet> 229 `, 230 { 231 headers: { 232 "Content-Type": "text/xml", 233 }, 234 }, 235 ); 236}