feat: initial commit
This commit is contained in:
commit
662a249ad3
192 changed files with 24641 additions and 0 deletions
45
public/_headers
Normal file
45
public/_headers
Normal file
|
@ -0,0 +1,45 @@
|
|||
/feeds/all.xml
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
x-content-type-options: nosniff
|
||||
|
||||
/feeds/books.xml
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
x-content-type-options: nosniff
|
||||
|
||||
/feeds/links.xml
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
x-content-type-options: nosniff
|
||||
|
||||
/feeds/posts.xml
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
x-content-type-options: nosniff
|
||||
|
||||
/feeds/movies.xml
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
x-content-type-options: nosniff
|
||||
|
||||
/feeds/syndication.xml
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
x-content-type-options: nosniff
|
||||
|
||||
/api/search
|
||||
Content-Type: application/json
|
||||
|
||||
/.well-known/webfinger
|
||||
Content-Type: application/jrd+json; charset=utf-8
|
||||
|
||||
/blogroll.opml
|
||||
Content-Disposition: attachment; filename=cory-dransfeldt-blogroll.opml
|
||||
|
||||
/music/releases.ics
|
||||
Content-Type: text/calendar
|
||||
Cache-Control: public, max-age=0, must-revalidate
|
||||
Access-Control-Allow-Origin: *
|
||||
Content-Disposition: inline; filename="releases.ics"
|
||||
|
||||
/*
|
||||
Content-Security-Policy: upgrade-insecure-requests; block-all-mixed-content;
|
||||
X-Frame-Options: DENY
|
||||
X-XSS-Protection: 1; mode=block
|
||||
Referrer-Policy: strict-origin-when-cross-origin, no-referrer-when-downgrade
|
||||
Permissions-Policy: autoplay=(), camera=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), publickey-credentials-get=()
|
83
public/_redirects
Normal file
83
public/_redirects
Normal file
|
@ -0,0 +1,83 @@
|
|||
# 404s
|
||||
/now.html /now 301
|
||||
/contact.html /contact 301
|
||||
|
||||
# feeds
|
||||
/feed.xml /feeds/posts 301
|
||||
/follow.xml /feeds/all 301
|
||||
/feeds/posts /feeds/posts.xml 301
|
||||
/feeds/posts.json /feeds/posts.xml 301
|
||||
/feeds/links /feeds/links.xml 301
|
||||
/feeds/links.json /feeds/links.xml 301
|
||||
/feeds/books /feeds/books.xml 301
|
||||
/feeds/books.json /feeds/books.xml 301
|
||||
/feeds/movies /feeds/movies.xml 301
|
||||
/feeds/movies.json /feeds/movies.xml 301
|
||||
/feeds/all /feeds/all.xml 301
|
||||
/feeds/all.json /feeds/all.xml 301
|
||||
/feeds/posts/ /feeds/posts 301
|
||||
/feeds/links/ /feeds/links 301
|
||||
/feeds/books/ /feeds/books 301
|
||||
/feeds/movies/ /feeds/movies 301
|
||||
/feeds/all/ /feeds/all 301
|
||||
|
||||
|
||||
# general
|
||||
/articles/ /posts/ 301
|
||||
/tags /search 301
|
||||
/sitemap.xml /sitemap-index.xml 301
|
||||
/watching/favorite-movies /watching/favorites/movies 301
|
||||
/watching/favorite-movies/ /watching/favorites/movies 301
|
||||
/watching/favorite-shows /watching/favorites/shows 301
|
||||
/watching/favorite-shows/ /watching/favorites/shows 301
|
||||
|
||||
# blog posts
|
||||
/blog/fixing-safari-icloud-syncing /posts/2022/fixing-safari-icloud-syncing/ 301
|
||||
/blog/migrating-to-fastmail /posts/2022/migrating-to-fastmail/ 301
|
||||
/blog/client-side-webmentions-in-nextjs /posts/2023/client-side-webmentions-in-nextjs/ 301
|
||||
/blog/apple-centric-digital-privacy-tools /posts/2022/apple-centric-digital-privacy-tools/ 301
|
||||
/blog/automating-rss-syndication-with-nextjs-github /posts/2023/automating-rss-syndication-with-nextjs-github/ 301
|
||||
/blog/apple-music-a-tale-of-woe /posts/2021/apple-music-a-tale-of-woe/ 301
|
||||
/blog/adding-client-side-rendered-webmentions-to-my-blog /posts/2023/client-side-webmentions-in-nextjs/ 301
|
||||
/blog/automating-email-cleanup-in-gmail /posts/2022/automating-email-cleanup-in-gmail/ 301
|
||||
/blog/fastmail-handling-inbound-email-with-regex-filters-now-with-chatgpt /posts/2023/fastmail-handling-inbound-email-with-regex-filters-now-with-chatgpt/ 301
|
||||
/blog/simple-api-fetch-hooks-with-swr /posts/2022/simple-api-fetch-hooks-with-swr/ 301
|
||||
/2023/02/automatingandprobablyoverengineeringmy-nowpage /posts/2023/automating-and-overengineering-my-now-page/ 301
|
||||
/2023/01/workflows-handling-inbound-email-on-fastmail-with-regular-expressions /posts/2023/fastmail-handling-inbound-email-with-regex-filters-now-with-chatgpt/ 301
|
||||
/posts/2023/i-block-ads/null /posts/2023/i-block-ads/ 301
|
||||
/posts/2023/i-dont-want-streaming-music/null /posts/2023/i-dont-want-streaming-music/ 301
|
||||
/posts/2022/migrating-to-fastmail/null /posts/2022/migrating-to-fastmail/ 301
|
||||
/posts/2023/webmentions-in-eleventy/null /posts/2023/webmentions-in-eleventy/ 301
|
||||
/posts/2023/a-safari-specific-guide-to-making-the-modern-web-suck-less/null /posts/2023/a-safari-specific-guide-to-making-the-modern-web-suck-less/ 301
|
||||
/posts/2024/dont-be-afraid-to-admit-when-you-dont-know-something/ /posts/2024/dont-be-afraid-to-admin-when-you-dont-know-something/ 301
|
||||
/posts/2024/data-sharing-should-always-be-opt-in/ /posts/2024/access-to-data-isnt-a-grant-to-exploit-it/ 301
|
||||
/posts/2023/popular-posts-widget-using-eleventy-plausible/ /posts/2023/building-a-popular-posts-widget-in-eleventy-using-plausible-analytics/ 301
|
||||
/posts/2023/i-dont-want-streaming-music/ /posts/2023/i-dont-want-streaming-music-i-just-want-to-stream-my-music/ 301
|
||||
/posts/2021/apple-music-a-tale-of-woe/ /posts/2022/apple-music-a-tale-of-woe/ 301
|
||||
/posts/2024/weaving-music-in-and-out-of-my-personal-site/ /posts/2024/weaving-music-data-in-and-out-of-my-personal-website/ 301
|
||||
/posts/2023/fastmail-handling-inbound-email-with-regex-filters-now-with-chatgpt/ /posts/2023/workflows-handling-inbound-email-on-fastmail-with-regular-expressions-now-featuring-chatgpt/ 301
|
||||
/-want-anything-your-ai-generates/ /posts/2024/i-dont-want-anything-your-ai-generates/ 301
|
||||
/posts/2023/default-apps-2023/ /posts/2023/my-default-apps-2023-edition/ 301
|
||||
/posts/2024/dont-be-afraid-to-admin-when-you-dont-know-something/ /posts/2024/dont-be-afraid-to-admin-when-you-dont-know-something/ 301
|
||||
/posts/2023/displaying-listening-data-from-apple-music-using-musickit/ /posts/2023/displaying-listening-data-from-apple-music-using-musickitjs/ 301
|
||||
/posts/2024/2024-minimalism-as-self-preservation/ /posts/2024/minimalism-as-self-preservation/ 301
|
||||
/posts/2023/client-side-webmentions-in-nextjs/ /posts/2023/adding-client-side-webmentions-to-my-nextjs-blog/ 301
|
||||
/posts/2024/2024-adblocker-required/ /posts/2024/adblocker-required/ 301
|
||||
/posts/2023/scheduled-eleventy-builds-cron-github-actions/ /posts/2023/scheduled-eleventy-builds-on-vercel-with-cron-triggered-github-actions/ 301
|
||||
/posts/2024/against-the-commercial-web/ /posts/2024/against-the-commercial-internet/ 301
|
||||
/posts/2023/i-removed-tailwind-from-my-site/ /posts/2024/i-removed-tailwind-from-my-site/
|
||||
/posts/2024/handling-images-with-b2-netlify-image-cdn-hazel-mountain-duck/ /posts/2024/handling-images-with-b2-netlifys-image-cdn-hazel-and-mountain-duck/ 301
|
||||
/posts/2023/my-default-apps-2023-edition/ /uses 301
|
||||
/posts/2024/link-blogging-using-readwise/ /posts/2024/link-blogging-using-readwise-reader/ 301
|
||||
/2022/12/automating-email-cleanup-in-gmail /posts/2022/automating-email-cleanup-in-gmail/ 301
|
||||
/posts/2023/automate-syndicate-content-mastodon-eleventy/ /posts/2023/automate-and-syndicate-content-from-eleventy-to-mastodon/ 301
|
||||
/posts/2023/road-to-madness-apple-music-charts/ /posts/2023/road-to-madness-charting-apple-music-listening-data/ 301
|
||||
/posts/2023/semi-automated-hashtags-syndicated-posts/ /posts/2023/semi-automated-hashtags-for-syndicated-posts/ 301
|
||||
/posts/2023/automating-rss-syndication-with-nextjs-github/ /posts/2023/automating-rss-syndication-and-sharing-with-nextjs-and-github/ 301
|
||||
/posts/2023/locally-stored-music-and-storage-as-a-meaningful-constraint/ /posts/2023/doppler-locally-stored-music-and-storage-as-a-beneficial-constraint/ 301
|
||||
/blog/digital-privacy-tools /posts/2021/digital-privacy-tools/ 301
|
||||
/posts/2023/now-page-update-matter-favorites/ /posts/2023/now-page-update-favorite-articles-from-matter/ 301
|
||||
/posts/2023/now-playing-eleventy-netlify-edge-functions-emoji/ /posts/2023/displaying-now-playing-data-with-matching-emoji-using-netlify-edge-functions-and-eleventy/ 301
|
||||
/posts/2014/sublime-text-ctrl-tab-key-bindings/ /posts/2014/sublime-text-3-ctrl-tab-key-bindings/ 301
|
||||
/posts/2022/simple-api-fetch-hooks-with-swr/ /posts/2022/simple-data-fetching-with-custom-react-hooks-and-swr/ 301
|
||||
/posts/2023/drying-up-now-page-templates-eleventy/ /posts/2023/drying-up-now-page-templates-and-normalizing-data-in-eleventy/ 301
|
5340
public/feeds/style.css
Normal file
5340
public/feeds/style.css
Normal file
File diff suppressed because it is too large
Load diff
78
public/feeds/style.xsl
Normal file
78
public/feeds/style.xsl
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
|
||||
<xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes" />
|
||||
<xsl:template match="/">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
||||
<head>
|
||||
<title><xsl:value-of select="/rss/channel/title" /> Web Feed</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
||||
<link rel="stylesheet" href="/feeds/style.css" type="text/css" />
|
||||
</head>
|
||||
<body class="bg-white">
|
||||
<nav class="container-md px-3 py-2 mt-2 mt-md-5 mb-5 markdown-body">
|
||||
<p class="bg-yellow-light ml-n1 px-1 py-1 mb-1">
|
||||
<strong>This is a web feed,</strong> also known as an RSS feed. <strong>Subscribe</strong>
|
||||
by copying the URL from the address bar into your newsreader. </p>
|
||||
<p class="text-gray"> Visit <a href="https://aboutfeeds.com">About Feeds</a> to get
|
||||
started with newsreaders and subscribing. It’s free. </p>
|
||||
</nav>
|
||||
<div class="container-md px-3 py-3 markdown-body">
|
||||
<header class="py-5">
|
||||
<h1 class="border-0">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
|
||||
style="vertical-align: text-bottom; width: 1.2em; height: 1.2em;" class="pr-1"
|
||||
id="RSSicon" viewBox="0 0 256 256">
|
||||
<defs>
|
||||
<linearGradient x1="0.085" y1="0.085" x2="0.915" y2="0.915" id="RSSg">
|
||||
<stop offset="0.0" stop-color="#E3702D" />
|
||||
<stop offset="0.1071" stop-color="#EA7D31" />
|
||||
<stop offset="0.3503" stop-color="#F69537" />
|
||||
<stop offset="0.5" stop-color="#FB9E3A" />
|
||||
<stop offset="0.7016" stop-color="#EA7C31" />
|
||||
<stop offset="0.8866" stop-color="#DE642B" />
|
||||
<stop offset="1.0" stop-color="#D95B29" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="256" height="256" rx="55" ry="55" x="0" y="0" fill="#CC5D15" />
|
||||
<rect width="246" height="246" rx="50" ry="50" x="5" y="5" fill="#F49C52" />
|
||||
<rect width="236" height="236" rx="47" ry="47" x="10" y="10" fill="url(#RSSg)" />
|
||||
<circle cx="68" cy="189" r="24" fill="#FFF" />
|
||||
<path d="M160 213h-34a82 82 0 0 0 -82 -82v-34a116 116 0 0 1 116 116z" fill="#FFF" />
|
||||
<path d="M184 213A140 140 0 0 0 44 73 V 38a175 175 0 0 1 175 175z" fill="#FFF" />
|
||||
</svg>
|
||||
Web Feed Preview </h1>
|
||||
<h2>
|
||||
<xsl:value-of select="/rss/channel/title" />
|
||||
</h2>
|
||||
<p>
|
||||
<xsl:value-of select="/rss/channel/description" />
|
||||
</p>
|
||||
<a class="head_link" target="_blank">
|
||||
<xsl:attribute name="href">
|
||||
<xsl:value-of select="/rss/channel/link" />
|
||||
</xsl:attribute> Visit
|
||||
Website → </a>
|
||||
</header>
|
||||
<h2>Recent Items</h2>
|
||||
<xsl:for-each select="/rss/channel/item">
|
||||
<div class="pb-5">
|
||||
<h3 class="mb-0">
|
||||
<a target="_blank">
|
||||
<xsl:attribute name="href">
|
||||
<xsl:value-of select="link" />
|
||||
</xsl:attribute>
|
||||
<xsl:value-of select="title" />
|
||||
</a>
|
||||
</h3>
|
||||
<small class="text-gray"> Published: <xsl:value-of select="pubDate" />
|
||||
</small>
|
||||
</div>
|
||||
</xsl:for-each>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
BIN
public/fonts/ml.woff2
Normal file
BIN
public/fonts/ml.woff2
Normal file
Binary file not shown.
BIN
public/fonts/mlb.woff2
Normal file
BIN
public/fonts/mlb.woff2
Normal file
Binary file not shown.
BIN
public/fonts/mlbi.woff2
Normal file
BIN
public/fonts/mlbi.woff2
Normal file
Binary file not shown.
BIN
public/fonts/mli.woff2
Normal file
BIN
public/fonts/mli.woff2
Normal file
Binary file not shown.
105
public/scripts/index.js
Normal file
105
public/scripts/index.js
Normal file
|
@ -0,0 +1,105 @@
|
|||
window.addEventListener("load", () => {
|
||||
// menu keyboard controls
|
||||
(() => {
|
||||
const menuInput = document.getElementById("menu-toggle");
|
||||
const menuButtonContainer = document.querySelector(
|
||||
".menu-button-container"
|
||||
);
|
||||
const menuItems = document.querySelectorAll(".menu-primary li");
|
||||
|
||||
menuButtonContainer.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
e.preventDefault();
|
||||
menuInput.checked = !menuInput.checked;
|
||||
}
|
||||
});
|
||||
|
||||
menuItems.forEach((item) => {
|
||||
item.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
e.preventDefault();
|
||||
item.querySelector("a").click();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Escape" && menuInput.checked) menuInput.checked = false;
|
||||
});
|
||||
})();
|
||||
|
||||
// modal keyboard controls and scroll management
|
||||
(() => {
|
||||
const modalInputs = document.querySelectorAll(".modal-input");
|
||||
if (!modalInputs) return;
|
||||
|
||||
const toggleBodyScroll = (disableScroll) => {
|
||||
if (disableScroll) {
|
||||
document.body.style.overflow = "hidden";
|
||||
} else {
|
||||
document.body.style.overflow = "";
|
||||
}
|
||||
};
|
||||
|
||||
const checkModals = () => {
|
||||
let isAnyModalOpen = false;
|
||||
modalInputs.forEach((modalInput) => {
|
||||
if (modalInput.checked) isAnyModalOpen = true;
|
||||
});
|
||||
toggleBodyScroll(isAnyModalOpen);
|
||||
};
|
||||
|
||||
modalInputs.forEach((modalInput) => {
|
||||
modalInput.addEventListener("change", checkModals);
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Escape") {
|
||||
modalInputs.forEach((modalInput) => {
|
||||
if (modalInput.checked) modalInput.checked = false;
|
||||
});
|
||||
toggleBodyScroll(false);
|
||||
}
|
||||
});
|
||||
|
||||
checkModals();
|
||||
})();
|
||||
|
||||
// text toggle for media pages
|
||||
(() => {
|
||||
const button = document.querySelector("[data-toggle-button]");
|
||||
const content = document.querySelector("[data-toggle-content]");
|
||||
const text = document.querySelectorAll("[data-toggle-content] p");
|
||||
const minHeight = 500; // this needs to match the height set on [data-toggle-content].text-toggle-hidden in text-toggle.css
|
||||
const interiorHeight = Array.from(text).reduce(
|
||||
(acc, node) => acc + node.scrollHeight,
|
||||
0
|
||||
);
|
||||
|
||||
if (!button || !content || !text) return;
|
||||
|
||||
if (interiorHeight < minHeight) {
|
||||
content.classList.remove("text-toggle-hidden");
|
||||
button.style.display = "none";
|
||||
return;
|
||||
}
|
||||
|
||||
button.addEventListener("click", () => {
|
||||
const isHidden = content.classList.toggle("text-toggle-hidden");
|
||||
button.textContent = isHidden ? "Show more" : "Show less";
|
||||
});
|
||||
})();
|
||||
|
||||
// pagination
|
||||
(() => {
|
||||
const dropdown = document.querySelector(".pagination select.client-side");
|
||||
|
||||
if (dropdown)
|
||||
dropdown.addEventListener("change", (event) => {
|
||||
const selectedOption = event.target.options[event.target.selectedIndex];
|
||||
const selectedHref = selectedOption.getAttribute("data-href");
|
||||
|
||||
if (selectedHref) window.location.href = selectedHref;
|
||||
});
|
||||
})();
|
||||
});
|
Reference in a new issue