Smooth corners with CSS mask-border images
Here’s a side by side comparison of the effect I’m taking about:
It’s a subtle effect but it does look a lot better to me. Unforunately this is only supported on Chromium and WebKit at the time of writing.
The code looks something like this
@utility smooth-md {
-webkit-mask-box-image-width: 60px;
mask-border-width: 60px;
mask-border: url(data:image/png;...);
-webkit-mask-box-image: url(data:image/png;...);
}
They should just add this to css already.
The Link Component
<Link href="https://..." external>text</Link>
The link component is just a standard wrapper around the <a>
tag, and adds a nice little arrow when it’s external.
The fun part is when I have to replace all the instances of <a>
with the proper <Link>
component when rendering the markdown. So I wrote a slightly cursed plugin to do so.
export default function linkToComponent() {
return (tree) => {
if (
!tree.children.some(
(el) => el.value?.includes("import Link from '@/components/common/Link.astro'") && el.type === 'mdxjsEsm',
)
) {
tree.children.unshift({
type: 'mdxjsEsm',
value: "import Link from '@/components/common/Link.astro';",
data: { ... },
});
}
for (const child of tree.children) { recursiveWalk(child); }
return tree;
};
}
function recursiveWalk(element) {
if (element.type === 'element' && element.tagName === 'a') {
const href = element.properties.href;
const isExternal = !href.startsWith('/');
element.type = 'mdxJsxFlowElement';
element. ... = ...; // etc
if (isExternal) {
element.attributes.push({
type: 'mdxJsxAttribute',
name: 'external',
value: null,
});
}
} else if (element.children) {
for (const child of element.children) {
recursiveWalk(child);
}
}
}
This walks the AST parsed from rehype(?) and replaces all <a>
tags with the <Link>
component. It also adds the external
prop if the link is external. The plugin is a bit of a mess, but it works for now. I also had to shove in the import statement for the link component in its AST form.
Fade by element
The last other plugin I use is for the animation delay on each element in the blog. I use a simple fade in animation, and I wanted to stagger the animation for each element. So I wrote a plugin that edits the style for each element in the tree.
export default function rehypeAnimationDelay() {
return (tree) => {
let index = 1;
tree.children.forEach((child) => {
if (child.type === 'element') {
const delay = Math.min(20 * 50, index * 50);
if (child.properties) {
child.properties.style = `${child.properties?.style || ''}animation-delay: ${delay}ms;`;
index += 1;
}
}
});
return tree;
};
}
To be honest, I don’t love writing specific plugins like this, not only is it in JavaScript(so untyped), but it also feels like it could break easily.
The contact me section
I have an api hosted on vercel that spins up a discord bot to send a message with the contents. It was shockingly simple to do. The api is also written in rust, which I didn’t think you could host on vercel.
You can view the code here