Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save harryfear/2b11529f9264705bc19fc147db8df4ff to your computer and use it in GitHub Desktop.
Save harryfear/2b11529f9264705bc19fc147db8df4ff to your computer and use it in GitHub Desktop.
(function () {
// Install here: https://chriszarate.github.io/bookmarkleter/
// https://chat.openai.com/c/03d8944a-e0a4-4c8f-9074-037ab2497483
// https://www.bionize.app/
// https://chrome.google.com/webstore/detail/hyper-bold/bjicoipahmlimcmjoejgaoneibennoab
// https://stephanango.com/tidy
var readabilityTarget = 'div[id^="readability-"]';
var readSrc =
"https://cdn.rawgit.com/mozilla/readability/8525c6af/Readability.js";
var styles = `@media (prefers-color-scheme: dark) {:root {--background: #222;--text: white;--text-muted: #999;}}@media (prefers-color-scheme: light) {:root {--background: white;--text: black;--text-muted: #666;}}* {font-family: -apple-system, BlinkMacSystemFont, "Inter", "IBM Plex Sans", Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;}code, pre {font-family: IBM Plex Mono, monospace;font-size: calc(1rem + 0.5vw);}html {box-sizing: border-box;width: 100%;height: 100%;font-size: 62.5%;background-color: var(--background) !important;}body {font-size: calc(1.6rem + 0.5vw);line-height: 1.8;margin: 0 auto;width: 40em;max-width: 88%;color: var(--text);background-color: var(--background);}.page {margin: 2rem auto;background: var(--background);padding: 0 0 20rem 0;}h1 {font-size: 44px !important;letter-spacing: -0.5px !important;line-height: 46px !important;margin: 22px 0 15px 0 !important;}h2 {font-size: 35px;line-height: 38px;font-weight: bold;}h3 {font-size: inherit;font-weight: bold;border-bottom: 1px solid #333;}ul {margin: 1rem;}ol {margin: 1rem;}video, img {max-width: 100%;}a {color: var(--text);text-decoration: underline;}a:visited {opacity: 0.6;color: var(--text-muted);}blockquote {margin: 0;padding: 0.1em 0 0.1em 2em;border-left: 2px solid #ccc;color: var(--text-muted);}pre {background-color: #ccc;padding: 1rem;}code {color: var(--text-muted);}pre > code {color: #333;} .noselect { user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; }`;
// Added no-select
function copyToClipboard(text) {
var textarea = document.createElement("textarea");
textarea.value = text;
document.body.appendChild(textarea);
textarea.select();
document.execCommand("copy");
document.body.removeChild(textarea);
}
function applyTransition() {
var elements = Array.from(document.body.children);
elements.forEach((element) => {
element.style.transition = "opacity 0.3s";
});
setTimeout(() => {
elements.forEach((element) => {
element.style.opacity = "0";
});
}, 0);
setTimeout(() => {
elements.forEach((element) => {
element.style.opacity = "1";
});
}, 300);
}
function boldFirstPart(text) {
return text.replace(/(\b\w{1,2})(\w*)/g, "<span data-bold='1'>$1</span>$2");
}
function emboldenDOMNode(node) {
if (node.nodeType === Node.TEXT_NODE) {
let newNode = document.createElement("span");
newNode.innerHTML = boldFirstPart(node.textContent);
node.replaceWith(newNode);
} else if (
node.nodeType === Node.ELEMENT_NODE &&
node.nodeName !== "SCRIPT" &&
node.nodeName !== "STYLE"
) {
for (let child of node.childNodes) {
emboldenDOMNode(child);
}
}
}
function addEmboldenFallbackStyles() {
let style = document.createElement("style");
style.type = "text/css";
style.id = "fallback-styles";
style.innerHTML = "span[data-bold] { font-weight: bold !important; }";
document.head.appendChild(style);
}
function doubleTapHandler(element, callback) {
let touchstartX = 0;
let touchstartY = 0;
let prevTouchTime;
let threshold = 300; // time threshold for double tap (in ms)
element.addEventListener("touchstart", function (event) {
if (event.timeStamp - prevTouchTime < threshold) {
this.classList.add("noselect");
setTimeout(() => this.classList.remove("noselect"), 500);
callback();
}
prevTouchTime = event.timeStamp;
touchstartX = event.changedTouches[0].screenX;
touchstartY = event.changedTouches[0].screenY;
});
}
function init() {
var jsCode = document.createElement("script");
jsCode.setAttribute("src", readSrc);
jsCode.onload = function () {
var loc = document.location;
var uri = {
spec: loc.href,
host: loc.host,
prePath: loc.protocol + "//" + loc.host,
scheme: loc.protocol.substr(0, loc.protocol.indexOf(":")),
pathBase:
loc.protocol +
"//" +
loc.host +
loc.pathname.substr(0, loc.pathname.lastIndexOf("/") + 1),
};
function doReadabilityWithPromise(uri, document) {
return new Promise((resolve) => {
var article = new Readability(uri, document).parse();
document.children[0].innerHTML = article.content;
resolve(article);
});
}
doReadabilityWithPromise(uri, document).then((article) => {
var divs = document.querySelectorAll(readabilityTarget);
let text = "";
divs.forEach((div) => {
text += div.innerText + "\n\n";
});
function shorten(inputString, maximumLength) {
var words = inputString.split(" ");
if (words.length > maximumLength) {
return words.slice(0, maximumLength).join(" ");
} else {
return inputString;
}
}
// Inline shorten function
text = shorten(text, 1999);
copyToClipboard(text);
//console.log(text);
applyTransition();
var tidyStyle = document.createElement("style");
tidyStyle.innerText = styles;
document.head.appendChild(tidyStyle);
addEmboldenFallbackStyles();
emboldenDOMNode(document.body);
let readabilityTargets = document.querySelectorAll(readabilityTarget);
readabilityTargets.forEach((target) => {
target.addEventListener("dblclick", function () {
this.classList.add("noselect");
setTimeout(() => this.classList.remove("noselect"), 500);
let styleElement = document.querySelector("#fallback-styles");
if (styleElement) {
styleElement.remove();
} else {
addEmboldenFallbackStyles();
}
});
doubleTapHandler(target, function () {
let styleElement = document.querySelector("#fallback-styles");
if (styleElement) {
styleElement.remove();
} else {
addEmboldenFallbackStyles();
}
});
});
}); // End doReadabilityWithPromise
}; // End JS loaded callback
// Begin loading the JS
document.body.appendChild(jsCode);
}
console.clear();
init();
return Date.now();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment