Skip to main content

📜 BookmarkLETS

This is a collection of JavaScript bookmarklets to assist in everyday life copy pasting.

Copies link to the current page in clipboard in Markdown format:

2023-03-12 [Hello from Dmytro Zharii | Dmytro Zharii](https://blog.zharii.com/)

2023-03-12 Hello from Dmytro Zharii | Dmytro Zharii

Name:

🥧 Copy as MD Link

Revision:

2023-03-12

Code:
javascript:(function() {
function showToast(message, textColor, backgroundColor) {
var toast = document.createElement("div");
toast.style.cssText = "position: fixed; top: 0; left: 0; background-color: " + backgroundColor + "; color: " + textColor + "; padding: 10px; font-family: Arial, Verdana; font-size: 16px; font-weight: bold; z-index: 9999; opacity: 0; transition: opacity 0.3s ease-in-out;";
toast.innerHTML = message;
document.body.appendChild(toast);
setTimeout(function() {
toast.style.opacity = 1;
}, 100);
setTimeout(function() {
toast.style.opacity = 0;
}, 3000);
}

document.body.focus();
var title = document.title;
/* remove [ and ] from title */
title = title.replace(/[\[\]]/g, ' ');

var url = window.location.href;
/* remove utm parameters from url */
url = url.replace(/utm_[^&]+&?/g, '');
/* remove final /? from url */
url = url.replace(/\/\?$/g, '/');
url = url.replace(/\?$/g, '/');

var date = new Date().toISOString().slice(0, 10);
var markdownLink = date + " [" + title + "](" + url + ")";
setTimeout(function() {
navigator.clipboard.writeText(markdownLink).then(function() {
showToast("Copied to clipboard", "lime", "#333");
}, function() {
showToast("Failed to copy to clipboard", "white", "darkred");
});
}, 100);
})();

RSS Feed Finder

Name:

📶 Find RSS

Revision:

2024-01-01

Code:
javascript:(async () => {
const pageUrl = document.location.href;

try {
const resp = await fetch(pageUrl);
const body = await resp.text();
const parser = new DOMParser();
const doc = parser.parseFromString(body, 'text/html');
const rssLinks = doc.querySelectorAll('link[type="application/rss+xml"]');
createDialog(Array.from(rssLinks).map(link => link.getAttribute('href')));
} catch (error) {
console.error('Error fetching page source:', error);
createDialog([]);
}

function createDialog(feedUrls) {
const dialog = document.createElement('div');
styleDialog(dialog, feedUrls.length > 0);
document.body.appendChild(dialog);

if (feedUrls.length > 0) {
const ul = document.createElement('ul');
feedUrls.forEach(url => {
const li = document.createElement('li');
li.textContent = url;
const copyBtn = createCopyButton(url);
li.appendChild(copyBtn);
ul.appendChild(li);
});
dialog.appendChild(ul);
} else {
dialog.textContent = 'No RSS Feed found';
setTimeout(() => fadeAndRemove(dialog), 3000);
}

const closeBtn = createCloseButton(dialog);
dialog.appendChild(closeBtn);
}

function styleDialog(dialog, hasFeeds) {
dialog.style.position = 'fixed';
dialog.style.top = '20px';
dialog.style.left = '50%';
dialog.style.transform = 'translateX(-50%)';
dialog.style.backgroundColor = hasFeeds ? 'green' : 'red';
dialog.style.padding = '20px';
dialog.style.zIndex = '10000';
dialog.style.color = 'white';
dialog.style.borderRadius = '5px';
dialog.style.fontSize = '16px';
}

function createCopyButton(text) {
const button = document.createElement('button');
button.textContent = 'Copy to Clipboard';
button.style.marginLeft = '10px';
button.onclick = () => {
navigator.clipboard.writeText(text).then(() => fadeAndRemove(button.parentElement.parentElement.parentElement));
};
return button;
}

function createCloseButton(dialog) {
const button = document.createElement('button');
button.textContent = 'Close';
button.style.display = 'block';
button.style.marginTop = '10px';
button.onclick = () => dialog.remove();
return button;
}

function fadeAndRemove(element) {
element.style.transition = 'opacity 0.5s';
element.style.opacity = '0';
setTimeout(() => element.remove(), 500);
}
})();

Content editable

Flips contentEditable on body to make copy-paste on laptop from keyboard easier.

Name:

🔛 Content Editable

Revision:

2023-03-12

Code:

javascript: document.body.contentEditable = (document.body.contentEditable === 'true') ? false : true;

Helpful for podcast sites

Name:

🧓 Silver Links

Revision:

2023-05-31

Code:

javascript:(function() {
var newStylesheet = document.createElement('style');
document.head.appendChild(newStylesheet);
newStylesheet.sheet.insertRule('a:visited { color: silver !important }', 0);
})();

Wake lock

Through the browser api, and while the current browser page is active, forces the screen to never lock or go sleep.

Name:

👀 Wake Lock

Revision:

2023-06-28

Code:

javascript:(async function() {
let statusElem = document.createElement('div');
statusElem.style.position = 'fixed';
statusElem.style.bottom = '0';
statusElem.style.right = '0';
statusElem.style.background = 'lightgray';
statusElem.style.padding = '10px';
document.body.appendChild(statusElem);

let wakeLock = null;
try {
wakeLock = await navigator.wakeLock.request('screen');
statusElem.textContent = 'Wake Lock is active!';
} catch (err) {
statusElem.textContent = `${err.name}, ${err.message}`;
}
})();

Export ChatGPT

Exports ChatGPT chat as HTML content into clipboard.

Name:

📤 Export ChatGPT

Revision:

2023-03-30

Code:
javascript: (() => {
const allItemsSelector = '.items-start';
const allItems = Array.from(document.querySelectorAll(allItemsSelector));

if (allItems.length === 0) {
console.error('Bookmarklet: No items found');
return;
}

console.log(allItems);

resultHtml = [];
let i = 0;
for (const element of allItems) {
i++;
if (i % 2 === 1) {
resultHtml.push(`<div class="bookmarklet-my-prompt"><pre>${element.textContent}</pre></div>`);
} else if (i % 2 === 0) {
resultHtml.push(`<div class="bookmarklet-chat-response">${element.innerHTML}</div>`);
} else {
console.error('Bookmarklet: Unknown element type:');
console.error(element);
}
}

const resultHtmlString = wrapHtml(resultHtml.join('\n'));

console.log('Bookmarklet: Result:');
console.log(resultHtmlString);

navigator.clipboard.writeText(resultHtmlString).then(() => {
console.log('Bookmarklet: Copied to clipboard');
showToast('Copied to clipboard', 'black', 'lightgreen');
}, (err) => {
console.error('Bookmarklet: Failed to copy to clipboard');
console.error(err);
showToast('Failed to copy to clipboard', 'white', 'brown');
});

function wrapHtml(html) {
const header = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>I am too lazy to set the title</title>
<style>

body {
font-family: Arial, sans-serif;
font-size: 20px;
line-height: 1.5;
color: #333;
}

article {
margin-left: 10%;
margin-right: 10%
}

h1, h2, h3 {
font-weight: bold;
}

h1 {
font-size: 2em;
}

h2 {
font-size: 1.5em;
}

h3 {
font-size: 1.17em;
}

p, ul, ol {
margin-bottom: 1.5em;
}

pre {
white-space: pre-wrap;
}

pre code {
display: block;
padding: .5em;
background-color: #f5f5f5;
border-radius: .3em;
}
.bookmarklet-my-prompt::first-letter {
font-size: 1.5rem;
font-weight: bold;
color: brown;
font-family: Georgia, 'Times New Roman', Times, serif
}

.bookmarklet-chat-response::first-letter {
font-size: 1.5rem;
font-weight: bold;
color: blue;
font-family: Georgia, 'Times New Roman', Times, serif
}

</style>
</head>
<body>
<article>
<h1>I am too lazy to set the title</h1>
`;

const footer = `
</article>
</body>
</html>`;
return header + "\n" + html + "\n" + footer;
}

function showToast(message, textColor, backgroundColor) {
var toast = document.createElement("div");
toast.style.cssText = "position: fixed; top: 0; left: 0; background-color: " + backgroundColor + "; color: " + textColor + "; padding: 10px; font-family: Arial, Verdana; font-size: 16px; font-weight: bold; z-index: 9999; opacity: 0; transition: opacity 0.3s ease-in-out;";
toast.innerHTML = message;
document.body.appendChild(toast);
setTimeout(function() {
toast.style.opacity = 1;
}, 100);
setTimeout(function() {
toast.style.opacity = 0;
}, 3000);
}
})();

Next, please!

Placeholder.