Display backlink preview on hover
The combination of microformat2 h-entry and backlinks is potent. Each note page that’s marked up with a e-content
microformat2 property can be retrieved via fetch()
and displayed as a preview elsewhere on the site. No database required; the website is the API. With these two snippets you can implement dynamic backlink functionality on pretty much any webpage. With a little standardization (mostly complete by the microformat2 standard), one could support backlinks across websites. Woah!
First, here’s a snippet to retrieve a popup of an internal link’s comment. For each link marked with class="internal"
, the first three elements or less will be retrieved from its e-content
div element.
function parsePageContent(text) {
var bodyDOM = new DOMParser().parseFromString(text, 'text/html');
const contentElement = bodyDOM.querySelector('div.e-content');
if (contentElement) {
const elementCount = contentElement.childElementCount < 3 ? contentElement.childElementCount : 3;
const contentSlice = Array.from(contentElement.children).slice(0, elementCount);
if (elementCount < contentElement.childElementCount) {
const ellipsisElement = document.createElement('p');
ellipsisElement.innerText = '...';
contentSlice.push(ellipsisElement);
}
return contentSlice;
} else {
const missing = document.createElement('p');
missing.text = 'no content found';
return [missing];
}
}
function createPopup(offsetTop, offsetLeft, contentElements) {
const popup = document.createElement('div');
popup.classList.add('backlink-popup', 'hide');
popup.style.top = `${offsetTop + 20}px`;
popup.style.left = `${offsetLeft}px`;
contentElements.forEach((el) => popup.appendChild(el));
return popup;
}
function appendLinkPopup(link) {
fetch(link.href)
.then((resp) => {
if (resp.status === 200) {
return resp.text();
} else {
return null;
}
})
.then((text) => {
if (text === null) { return null; }
const contentElements = parsePageContent(text);
const popupElement = createPopup(link.offsetTop, link.offsetLeft, contentElements);
link.appendChild(popupElement);
});
}
// adds backlink popup as a hidden child element to all links marked internal
const internalLinks = document.querySelectorAll('a.internal');
internalLinks.forEach((link) => {
appendLinkPopup(link);
});
Second, here’s a snippet to populate the context of a backlink. For each link marked with class="backlink"
, the parent context of the link on the backlinked page will be appended to the link’s parent element.
function parsePageContext(text) {
var bodyDOM = new DOMParser().parseFromString(text, 'text/html');
var urlParts = document.URL.split('/');
var backlinkName = urlParts[urlParts.length - 2];
var backlinkElement = bodyDOM.getElementsByName(backlinkName)[0];
return backlinkElement.parentElement;
}
function appendSourceContent(link) {
fetch(link.href)
.then((resp) => {
if (resp.status === 200) {
return resp.text();
} else {
return null;
}
})
.then((text) => {
if (text === null) { return null; }
const contextElement = parsePageContext(text);
const wrapper = document.createElement('p');
wrapper.appendChild(contextElement);
link.parentElement.appendChild(wrapper);
});
}
// retrieves content from all backlinks that reference this page
const sourceLinks = document.querySelectorAll('a.backlink');
sourceLinks.forEach((link) => {
appendSourceContent(link);
});