Reader Mode + Highlight + Translator + Webpage Editor button
// ==UserScript==
// @name Reader view + Editor button
// @namespace http://tampermonkey.net/
// @version 16.10.2025
// @description Reader Mode + Highlight + Translator + Webpage Editor button
// @author Copilot
// @match *://*/*
// @grant GM_registerMenuCommand
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
let readerOpened = false;
let editingEnabled = false;
GM_registerMenuCommand("Open Reader Mode", () => {
const btn = document.getElementById('tm-reader-btn');
if (btn) {
btn.click();
} else {
alert("Reader button not available yet.");
}
});
function injectButton() {
if (readerOpened) return;
if (document.getElementById('tm-reader-box')) return;
const readerBox = document.createElement('div');
readerBox.id = 'tm-reader-box';
const readerBtn = document.createElement('button');
readerBtn.id = 'tm-reader-btn';
readerBtn.textContent = 'Reader';
readerBox.appendChild(readerBtn);
const style = document.createElement('style');
style.textContent = `
#tm-reader-box {
position: fixed !important;
bottom: 10px !important;
right: 60px !important;
z-index: 2147483647 !important;
}
#tm-reader-btn {
border: none !important;
background: transparent !important;
color: #696969 !important;
font-size: 12px !important;
cursor: pointer !important;
font-family: system-ui, sans-serif !important;
}
#tm-reader-btn:hover { text-decoration: underline !important; }
`;
document.head.appendChild(style);
document.body.appendChild(readerBox);
readerBtn.addEventListener('click', openReaderMode);
}
async function openReaderMode() {
try {
const loadScript = url => new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = url;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
if (!window.Readability) {
await loadScript('https://cdn.jsdelivr.net/npm/@mozilla/[email protected]/Readability.js');
}
if (!window.DOMPurify) {
await loadScript('https://cdn.jsdelivr.net/npm/[email protected]/dist/purify.min.js');
}
const clone = document.cloneNode(true);
const article = new Readability(clone).parse();
if (!article) {
alert('Reader Mode: No article found on this page.');
return;
}
const readerBox = document.getElementById('tm-reader-box');
if (readerBox) readerBox.remove();
readerOpened = true;
const css = `
html, body { margin:0; padding:0; background:#fff; }
body {
font-family: system-ui, sans-serif !important;
max-width: 48rem;
margin: 0 auto;
padding: 2rem;
color: #111;
line-height: 1.6;
}
article *, article { font-size: 28px !important; }
img, video { max-width:100%; height:auto; border-radius:8px; margin:2rem auto; }
@media (prefers-color-scheme: dark) {
html, body { background:#111; }
body { color:#eee; }
}
`;
const html = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${article.title || 'Reader Mode'}</title>
<style>${css}</style>
</head>
<body>
<article>
<h1>${article.title || ''}</h1>
<div>${window.DOMPurify ? DOMPurify.sanitize(article.content) : article.content}</div>
</article>
</body>
</html>
`;
document.open();
document.write(html);
document.close();
// Highlight button reinjection
const btn = document.createElement('button');
btn.innerText = '🖍️';
btn.id = 'tm-highlight-btn';
btn.style.cssText = `
position: fixed; bottom: 20px; right: 20px;
z-index: 10000; padding: 10px; border-radius: 50%;
background-color: #ffeb3b; border: 2px solid #000;
font-size: 20px; display: none;
`;
document.body.appendChild(btn);
document.addEventListener('selectionchange', () => {
const selection = window.getSelection();
btn.style.display = (selection.toString().length > 0) ? 'block' : 'none';
});
btn.addEventListener('click', () => {
const selection = window.getSelection();
if (!selection.rangeCount) return;
const range = selection.getRangeAt(0);
const mark = document.createElement('mark');
mark.style.backgroundColor = 'yellow';
mark.style.color = 'black';
try {
range.surroundContents(mark);
selection.removeAllRanges();
btn.style.display = 'none';
} catch (e) {
alert("Can't highlight across multiple complex elements.");
}
});
// Reinject translator + editor after Reader Mode wipes DOM
injectTranslator();
injectEditorButton();
} catch (err) {
alert('Reader Mode failed: ' + err.message);
}
}
// Translator button injection
function injectTranslator() {
if (document.getElementById('google_translate_elm')) return;
const script = document.createElement('script');
script.src = '//translate.google.com/translate_a/element.js?cb=googleTranslate';
script.async = true;
document.head.appendChild(script);
const div = document.createElement('div');
div.id = 'google_translate_elm';
div.setAttribute('style', 'position:fixed;top:2px;left:6px;z-index:2147483647;');
document.documentElement.appendChild(div);
const style = document.createElement('style');
style.innerHTML = `
.skiptranslate iframe {display:none!important}
.goog-te-gadget-simple img {display:none!important}
.goog-te-gadget-icon {display: none!important}
.goog-te-gadget-simple {background:transparent!important;border:1px solid transparent!important;border-radius:6px!important;padding:6px 10px!important;font-size:12px!important;color:#696969!important}
.goog-te-gadget-simple span {color:#696969!important}
`;
document.head.appendChild(style);
window.googleTranslate = () => {
new google.translate.TranslateElement({
layout: google.translate.TranslateElement.InlineLayout.SIMPLE,
pageLanguage: 'auto',
includedLanguages: 'mr,en,hi,zh-CN'
}, 'google_translate_elm');
};
}
// Editor button injection
function injectEditorButton() {
if (document.getElementById('tm-editor-btn')) return;
const editorBtn = document.createElement('button');
editorBtn.id = 'tm-editor-btn';
editorBtn.textContent = '🖉';
editorBtn.style.cssText = `
position: fixed; top: 20px; right: 30px;
z-index: 2147483647; opacity: 0.5;
background: none; border: none; font-size: 20px;
cursor: pointer;
`;
editorBtn.title = 'Toggle Webpage Editor';
document.body.appendChild(editorBtn);
function enableEditing() {
document.body.contentEditable = 'true';
document.designMode = 'on';
editingEnabled = true;
}
function disableEditing() {
document.body.contentEditable = 'false';
document.designMode = 'off';
editingEnabled = false;
}
function toggleEditing() {
if (editingEnabled) disableEditing();
else enableEditing();
}
editorBtn.addEventListener('click', toggleEditing);
}
// Inject globally at load
window.addEventListener('load', () => {
injectButton();
injectTranslator();
injectEditorButton();
});
const observer = new MutationObserver(() => injectButton());
observer.observe(document.documentElement, { childList: true, subtree: true });
setInterval(injectButton, 2000);
})();