您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
复制网页上的 LaTeX 公式(CSDN,zhihu,wiki)
当前为
// ==UserScript== // @name Copy LaTeX Formula 1.1 // @namespace http://tampermonkey.net/ // @version 1.0 // @description 复制网页上的 LaTeX 公式(CSDN,zhihu,wiki) // @author shezhao // @match *://*/* // @match https://www.zhihu.com/question/* // @match https://zhuanlan.zhihu.com/p/* // @match https://blog.csdn.net/*/article/* // @match https://*.wikipedia.org/* // @match https://www.wikiwand.com/* // @license MIT // @grant none // ==/UserScript== // 鸣谢 // https://greasyfork.org/zh-CN/scripts/397740 // 参考了wiki部分 https://github.com/flaribbit/click-to-copy-equations (function() { 'use strict'; const host = document.location.host; class zhihuLaTeXFormulaCopier { constructor(elementSelector = 'span.ztext-math') { this.elementSelector = elementSelector; this.contextMenu = this.createContextMenu(); this.addEventListeners(); } createContextMenu() { const contextMenu = document.createElement('div'); contextMenu.style.display = 'none'; contextMenu.style.position = 'absolute'; contextMenu.style.backgroundColor = 'white'; contextMenu.style.border = '1px solid black'; contextMenu.style.padding = '5px'; contextMenu.style.zIndex = '10000'; const copyOption = document.createElement('div'); copyOption.textContent = 'Copy LaTeX Formula'; copyOption.style.cursor = 'pointer'; copyOption.style.padding = '5px'; copyOption.addEventListener('click', () => { const formula = this.getSelectedFormula(); if (formula) { console.log('Formula to be copied:', formula); this.copyToClipboard(formula); } else { console.log('No formula found'); } this.hideContextMenu(); }); contextMenu.appendChild(copyOption); document.body.appendChild(contextMenu); return contextMenu; } showContextMenu(x, y) { if (this.contextMenu) { this.contextMenu.style.left = `${x}px`; this.contextMenu.style.top = `${y}px`; this.contextMenu.style.display = 'block'; console.log('Context menu shown at:', x, y); } } hideContextMenu() { if (this.contextMenu) { this.contextMenu.style.display = 'none'; console.log('Context menu hidden'); } } getSelectedFormula() { const selection = window.getSelection(); if (selection.rangeCount > 0) { const range = selection.getRangeAt(0); const startNode = range.startContainer; const endNode = range.endContainer; const latexElements = document.querySelectorAll(this.elementSelector); console.log('Found latex elements:', latexElements.length); for (const element of latexElements) { if (element.contains(startNode) && element.contains(endNode)) { const formula = element.getAttribute('data-tex'); console.log('Selected formula:', formula); return '$' + formula + '$'; // 在这里添加 $ 符号 } } } console.log('No formula selected'); return null; } copyToClipboard(text) { navigator.clipboard.writeText(text) .then(() => { console.log('Copied to clipboard:', text); if (!DEFAULT_COPY){ alert('已复制到剪贴板'); } }) .catch((error) => { console.error('Failed to copy to clipboard:', error); if (!DEFAULT_COPY){ alert('复制失败'); } }); } addEventListeners() { document.addEventListener('contextmenu', (event) => { event.preventDefault(); const clickedElement = event.target; this.highlightElement(clickedElement); const latexElement = this.findClosestLatexElement(clickedElement); if (latexElement) { const formula = latexElement.getAttribute('data-tex'); if (formula) { console.log('Formula found in clicked element:', formula); if (!DEFAULT_COPY) { let shouldCopy = window.confirm('是否要复制这个公式?'); if (shouldCopy) { this.copyToClipboard('$' + formula + '$'); // 在这里添加 $ 符号 } } else{ this.copyToClipboard('$' + formula + '$'); // 在这里添加 $ 符号 } } else { console.log('No formula found in clicked element'); } } else { console.log('No ztext-math element found in clicked area'); } this.showContextMenu(event.pageX, event.pageY); }); document.addEventListener('click', () => { this.hideContextMenu(); this.removeHighlight(); }); } findClosestLatexElement(element) { let currentElement = element; while (currentElement) { if (currentElement.classList && currentElement.classList.contains('ztext-math')) { return currentElement; } currentElement = currentElement.parentElement; } return null; } highlightElement(element) { this.removeHighlight(); element.style.border = '2px solid red'; this.highlightedElement = element; } removeHighlight() { if (this.highlightedElement) { this.highlightedElement.style.border = ''; this.highlightedElement = null; } } } class csdnKatexFormulaCopier { constructor(elementSelector = 'span.katex-mathml') { this.elementSelector = elementSelector; this.contextMenu = this.createContextMenu(); this.addEventListeners(); } createContextMenu() { const contextMenu = document.createElement('div'); contextMenu.style.display = 'none'; contextMenu.style.position = 'absolute'; contextMenu.style.backgroundColor = 'white'; contextMenu.style.border = '1px solid black'; contextMenu.style.padding = '5px'; contextMenu.style.zIndex = '10000'; const copyOption = document.createElement('div'); copyOption.textContent = 'Copy LaTeX Formula'; copyOption.style.cursor = 'pointer'; copyOption.style.padding = '5px'; copyOption.addEventListener('click', () => { const formula = this.getSelectedFormula(); if (formula) { console.log('Formula to be copied:', formula); this.copyToClipboard(formula); } else { console.log('No formula found'); } this.hideContextMenu(); }); contextMenu.appendChild(copyOption); document.body.appendChild(contextMenu); return contextMenu; } showContextMenu(x, y) { if (this.contextMenu) { this.contextMenu.style.left = `${x}px`; this.contextMenu.style.top = `${y}px`; this.contextMenu.style.display = 'block'; console.log('Context menu shown at:', x, y); } } hideContextMenu() { if (this.contextMenu) { this.contextMenu.style.display = 'none'; console.log('Context menu hidden'); } } getSelectedFormula() { const selection = window.getSelection(); if (selection.rangeCount > 0) { const range = selection.getRangeAt(0); const startNode = range.startContainer; const endNode = range.endContainer; const katexElements = document.querySelectorAll(this.elementSelector); console.log('Found katex elements:', katexElements.length); for (const element of katexElements) { if (element.contains(startNode) && element.contains(endNode)) { const formula = element.textContent; // 处理公式 以换行符分隔,获取最后一个公式 const formulas = formula.split('\n'); formula = formulas[formulas.length - 1]; if (!formula) { if (formulas.length < 2) { console.log('No formula found'); return null; } formula = formulas[formulas.length - 2]; } console.log('Selected formula:', formula); return '$' + formula + '$'; } } } console.log('No formula selected'); return null; } copyToClipboard(text) { navigator.clipboard.writeText(text) .then(() => { console.log('Copied to clipboard:', text); if (!DEFAULT_COPY) { alert('已复制到剪贴板'); } }) .catch((error) => { console.error('Failed to copy to clipboard:', error); if (!DEFAULT_COPY) { alert('复制失败'); } }); } addEventListeners() { document.addEventListener('contextmenu', (event) => { event.preventDefault(); const clickedElement = event.target; const katexElement = this.findClosestKatexElement(clickedElement); if (katexElement) { const formula = katexElement.textContent; if (formula) { console.log(typeof formula); // 将公式按换行符分割 const formulas_origin = formula.split("\n"); let formula_text = ""; let maxLength = 0; for (let i = 0; i < formulas_origin.length; i++) { // 修剪每个公式的首尾空白 const trimmedFormula = formulas_origin[i].trim(); // 检查修剪后的公式是否不为空且长度大于当前最大长度 if (trimmedFormula.length > 0 && trimmedFormula.length > maxLength) { formula_text = trimmedFormula; maxLength = trimmedFormula.length; } } console.log('在点击的元素中找到的公式:', formula_text); if(!DEFAULT_COPY) { let shouldCopy = window.confirm('是否要复制这个公式?'); if (shouldCopy) { this.copyToClipboard('$' + formula_text + '$'); } } else { this.copyToClipboard('$' + formula_text + '$'); } } else { console.log('No formula found in clicked element'); } } else { console.log('No katex-mathml element found in clicked area'); } this.showContextMenu(event.pageX, event.pageY); }); document.addEventListener('click', () => { this.hideContextMenu(); }); } findClosestKatexElement(element) { let currentElement = element; while (currentElement) { if (currentElement.classList && currentElement.classList.contains('katex-mathml')) { return currentElement; } // 检查父元素的同级元素 let sibling = currentElement.previousElementSibling; while (sibling) { if (sibling.classList && sibling.classList.contains('katex-mathml')) { return sibling; } sibling = sibling.previousElementSibling; } sibling = currentElement.nextElementSibling; while (sibling) { if (sibling.classList && sibling.classList.contains('katex-mathml')) { return sibling; } sibling = sibling.nextElementSibling; } currentElement = currentElement.parentElement; } return null; } } // 用于复制维基百科和 Wiki 上的公式 class WikiTeXFormulaCopier { constructor() { this.init(); } init() { if (host.search('wikipedia') >= 0) { this.setupWikipedia(); } else if (host.search('wikiwand') >= 0) { this.setupWikiwand(); } } clearAnimation(event) { event.target.style.animation = ''; } setupWikipedia() { const copyTex = function () { if(!DEFAULT_COPY) { if (confirm('是否复制该公式?')) { navigator.clipboard.writeText('$' + this.alt + '$'); this.style.animation = 'aniclick .2s'; } } else { navigator.clipboard.writeText('$' + this.alt + '$'); this.style.animation = 'aniclick .2s'; } } const eqs = document.querySelectorAll('.mwe-math-fallback-image-inline, .mwe-math-fallback-image-display'); for (let i = 0; i < eqs.length; i++) { eqs[i].onclick = copyTex; eqs[i].addEventListener('animationend', this.clearAnimation); eqs[i].title = '点击即可复制公式'; } } setupWikiwand() { const copyTex = function () { const tex = this.getElementsByTagName('math')[0].getAttribute("alttext"); if(!DEFAULT_COPY) { if (confirm('是否复制该公式?')) { navigator.clipboard.writeText('$' + tex + '$'); this.style.animation = 'aniclick .2s'; } } else { navigator.clipboard.writeText('$' + tex + '$'); this.style.animation = 'aniclick .2s'; } } const check_equations = (mutationList, observer) => { const eqs = document.querySelectorAll('.mwe-math-element'); for (let i = 0; i < eqs.length; i++) { eqs[i].onclick = copyTex; eqs[i].addEventListener('animationend', this.clearAnimation); eqs[i].title = '点击即可复制公式'; } } const targetNode = document.getElementsByTagName('article')[0]; const config = { attributes: false, childList: true, subtree: true }; const observer = new MutationObserver(check_equations); observer.observe(targetNode, config); } } const DEFAULT_COPY = true if (host.search('zhihu.com') >= 0||host.search('blog.csdn') >= 0||host.search('wikipedia') >= 0||host.search('wikiwand') >= 0) { // 默认复制到剪贴板 const DEFAULT_COPY = window.confirm('是否默认复制到剪贴板?'); // 网址包含 zhihu.com 的页面 if (host.search('zhihu.com') >= 0) { new zhihuLaTeXFormulaCopier(); } // 网址包含 csdn.net 的页面 else if (host.search('blog.csdn') >= 0) { new csdnKatexFormulaCopier(); } else if (host.search('wikipedia') >= 0 || host.search('wikiwand') >= 0) { new WikiTeXFormulaCopier(); } } })();