Expand One Line Links ๐

Search for a command to run...

Waylon Walker the article is broken. Good content.
Thanks for the heads up, fixed now!
I've slowly adding more and more lua functions into my neovim configuration, and recently I noticed a pattern for a class of functions that reach out to run shell commands that can be abstracted away. https://youtu.be/8m5ipBuopPU Telegraph.nvim Check...

Kedro can have a chatty logger. While this is super nice in production so see everything that happened during a pipeline run. This can be troublesome

In 2021 I changed the way I navigate between tmux sessions big time. Now I can create, kill, switch with ease, and generally keep work separated into
People who are quick to toss team members under a bus are not well trusted or highly thought of and it will lead to some toxic team dynamics. Building Steam While collaborating on any project there are going to be decisions made that aren't necessari...

I create this blog with one person in mind, me. There are others like me This is not completely selfish, as there are likely many others out there that think similarly to me. Everyone comes from different backgrounds and varying levels of experience...

I wanted a super simple way to cross-link blog posts that require as little effort as possible, yet still looks good in vanilla markdown in GitHub. I have been using a snippet that puts HTML into the markdown. While this works, it's more manual/difficult for me does not look the best, and does not read well as
The new card should be fully automated to expand with title, description, and cover image. Bonus if I am able to attach a comment behind it.
If you can call it a card ๐คฃ. This card was just an image wrapped in an anchor tag and a paragraph tag. I found this was the most consistent way to get an image narrower and centered in both GitHub and dev.to.
<p style='text-align: center'>
<a href='https://waylonwalker.com/notes/eight-years-cat'>
<img
style='width:500px; max-width:80%; margin: auto;'
src="https://waylonwalker.com/eight-years-cat.png"
alt="My first eight years as a working professional article"
/>
</a>
</p>
The key here is that I have to put the HTML into the markdown. It looks a bit dirty while editing and quite frankly it's a pain to deal with.
<a class="onelinelink" href="https://waylonwalker.com/eight-years-cat/">
<img style="float: right;" align='right' src="https://waylonwalker.com/static/29cdf6fcfb17d7fd766fc438144fb3e4/630fb/eight-years-cat-xmas2020.png" alt="article cover for My first eight years as a working professional.">
<div class="right">
<h2>My first eight years as a working professional.</h2>
<p class="description">
This day 8 years ago I started my first day as a Mechanical Engineer. I am so grateful for this journey that I have been able to have. There is no way that I could have planned this journey from the beginning.
</p>
<p class="url">
<span class="read-more">read more</span> waylonwalker.com
</p>
</div>
</a>
My first attempt was to make my own transformer for gatsby-remark-embedder. I previously set this up on my site for Twitter and YouTube. I tried to get some custom transformers going, to do what I wanted for my own website, but failed. I really struggled to understand what data was coming in and out of the transformer. My lack of js/node debugging skills was really showing.
using gatsby-remark-embedder to expand Twitter/YouTube
It also works with redirects. I have a redirect to my "latest" post. It's something that I don't do the best job at keeping up to date, but when I feel really proud of a post I make it the latest.
this post is a redirect to my "latest post"
I started out by running this card expansion client side. This was the strategy that I used to find the list of elements that should be transformed.
shouldTransformoneLineLinkCard applied.const oneLineLinks = () => {
const linkText = [...document.querySelectorAll('.post-body p a')].map(
(p) => p.innerText
)
const paragraphs = document.querySelectorAll('.post-body p') //
const regex = /^https?:\/\/waylonwalker\.com\//
const shouldTransform = (url) => regex.test(url)
const anchorOnly = [...paragraphs].filter(
(p) => linkText.includes(p.innerText) && p.childElementCount === 1
)
anchorOnly
.filter((p) => shouldTransform(p.firstElementChild.href))
.map(
async (p) =>
(p.outerHTML = await oneLineLinkCard(p.firstElementChild.href))
)
}
CSS is not my strong suit, but I can generally hammer something into a shape that I am happy with. For this one, I did struggle a bit with how it looked on various screens, particularly because I was holding the cover image size to a hard 300px. I ended up with more media queries than I needed, but it works.
.onelinelink + blockquote {
position: relative;
left: 2rem;
background: rgba(0, 0, 0, .2);
margin: -6rem auto 1rem;
padding-top: 3rem;
border: 1px solid goldenrod;
border-top: 2px solid goldenrod;
max-width: 300px;
@media (max-width: 350px) {
left: 0rem;
margin-left: .4rem;
margin-right: .4rem;
}
@media (min-width: 800px) {
max-width: 600px;
}
@media (min-width: 900px) {
max-width: 700px;
}
@media (min-width: 1000px) {
max-width: 800px;
}
border-radius: 15px/45px;
display: block;
}
}
.onelinelink {
position: relative;
z-index: 2;
margin: 4rem;
overflow: hidden;
display: flex;
border: 2px solid rgba(255, 50, 50, .1);
background: rgba(255, 50, 50, .015);
background: #262236;
text-decoration: none;
border-radius: 8px;
max-height: 126px;
@media (max-width: 800px) {
flex-direction: column;
max-height: 800px;
max-width: 300px;
margin: 4rem auto;
}
h2 {
top: -1.2rem;
postition: relative;
margin: 0;
padding: 0;
font-size: .8rem;
font-weight: 400;
}
.right {
width: 100%;
padding: 5px 15px;
}
.description {
font-size: 1rem;
line-height: 1.2rem;
height: calc(100% - 31px - 1rem);
padding: 0;
padding-bottom: 1rem;
padding-top: .1rem;
margin: 0;
}
.url {
padding-right: 30px;
color: rgba(255, 255, 255, .1);
text-align: right;
position: relative;
z-index: 2;
background: #262236;
}
img {
max-width: 300px;
max-height: 126px;
padding: 0;
margin: 0;
border-radius: 8px 0 0 8px;
}
.read-more {
font-size: .6rem;
color: rgba(255, 255, 255, .08);
}
}
On mobile, it renders vertically.

On desktop, it renders horizontally.

I'm sure that all of this can be better, my js skills are still forming. It's quite humbling to see how hard it is to think in an unfamiliar language. The following oneLineLineCard renders a string template literal from a paragraph with a single anchor to a card that contains some of that pages meta information. The getDescription function uses a fetch to get the metadata right from the content of the page.
const getDescription = (url) =>
fetch(url)
.then((r) => r.text())
.then((html) => {
let parser = new DOMParser()
let doc = parser.parseFromString(html, 'text/html')
let meta = doc.querySelectorAll('meta')
const description = [...meta].filter(
(m) => m.name === 'og:description'
)[0].content
const image = [...meta].filter((m) => m.name === 'og:image')[0]?.content
const sm_image = [...meta].filter((m) => m.name === 'og:sm_image')[0]
?.content
const url = [...meta].filter((m) => m.name === 'og:url')[0]?.content
const title = [...meta].filter((m) => m.name === 'title')[0]?.content
return { description, image, url, title, sm_image }
})
const oneLineLinkCard = (url) => {
return getDescription(url).then(
(meta) =>
`<a class="onelinelink" href=${meta.url}>
<img src='${meta.sm_image ? meta.sm_image : meta.image ? meta.image : ''}' alt='cover image for ${meta.title ? meta.title : ''}>
<div class="right">
<h2>${meta.title ? meta.title : ''}</h2>
<p class='description'>
${meta.description ? meta.description : ''}
</p>
<p class="url">
<span class='read-more'>read more</span> waylonwalker.com
</p>
</div>
</a>
`
)
}
And it works. Whenever I reference my own blog with just a single link on a line in markdown I get a nice card link out to the other post, with a small image sized for the card, the title, and the description of the post.
For every link I do this with the client will pull the full page just to get a bit of metadata. I am already doing a bit more than I want to do client-side for a blog, so I would prefer to do it ahead of time.
Additionally, since it is done client-side it does not translate well when I copy my markdown to various other blogging platforms. If it were rendered right into the markdown cross-posting would be much easier.
actually already implemented at this point
The direction I am going to try is to use python to load each post, look for lines that contain only a link, then render this same markup right in the markdown. For this I am going to use a language I am more familiar with, python, and do this inside of GitHub actions just before build time so that the markdown I write stays the same, the cards will only be rendered in prod.
Python is my every day what I know, I work much more efficiently and cleanly with it. Also the more I blog the more abstractions I am seeing and the lazier I am getting. Things like description, SEO, cover images are all getting automated. Gatsby really doesn't like to run when some of those things are missing, probably due to my lack of JS error handling skills. I find it much easier to load up all the pages and patch up the frontmatter in python before build time.
I am kinda curious if eventually, I can re-create everything I need in python because I am honestly not using react for much more than a glorified templating system, besides search. If I can pre-render everything in python
Do they look good? Could they be better?