First of all I sincerely apologize for bumping this thread. Full credit for this excellent script goes to TryNinja, who is the original creator and owner.
I recently shared a small update in another topic but I felt it was much more relevant to post it here. While TryNinja's original script works perfectly for copying quotes from within the forum, I have humbly tried to add a small feature to it. With this new implementation, if you copy any text from outside the forum, it will also be automatically formatted as a quote, I have provided a little detail about this addition below.

// ==UserScript==
// @name Universal Quick Quote with Text Fragment Formatter
// @version 1.0
// @description Copy selected text as a BBCode quote from Bitcointalk or any website
// @author TryNinja + PX-Z + Modified by Royal Cap
// @match *://*/*
// @icon https://bitcointalk.org/favicon.ico
// @grant GM_setClipboard
// @run-at document-end
// ==/UserScript==
(function () {
'use strict';
const btn = document.createElement('button');
Object.assign(btn.style, {
position: 'absolute',
display: 'none',
zIndex: '2147483647',
padding: '5px 10px',
background: '#e7eaef',
border: '1px solid #000',
borderRadius: '3px',
cursor: 'pointer',
fontSize: '11px',
fontWeight: 'bold',
boxShadow: '2px 2px 5px rgba(0,0,0,.2)',
color: '#000'
});
btn.textContent = '❝ Copy Quote';
document.body.appendChild(btn);
let selectedText = '', selectedPost = null;
const isBT = location.hostname.includes('bitcointalk.org');
const hide = () => btn.style.display = 'none';
function encode(text) {
return encodeURIComponent(text).replace(/'/g, '%27');
}
function fragment(text) {
const clean = text.replace(/\s+/g, ' ').trim();
const words = clean.split(' ');
if (words.length <= 8) return encode(clean);
return `${encode(words.slice(0, 4).join(' '))},${encode(words.slice(-4).join(' '))}`;
}
function date() {
const d = new Date();
const m = ['January','February','March','April','May','June','July','August','September','October','November','December'];
return `${m[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}`;
}
function findPost(node) {
if (!isBT || !node) return null;
if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;
return node?.closest('div.post') || null;
}
function author(post) {
const content = post?.closest('td.td_headerandpost');
const a = content?.previousElementSibling?.querySelector('b > a');
return a?.textContent.trim() || 'Unknown Author';
}
function postDate(post) {
const content = post?.closest('td.td_headerandpost');
const subject = content?.querySelector('div.subject');
const small = subject?.parentElement?.querySelector('.smalltext');
if (!small) return date();
let d = small.textContent.trim();
return d.startsWith('Today')
? d.replace('Today', date()).replace(' at ', ', ')
: d;
}
function postUrl(post) {
const content = post?.closest('td.td_headerandpost');
const link = content?.querySelector('div.subject a') ||
content?.querySelector('a[href*="#msg"]');
const url = link?.href || location.href;
const parts = url.split('#');
const base = parts[0].split(';')[0];
return parts[1] ? `${base}#${parts[1]}` : base;
}
function siteName() {
const meta = document.querySelector('meta[property="og:site_name"]');
if (meta?.content) return meta.content.trim();
return location.hostname
.replace(/^www\./, '')
.split('.')[0]
.replace(/[-_]/g, ' ')
.replace(/\b\w/g, c => c.toUpperCase());
}
document.addEventListener('mouseup', e => {
if (e.target === btn) return;
setTimeout(() => {
const selection = window.getSelection();
if (!selection?.rangeCount) return hide();
selectedText = selection.toString().trim();
if (!selectedText) return hide();
selectedPost = findPost(selection.anchorNode);
const rect = selection.getRangeAt(0).getBoundingClientRect();
if (!rect.width && !rect.height) return hide();
let left = scrollX + rect.left;
if (left + 120 > scrollX + innerWidth)
left = scrollX + innerWidth - 130;
btn.style.left = `${left}px`;
btn.style.top = `${scrollY + rect.bottom + 5}px`;
btn.style.display = 'block';
}, 10);
});
document.addEventListener('mousedown', e => {
if (e.target !== btn) hide();
});
btn.addEventListener('click', () => {
if (!selectedText) return;
try {
const f = fragment(selectedText);
let pageUrl = location.href.replace(/#:~:text=.*$/, '');
let url = `${pageUrl}#:~:text=${f}`;
let header;
if (isBT && selectedPost) {
const a = author(selectedPost);
const d = postDate(selectedPost);
url = `${postUrl(selectedPost)}#:~:text=${f}`;
header = `[url=${url}]${a} on ${d}[/url]`;
} else {
header = `[url=${url}]${siteName()}[/url]`;
}
const quote =
`[quote="${header}"]\n${selectedText}\n[/quote]`;
GM_setClipboard(quote);
btn.textContent = 'Copied!';
btn.style.background = '#dff0d8';
btn.style.color = '#3c763d';
setTimeout(() => {
btn.textContent = '❝ Copy Quote';
btn.style.background = '#e7eaef';
btn.style.color = '#000';
hide();
}, 1000);
} catch (err) {
console.error('[Quick Quote Error]', err);
btn.textContent = 'Error';
btn.style.background = '#f2dede';
btn.style.color = '#a94442';
setTimeout(() => {
btn.textContent = '❝ Copy Quote';
btn.style.background = '#e7eaef';
btn.style.color = '#000';
hide();
}, 1500);
}
});
})();